mathpix-mcp

A Model Context Protocol server for Mathpix OCR, over stdio or Streamable HTTP (bearer-token auth). It exposes Mathpix conversion as MCP tools so an LLM/agent can turn images and PDF/DOCX/PPTX documents into LaTeX and Markdown.

Tools

Tool Purpose
convert_document_tool PDF/DOCX/PPTX → Markdown/LaTeX/HTML (URL or local path). Saves output to a file and returns a path + preview so it doesn't overflow the model context.
convert_image_tool Image → LaTeX/text/MathML/etc. Result is written to a file (path + preview returned).
convert_strokes_tool Handwritten strokes → LaTeX/text.
batch_convert_tool Multiple images, optionally concurrent (parallel, max_parallel).
check_document_status_tool Poll an async document conversion.
search_results_tool Search recent captures; full content (when requested) is written to files.
get_usage_tool / get_account_info_tool Usage statistics and account identifiers.
list_formats_tool List supported output formats.

OCR results (LaTeX/text/MathML/etc.) are always written to files rather than returned inline; tools return a file path, a short preview, and metadata. The destination follows the tool's output_path/output_dir argument, else MATHPIX_OUTPUT_DIR, else the system temp dir.

Requirements

  • Ruby >= 3.2 (CI runs 3.3 and 3.4)
  • Mathpix API credentials (MATHPIX_APP_ID, MATHPIX_APP_KEY)

Install

From RubyGems (provides the mathpix-mcp / mathpix-mcp-http executables):

gem install mathpix-mcp

Or straight from GitHub (in a Gemfile):

gem 'mathpix-mcp', git: 'https://github.com/georgedouzas/mathpix-mcp'

Or build locally from a clone:

gem build mathpix-mcp.gemspec
gem install ./mathpix-mcp-*.gem

Or run from a clone with Bundler:

bundle install
cp .env.example .env                 # add your MATHPIX_APP_ID / MATHPIX_APP_KEY

Configuration

All configuration is via environment variables (loaded from .env when launched from the project directory, or from the process environment). Copy .env.example to .env as a starting point.

Variable Required Default Description
MATHPIX_APP_ID yes Mathpix application id.
MATHPIX_APP_KEY yes Mathpix application key.
MATHPIX_OUTPUT_DIR no system temp dir Where OCR results are written when a tool isn't given an explicit output_path/output_dir.
MATHPIX_MAX_FILE_SIZE_MB no 10 Maximum local file size accepted for upload.
MATHPIX_HTTPS_ONLY no true Upgrade/enforce HTTPS for remote sources.
MATHPIX_API_URL no https://api.mathpix.com/v3 Mathpix API base URL.
MATHPIX_TIMEOUT no 30 Per-request timeout in seconds (1–300).
MATHPIX_LOG_LEVEL no (off) Log verbosity to stderr: DEBUG/INFO/WARN/ERROR.
MATHPIX_MCP_TOKEN HTTP only Bearer token required by the HTTP transport.
MATHPIX_MCP_HOST no 127.0.0.1 HTTP bind host.
MATHPIX_MCP_PORT no 3000 HTTP bind port.

Run (stdio)

mathpix-mcp            # if installed as a gem
# or
bundle exec mathpix-mcp

It speaks MCP over stdio. Credentials are read from .env (when launched from the project directory) or the process environment.

Run (HTTP / Streamable HTTP)

The HTTP transport requires a bearer token (MATHPIX_MCP_TOKEN) — every request must send Authorization: Bearer <token>. It binds to 127.0.0.1:3000 by default (MATHPIX_MCP_HOST / MATHPIX_MCP_PORT).

export MATHPIX_MCP_TOKEN=$(openssl rand -hex 32)
mathpix-mcp-http                 # if installed as a gem
# or
bundle exec mathpix-mcp-http
# or, with a Rack server of your choice:
bundle exec puma config.ru -b tcp://127.0.0.1:3000

Example request:

curl -s http://127.0.0.1:3000/ \
  -H "Authorization: Bearer $MATHPIX_MCP_TOKEN" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'

Don't expose it on a public interface without a TLS-terminating reverse proxy.

Connect an agent

This server speaks MCP over stdio (mathpix-mcp) and Streamable HTTP (mathpix-mcp-http, bearer-token auth). Replace credentials with your own and prefer a real secret for MATHPIX_MCP_TOKEN (e.g. openssl rand -hex 32). Config schemas vary slightly between client versions — check your client's docs if a key is rejected. Examples assume the gem is installed (mathpix-mcp on PATH); to run from a clone, use bundle as the command with args: ["exec", "mathpix-mcp"] and set BUNDLE_GEMFILE to the project's Gemfile.

Claude Code (CLI)

stdio — keep secrets in the project .env and let the launcher cd in:

claude mcp add mathpix -- \
  bash -lc 'cd /path/to/mathpix-mcp && exec bundle exec mathpix-mcp'

or, if installed as a gem, pass creds inline:

claude mcp add mathpix -e MATHPIX_APP_ID=... -e MATHPIX_APP_KEY=... -- mathpix-mcp

HTTP — point at a running mathpix-mcp-http:

claude mcp add --transport http mathpix http://127.0.0.1:3000/ \
  --header "Authorization: Bearer $MATHPIX_MCP_TOKEN"

List/verify: claude mcp list.

Claude Desktop

Edit the config file (macOS: ~/Library/Application Support/Claude/claude_desktop_config.json, Windows: %APPDATA%\Claude\claude_desktop_config.json):

{
  "mcpServers": {
    "mathpix": {
      "command": "mathpix-mcp",
      "env": { "MATHPIX_APP_ID": "your_app_id", "MATHPIX_APP_KEY": "your_app_key" }
    }
  }
}

Claude Desktop talks to local servers over stdio, so for HTTP bridge with mcp-remote:

{
  "mcpServers": {
    "mathpix": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "http://127.0.0.1:3000/",
               "--header", "Authorization: Bearer YOUR_TOKEN"]
    }
  }
}

Restart Claude Desktop after editing.

Codex (OpenAI Codex CLI)

Edit ~/.codex/config.toml:

[mcp_servers.mathpix]
command = "mathpix-mcp"
env = { MATHPIX_APP_ID = "your_app_id", MATHPIX_APP_KEY = "your_app_key" }

For HTTP, bridge with mcp-remote:

[mcp_servers.mathpix]
command = "npx"
args = ["-y", "mcp-remote", "http://127.0.0.1:3000/", "--header", "Authorization: Bearer YOUR_TOKEN"]
Cursor

Edit ~/.cursor/mcp.json (global) or .cursor/mcp.json (project).

{
  "mcpServers": {
    "mathpix": {
      "command": "mathpix-mcp",
      "env": { "MATHPIX_APP_ID": "your_app_id", "MATHPIX_APP_KEY": "your_app_key" }
    }
  }
}

HTTP (Cursor supports remote URLs with headers):

{
  "mcpServers": {
    "mathpix": {
      "url": "http://127.0.0.1:3000/",
      "headers": { "Authorization": "Bearer YOUR_TOKEN" }
    }
  }
}
Gemini CLI

Edit ~/.gemini/settings.json:

{
  "mcpServers": {
    "mathpix": {
      "command": "mathpix-mcp",
      "env": { "MATHPIX_APP_ID": "your_app_id", "MATHPIX_APP_KEY": "your_app_key" }
    }
  }
}

HTTP (Gemini CLI uses httpUrl for Streamable HTTP; url for SSE):

{
  "mcpServers": {
    "mathpix": {
      "httpUrl": "http://127.0.0.1:3000/",
      "headers": { "Authorization": "Bearer YOUR_TOKEN" }
    }
  }
}
VS Code (GitHub Copilot, agent mode)

Create .vscode/mcp.json in the workspace (top-level key is servers):

{
  "servers": {
    "mathpix": {
      "type": "stdio",
      "command": "mathpix-mcp",
      "env": { "MATHPIX_APP_ID": "your_app_id", "MATHPIX_APP_KEY": "your_app_key" }
    }
  }
}

HTTP — use "type": "http", "url": "http://127.0.0.1:3000/", and a headers object with the bearer token.

Windsurf

Edit ~/.codeium/windsurf/mcp_config.json:

{
  "mcpServers": {
    "mathpix": {
      "command": "mathpix-mcp",
      "env": { "MATHPIX_APP_ID": "your_app_id", "MATHPIX_APP_KEY": "your_app_key" }
    }
  }
}

HTTP uses serverUrl: { "mcpServers": { "mathpix": { "serverUrl": "http://127.0.0.1:3000/" } } }. If your version can't attach the bearer header, use the mcp-remote bridge as the command.

Zed

Edit settings.json (Cmd/Ctrl+,) under context_servers:

{
  "context_servers": {
    "mathpix": {
      "command": {
        "path": "mathpix-mcp",
        "args": [],
        "env": { "MATHPIX_APP_ID": "your_app_id", "MATHPIX_APP_KEY": "your_app_key" }
      }
    }
  }
}
Continue, Cline, Goose

Continue (~/.continue/config.yaml):

mcpServers:
  - name: Mathpix
    command: mathpix-mcp
    env:
      MATHPIX_APP_ID: your_app_id
      MATHPIX_APP_KEY: your_app_key

Cline (MCP Servers panel → "Configure MCP Servers" → cline_mcp_settings.json): same mcpServers JSON shape as Cursor.

Goose (~/.config/goose/config.yaml):

extensions:
  mathpix:
    enabled: true
    type: stdio
    cmd: mathpix-mcp
    args: []
    envs:
      MATHPIX_APP_ID: your_app_id
      MATHPIX_APP_KEY: your_app_key
Programmatic (agent SDKs) & any other client

For HTTP, point any MCP-capable SDK at http://<host>:3000/ with an Authorization: Bearer <token> header — e.g. the Anthropic Claude Agent SDK MCP connector, the OpenAI Agents SDK (MCPServerStreamableHttp), or LangChain's MCP adapters. For stdio, spawn mathpix-mcp with MATHPIX_APP_ID / MATHPIX_APP_KEY in its environment.

Most clients use one of two shapes: stdio (command + args + env) or HTTP (a URL field — url/httpUrl/serverUrl, name varies — plus headers). If a stdio-only client can't reach the HTTP server, bridge with mcp-remote:

npx -y mcp-remote http://127.0.0.1:3000/ --header "Authorization: Bearer YOUR_TOKEN"

Deploy (HTTP)

Production deployment — TLS reverse proxy (Caddy/nginx), systemd, Docker / docker-compose, and the security checklist — is in docs/DEPLOYMENT.md. A Dockerfile is included:

docker build -t mathpix-mcp .
docker run --rm -p 3000:3000 \
  -e MATHPIX_APP_ID=... -e MATHPIX_APP_KEY=... \
  -e MATHPIX_MCP_TOKEN=$(openssl rand -hex 32) mathpix-mcp

Notes

  • If Mathpix's backend rejects a malformed PDF (e.g. a pdftoppm crash), the tool returns a descriptive error; repairing the PDF first (gs -o fixed.pdf -sDEVICE=pdfwrite in.pdf) usually resolves it.

License

MIT — see LICENSE.