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_dirargument, elseMATHPIX_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
pdftoppmcrash), 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.