mathpix-mcp 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +44 -0
- data/LICENSE +22 -0
- data/README.md +403 -0
- data/bin/mathpix-mcp +46 -0
- data/bin/mathpix-mcp-http +39 -0
- data/config.ru +24 -0
- data/lib/mathpix/client.rb +534 -0
- data/lib/mathpix/configuration.rb +182 -0
- data/lib/mathpix/document.rb +345 -0
- data/lib/mathpix/errors.rb +78 -0
- data/lib/mathpix/mcp/base_tool.rb +225 -0
- data/lib/mathpix/mcp/http_app.rb +60 -0
- data/lib/mathpix/mcp/server.rb +124 -0
- data/lib/mathpix/mcp/tools/batch_convert_tool.rb +147 -0
- data/lib/mathpix/mcp/tools/check_document_status_tool.rb +70 -0
- data/lib/mathpix/mcp/tools/convert_document_tool.rb +176 -0
- data/lib/mathpix/mcp/tools/convert_image_tool.rb +108 -0
- data/lib/mathpix/mcp/tools/convert_strokes_tool.rb +97 -0
- data/lib/mathpix/mcp/tools/get_account_info_tool.rb +47 -0
- data/lib/mathpix/mcp/tools/get_usage_tool.rb +61 -0
- data/lib/mathpix/mcp/tools/list_formats_tool.rb +79 -0
- data/lib/mathpix/mcp/tools/search_results_tool.rb +116 -0
- data/lib/mathpix/mcp.rb +31 -0
- data/lib/mathpix/result.rb +387 -0
- data/lib/mathpix/version.rb +5 -0
- data/lib/mathpix.rb +52 -0
- metadata +132 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 4b82c966d9f5d395fd034f4c76fde15fe299dbf5a7f181e4134e23b7791b43fd
|
|
4
|
+
data.tar.gz: 7d83ad2772cc8f35c8e0ff522a5079fdbf633f3154194e5b942ebff026cfac3a
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 8ecbcc1d334fe67f92964cbe85228af711d018a31ab459d43383f23d0215c70f5e642a80a68d1f281a4b674b2f1bf8fd6e3354b7eb7e8bece97b81312d4c17c9
|
|
7
|
+
data.tar.gz: 33b669c9f84353b892a9293c2875bf7317e836b3382a80c5b742f70df9105f6f2c81763ea0505ef22c05adaa6a742af47de5f9495dff1dfc91b6d308821c1510
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [1.0.0] - 2026-06-29
|
|
11
|
+
|
|
12
|
+
First release: a Model Context Protocol server for Mathpix OCR over **stdio** and
|
|
13
|
+
**Streamable HTTP**, with every tool verified end-to-end against the live Mathpix
|
|
14
|
+
API.
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
- Nine MCP tools: `convert_document`, `convert_image`, `convert_strokes`,
|
|
18
|
+
`batch_convert`, `check_document_status`, `search_results`, `get_usage`,
|
|
19
|
+
`get_account_info`, `list_formats`.
|
|
20
|
+
- Document conversion (PDF/DOCX/PPTX) via `/v3/pdf` for remote URLs and local
|
|
21
|
+
files (multipart upload), returning Markdown/HTML.
|
|
22
|
+
- Image OCR via `/v3/text`, handwritten strokes via `/v3/strokes`, and recent
|
|
23
|
+
captures via `/v3/ocr-results`; usage/account identifiers via `/v3/ocr-usage`.
|
|
24
|
+
- File-routed output: OCR results (LaTeX/text/MathML/HTML/bounding-box data) are
|
|
25
|
+
always written to files and returned as a path + short preview + metadata, so
|
|
26
|
+
results never overflow the model context. Destination follows the tool's
|
|
27
|
+
`output_path`/`output_dir`, else `MATHPIX_OUTPUT_DIR`, else the system temp dir.
|
|
28
|
+
- Descriptive API errors that surface Mathpix's `error_info.message` (status and
|
|
29
|
+
details included).
|
|
30
|
+
- Concurrent `batch_convert` (bounded thread pool) and polling that tolerates all
|
|
31
|
+
intermediate Mathpix states.
|
|
32
|
+
- stdio transport (`mathpix-mcp`) and Streamable HTTP transport
|
|
33
|
+
(`mathpix-mcp-http` / `config.ru`) with required bearer-token auth
|
|
34
|
+
(`MATHPIX_MCP_TOKEN`).
|
|
35
|
+
- Configuration via environment variables (documented in the README and
|
|
36
|
+
`.env.example`), including `MATHPIX_OUTPUT_DIR` for the output directory.
|
|
37
|
+
- Docs: README with an env-var reference and per-agent client setup,
|
|
38
|
+
`docs/DEPLOYMENT.md` for HTTP deployment, `MAINTAINING.md` for release/admin,
|
|
39
|
+
and a `Dockerfile`.
|
|
40
|
+
- Tooling/CI: RuboCop + RSpec (`rake`), GitHub Actions CI (rubocop, rspec,
|
|
41
|
+
bundler-audit), Dependabot, and a trusted-publishing release workflow.
|
|
42
|
+
|
|
43
|
+
### Dependencies
|
|
44
|
+
- Runtime: `base64`, `mcp` (>= 0.9.2), `rack`, `puma` (>= 8.0.2).
|
data/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Barton Rhodes
|
|
4
|
+
Copyright (c) 2026 Georgios Douzas
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
# mathpix-mcp
|
|
2
|
+
|
|
3
|
+
A **Model Context Protocol server** for [Mathpix](https://mathpix.com) OCR, over
|
|
4
|
+
**stdio** or **Streamable HTTP** (bearer-token auth). It exposes Mathpix
|
|
5
|
+
conversion as MCP tools so an LLM/agent can turn images and PDF/DOCX/PPTX
|
|
6
|
+
documents into LaTeX and Markdown.
|
|
7
|
+
|
|
8
|
+
## Tools
|
|
9
|
+
|
|
10
|
+
| Tool | Purpose |
|
|
11
|
+
|------|---------|
|
|
12
|
+
| `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. |
|
|
13
|
+
| `convert_image_tool` | Image → LaTeX/text/MathML/etc. Result is written to a file (path + preview returned). |
|
|
14
|
+
| `convert_strokes_tool` | Handwritten strokes → LaTeX/text. |
|
|
15
|
+
| `batch_convert_tool` | Multiple images, optionally concurrent (`parallel`, `max_parallel`). |
|
|
16
|
+
| `check_document_status_tool` | Poll an async document conversion. |
|
|
17
|
+
| `search_results_tool` | Search recent captures; full content (when requested) is written to files. |
|
|
18
|
+
| `get_usage_tool` / `get_account_info_tool` | Usage statistics and account identifiers. |
|
|
19
|
+
| `list_formats_tool` | List supported output formats. |
|
|
20
|
+
|
|
21
|
+
> OCR results (LaTeX/text/MathML/etc.) are always written to files rather than
|
|
22
|
+
> returned inline; tools return a file path, a short preview, and metadata. The
|
|
23
|
+
> destination follows the tool's `output_path`/`output_dir` argument, else
|
|
24
|
+
> `MATHPIX_OUTPUT_DIR`, else the system temp dir.
|
|
25
|
+
|
|
26
|
+
## Requirements
|
|
27
|
+
|
|
28
|
+
- Ruby >= 3.2 (CI runs 3.3 and 3.4)
|
|
29
|
+
- Mathpix API credentials (`MATHPIX_APP_ID`, `MATHPIX_APP_KEY`)
|
|
30
|
+
|
|
31
|
+
## Install
|
|
32
|
+
|
|
33
|
+
From RubyGems (provides the `mathpix-mcp` / `mathpix-mcp-http` executables):
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
gem install mathpix-mcp
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Or straight from GitHub (in a Gemfile):
|
|
40
|
+
|
|
41
|
+
```ruby
|
|
42
|
+
gem 'mathpix-mcp', git: 'https://github.com/georgedouzas/mathpix-mcp'
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Or build locally from a clone:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
gem build mathpix-mcp.gemspec
|
|
49
|
+
gem install ./mathpix-mcp-*.gem
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Or run from a clone with Bundler:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
bundle install
|
|
56
|
+
cp .env.example .env # add your MATHPIX_APP_ID / MATHPIX_APP_KEY
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Configuration
|
|
60
|
+
|
|
61
|
+
All configuration is via environment variables (loaded from `.env` when launched
|
|
62
|
+
from the project directory, or from the process environment). Copy
|
|
63
|
+
[`.env.example`](.env.example) to `.env` as a starting point.
|
|
64
|
+
|
|
65
|
+
| Variable | Required | Default | Description |
|
|
66
|
+
|----------|----------|---------|-------------|
|
|
67
|
+
| `MATHPIX_APP_ID` | **yes** | — | Mathpix application id. |
|
|
68
|
+
| `MATHPIX_APP_KEY` | **yes** | — | Mathpix application key. |
|
|
69
|
+
| `MATHPIX_OUTPUT_DIR` | no | system temp dir | Where OCR results are written when a tool isn't given an explicit `output_path`/`output_dir`. |
|
|
70
|
+
| `MATHPIX_MAX_FILE_SIZE_MB` | no | `10` | Maximum local file size accepted for upload. |
|
|
71
|
+
| `MATHPIX_HTTPS_ONLY` | no | `true` | Upgrade/enforce HTTPS for remote sources. |
|
|
72
|
+
| `MATHPIX_API_URL` | no | `https://api.mathpix.com/v3` | Mathpix API base URL. |
|
|
73
|
+
| `MATHPIX_TIMEOUT` | no | `30` | Per-request timeout in seconds (1–300). |
|
|
74
|
+
| `MATHPIX_LOG_LEVEL` | no | _(off)_ | Log verbosity to stderr: `DEBUG`/`INFO`/`WARN`/`ERROR`. |
|
|
75
|
+
| `MATHPIX_MCP_TOKEN` | HTTP only | — | Bearer token required by the HTTP transport. |
|
|
76
|
+
| `MATHPIX_MCP_HOST` | no | `127.0.0.1` | HTTP bind host. |
|
|
77
|
+
| `MATHPIX_MCP_PORT` | no | `3000` | HTTP bind port. |
|
|
78
|
+
|
|
79
|
+
## Run (stdio)
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
mathpix-mcp # if installed as a gem
|
|
83
|
+
# or
|
|
84
|
+
bundle exec mathpix-mcp
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
It speaks MCP over stdio. Credentials are read from `.env` (when launched from
|
|
88
|
+
the project directory) or the process environment.
|
|
89
|
+
|
|
90
|
+
## Run (HTTP / Streamable HTTP)
|
|
91
|
+
|
|
92
|
+
The HTTP transport requires a bearer token (`MATHPIX_MCP_TOKEN`) — every request
|
|
93
|
+
must send `Authorization: Bearer <token>`. It binds to `127.0.0.1:3000` by
|
|
94
|
+
default (`MATHPIX_MCP_HOST` / `MATHPIX_MCP_PORT`).
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
export MATHPIX_MCP_TOKEN=$(openssl rand -hex 32)
|
|
98
|
+
mathpix-mcp-http # if installed as a gem
|
|
99
|
+
# or
|
|
100
|
+
bundle exec mathpix-mcp-http
|
|
101
|
+
# or, with a Rack server of your choice:
|
|
102
|
+
bundle exec puma config.ru -b tcp://127.0.0.1:3000
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Example request:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
curl -s http://127.0.0.1:3000/ \
|
|
109
|
+
-H "Authorization: Bearer $MATHPIX_MCP_TOKEN" \
|
|
110
|
+
-H 'Content-Type: application/json' \
|
|
111
|
+
-H 'Accept: application/json, text/event-stream' \
|
|
112
|
+
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Don't expose it on a public interface without a TLS-terminating reverse proxy.
|
|
116
|
+
|
|
117
|
+
## Connect an agent
|
|
118
|
+
|
|
119
|
+
This server speaks MCP over **stdio** (`mathpix-mcp`) and **Streamable HTTP**
|
|
120
|
+
(`mathpix-mcp-http`, bearer-token auth). Replace credentials with your own and
|
|
121
|
+
prefer a real secret for `MATHPIX_MCP_TOKEN` (e.g. `openssl rand -hex 32`).
|
|
122
|
+
Config schemas vary slightly between client versions — check your client's docs
|
|
123
|
+
if a key is rejected. Examples assume the gem is installed (`mathpix-mcp` on
|
|
124
|
+
`PATH`); to run from a clone, use `bundle` as the command with
|
|
125
|
+
`args: ["exec", "mathpix-mcp"]` and set `BUNDLE_GEMFILE` to the project's
|
|
126
|
+
`Gemfile`.
|
|
127
|
+
|
|
128
|
+
### Claude Code (CLI)
|
|
129
|
+
|
|
130
|
+
**stdio** — keep secrets in the project `.env` and let the launcher `cd` in:
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
claude mcp add mathpix -- \
|
|
134
|
+
bash -lc 'cd /path/to/mathpix-mcp && exec bundle exec mathpix-mcp'
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
or, if installed as a gem, pass creds inline:
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
claude mcp add mathpix -e MATHPIX_APP_ID=... -e MATHPIX_APP_KEY=... -- mathpix-mcp
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
**HTTP** — point at a running `mathpix-mcp-http`:
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
claude mcp add --transport http mathpix http://127.0.0.1:3000/ \
|
|
147
|
+
--header "Authorization: Bearer $MATHPIX_MCP_TOKEN"
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
List/verify: `claude mcp list`.
|
|
151
|
+
|
|
152
|
+
<details>
|
|
153
|
+
<summary><b>Claude Desktop</b></summary>
|
|
154
|
+
|
|
155
|
+
Edit the config file (macOS:
|
|
156
|
+
`~/Library/Application Support/Claude/claude_desktop_config.json`, Windows:
|
|
157
|
+
`%APPDATA%\Claude\claude_desktop_config.json`):
|
|
158
|
+
|
|
159
|
+
```json
|
|
160
|
+
{
|
|
161
|
+
"mcpServers": {
|
|
162
|
+
"mathpix": {
|
|
163
|
+
"command": "mathpix-mcp",
|
|
164
|
+
"env": { "MATHPIX_APP_ID": "your_app_id", "MATHPIX_APP_KEY": "your_app_key" }
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Claude Desktop talks to local servers over stdio, so for HTTP bridge with
|
|
171
|
+
[`mcp-remote`](https://www.npmjs.com/package/mcp-remote):
|
|
172
|
+
|
|
173
|
+
```json
|
|
174
|
+
{
|
|
175
|
+
"mcpServers": {
|
|
176
|
+
"mathpix": {
|
|
177
|
+
"command": "npx",
|
|
178
|
+
"args": ["-y", "mcp-remote", "http://127.0.0.1:3000/",
|
|
179
|
+
"--header", "Authorization: Bearer YOUR_TOKEN"]
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Restart Claude Desktop after editing.
|
|
186
|
+
</details>
|
|
187
|
+
|
|
188
|
+
<details>
|
|
189
|
+
<summary><b>Codex (OpenAI Codex CLI)</b></summary>
|
|
190
|
+
|
|
191
|
+
Edit `~/.codex/config.toml`:
|
|
192
|
+
|
|
193
|
+
```toml
|
|
194
|
+
[mcp_servers.mathpix]
|
|
195
|
+
command = "mathpix-mcp"
|
|
196
|
+
env = { MATHPIX_APP_ID = "your_app_id", MATHPIX_APP_KEY = "your_app_key" }
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
For HTTP, bridge with `mcp-remote`:
|
|
200
|
+
|
|
201
|
+
```toml
|
|
202
|
+
[mcp_servers.mathpix]
|
|
203
|
+
command = "npx"
|
|
204
|
+
args = ["-y", "mcp-remote", "http://127.0.0.1:3000/", "--header", "Authorization: Bearer YOUR_TOKEN"]
|
|
205
|
+
```
|
|
206
|
+
</details>
|
|
207
|
+
|
|
208
|
+
<details>
|
|
209
|
+
<summary><b>Cursor</b></summary>
|
|
210
|
+
|
|
211
|
+
Edit `~/.cursor/mcp.json` (global) or `.cursor/mcp.json` (project).
|
|
212
|
+
|
|
213
|
+
```json
|
|
214
|
+
{
|
|
215
|
+
"mcpServers": {
|
|
216
|
+
"mathpix": {
|
|
217
|
+
"command": "mathpix-mcp",
|
|
218
|
+
"env": { "MATHPIX_APP_ID": "your_app_id", "MATHPIX_APP_KEY": "your_app_key" }
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
HTTP (Cursor supports remote URLs with headers):
|
|
225
|
+
|
|
226
|
+
```json
|
|
227
|
+
{
|
|
228
|
+
"mcpServers": {
|
|
229
|
+
"mathpix": {
|
|
230
|
+
"url": "http://127.0.0.1:3000/",
|
|
231
|
+
"headers": { "Authorization": "Bearer YOUR_TOKEN" }
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
```
|
|
236
|
+
</details>
|
|
237
|
+
|
|
238
|
+
<details>
|
|
239
|
+
<summary><b>Gemini CLI</b></summary>
|
|
240
|
+
|
|
241
|
+
Edit `~/.gemini/settings.json`:
|
|
242
|
+
|
|
243
|
+
```json
|
|
244
|
+
{
|
|
245
|
+
"mcpServers": {
|
|
246
|
+
"mathpix": {
|
|
247
|
+
"command": "mathpix-mcp",
|
|
248
|
+
"env": { "MATHPIX_APP_ID": "your_app_id", "MATHPIX_APP_KEY": "your_app_key" }
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
HTTP (Gemini CLI uses `httpUrl` for Streamable HTTP; `url` for SSE):
|
|
255
|
+
|
|
256
|
+
```json
|
|
257
|
+
{
|
|
258
|
+
"mcpServers": {
|
|
259
|
+
"mathpix": {
|
|
260
|
+
"httpUrl": "http://127.0.0.1:3000/",
|
|
261
|
+
"headers": { "Authorization": "Bearer YOUR_TOKEN" }
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
```
|
|
266
|
+
</details>
|
|
267
|
+
|
|
268
|
+
<details>
|
|
269
|
+
<summary><b>VS Code (GitHub Copilot, agent mode)</b></summary>
|
|
270
|
+
|
|
271
|
+
Create `.vscode/mcp.json` in the workspace (top-level key is `servers`):
|
|
272
|
+
|
|
273
|
+
```json
|
|
274
|
+
{
|
|
275
|
+
"servers": {
|
|
276
|
+
"mathpix": {
|
|
277
|
+
"type": "stdio",
|
|
278
|
+
"command": "mathpix-mcp",
|
|
279
|
+
"env": { "MATHPIX_APP_ID": "your_app_id", "MATHPIX_APP_KEY": "your_app_key" }
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
HTTP — use `"type": "http"`, `"url": "http://127.0.0.1:3000/"`, and a `headers`
|
|
286
|
+
object with the bearer token.
|
|
287
|
+
</details>
|
|
288
|
+
|
|
289
|
+
<details>
|
|
290
|
+
<summary><b>Windsurf</b></summary>
|
|
291
|
+
|
|
292
|
+
Edit `~/.codeium/windsurf/mcp_config.json`:
|
|
293
|
+
|
|
294
|
+
```json
|
|
295
|
+
{
|
|
296
|
+
"mcpServers": {
|
|
297
|
+
"mathpix": {
|
|
298
|
+
"command": "mathpix-mcp",
|
|
299
|
+
"env": { "MATHPIX_APP_ID": "your_app_id", "MATHPIX_APP_KEY": "your_app_key" }
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
HTTP uses `serverUrl`:
|
|
306
|
+
`{ "mcpServers": { "mathpix": { "serverUrl": "http://127.0.0.1:3000/" } } }`. If
|
|
307
|
+
your version can't attach the bearer header, use the `mcp-remote` bridge as the
|
|
308
|
+
`command`.
|
|
309
|
+
</details>
|
|
310
|
+
|
|
311
|
+
<details>
|
|
312
|
+
<summary><b>Zed</b></summary>
|
|
313
|
+
|
|
314
|
+
Edit `settings.json` (`Cmd/Ctrl+,`) under `context_servers`:
|
|
315
|
+
|
|
316
|
+
```json
|
|
317
|
+
{
|
|
318
|
+
"context_servers": {
|
|
319
|
+
"mathpix": {
|
|
320
|
+
"command": {
|
|
321
|
+
"path": "mathpix-mcp",
|
|
322
|
+
"args": [],
|
|
323
|
+
"env": { "MATHPIX_APP_ID": "your_app_id", "MATHPIX_APP_KEY": "your_app_key" }
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
```
|
|
329
|
+
</details>
|
|
330
|
+
|
|
331
|
+
<details>
|
|
332
|
+
<summary><b>Continue, Cline, Goose</b></summary>
|
|
333
|
+
|
|
334
|
+
**Continue** (`~/.continue/config.yaml`):
|
|
335
|
+
|
|
336
|
+
```yaml
|
|
337
|
+
mcpServers:
|
|
338
|
+
- name: Mathpix
|
|
339
|
+
command: mathpix-mcp
|
|
340
|
+
env:
|
|
341
|
+
MATHPIX_APP_ID: your_app_id
|
|
342
|
+
MATHPIX_APP_KEY: your_app_key
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
**Cline** (MCP Servers panel → "Configure MCP Servers" →
|
|
346
|
+
`cline_mcp_settings.json`): same `mcpServers` JSON shape as Cursor.
|
|
347
|
+
|
|
348
|
+
**Goose** (`~/.config/goose/config.yaml`):
|
|
349
|
+
|
|
350
|
+
```yaml
|
|
351
|
+
extensions:
|
|
352
|
+
mathpix:
|
|
353
|
+
enabled: true
|
|
354
|
+
type: stdio
|
|
355
|
+
cmd: mathpix-mcp
|
|
356
|
+
args: []
|
|
357
|
+
envs:
|
|
358
|
+
MATHPIX_APP_ID: your_app_id
|
|
359
|
+
MATHPIX_APP_KEY: your_app_key
|
|
360
|
+
```
|
|
361
|
+
</details>
|
|
362
|
+
|
|
363
|
+
<details>
|
|
364
|
+
<summary><b>Programmatic (agent SDKs) & any other client</b></summary>
|
|
365
|
+
|
|
366
|
+
For HTTP, point any MCP-capable SDK at `http://<host>:3000/` with an
|
|
367
|
+
`Authorization: Bearer <token>` header — e.g. the Anthropic Claude Agent SDK MCP
|
|
368
|
+
connector, the OpenAI Agents SDK (`MCPServerStreamableHttp`), or LangChain's MCP
|
|
369
|
+
adapters. For stdio, spawn `mathpix-mcp` with `MATHPIX_APP_ID` /
|
|
370
|
+
`MATHPIX_APP_KEY` in its environment.
|
|
371
|
+
|
|
372
|
+
Most clients use one of two shapes: **stdio** (`command` + `args` + `env`) or
|
|
373
|
+
**HTTP** (a URL field — `url`/`httpUrl`/`serverUrl`, name varies — plus
|
|
374
|
+
`headers`). If a stdio-only client can't reach the HTTP server, bridge with
|
|
375
|
+
[`mcp-remote`](https://www.npmjs.com/package/mcp-remote):
|
|
376
|
+
|
|
377
|
+
```bash
|
|
378
|
+
npx -y mcp-remote http://127.0.0.1:3000/ --header "Authorization: Bearer YOUR_TOKEN"
|
|
379
|
+
```
|
|
380
|
+
</details>
|
|
381
|
+
|
|
382
|
+
## Deploy (HTTP)
|
|
383
|
+
|
|
384
|
+
Production deployment — TLS reverse proxy (Caddy/nginx), systemd, Docker /
|
|
385
|
+
docker-compose, and the security checklist — is in
|
|
386
|
+
**[docs/DEPLOYMENT.md](docs/DEPLOYMENT.md)**. A `Dockerfile` is included:
|
|
387
|
+
|
|
388
|
+
```bash
|
|
389
|
+
docker build -t mathpix-mcp .
|
|
390
|
+
docker run --rm -p 3000:3000 \
|
|
391
|
+
-e MATHPIX_APP_ID=... -e MATHPIX_APP_KEY=... \
|
|
392
|
+
-e MATHPIX_MCP_TOKEN=$(openssl rand -hex 32) mathpix-mcp
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
## Notes
|
|
396
|
+
|
|
397
|
+
- If Mathpix's backend rejects a malformed PDF (e.g. a `pdftoppm` crash), the
|
|
398
|
+
tool returns a descriptive error; repairing the PDF first
|
|
399
|
+
(`gs -o fixed.pdf -sDEVICE=pdfwrite in.pdf`) usually resolves it.
|
|
400
|
+
|
|
401
|
+
## License
|
|
402
|
+
|
|
403
|
+
MIT — see [LICENSE](LICENSE).
|
data/bin/mathpix-mcp
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require 'bundler/setup'
|
|
5
|
+
|
|
6
|
+
# Load environment variables from a .env file if one is present (no-op if the
|
|
7
|
+
# dotenv gem or file is missing). Done before configuring Mathpix so MATHPIX_*
|
|
8
|
+
# from .env are available.
|
|
9
|
+
begin
|
|
10
|
+
require 'dotenv/load'
|
|
11
|
+
rescue LoadError
|
|
12
|
+
# dotenv not installed — rely on the process environment
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
require 'mathpix'
|
|
16
|
+
require 'mathpix/mcp'
|
|
17
|
+
|
|
18
|
+
# Configure Mathpix from environment
|
|
19
|
+
Mathpix.configure do |config|
|
|
20
|
+
config.app_id = ENV.fetch('MATHPIX_APP_ID', nil)
|
|
21
|
+
config.app_key = ENV.fetch('MATHPIX_APP_KEY', nil)
|
|
22
|
+
|
|
23
|
+
# Optional configuration
|
|
24
|
+
config.max_file_size_mb = ENV['MATHPIX_MAX_FILE_SIZE_MB']&.to_i || 10
|
|
25
|
+
config.enforce_https = ENV['MATHPIX_HTTPS_ONLY'] != 'false'
|
|
26
|
+
|
|
27
|
+
# Logging
|
|
28
|
+
if ENV['MATHPIX_LOG_LEVEL']
|
|
29
|
+
require 'logger'
|
|
30
|
+
config.logger = Logger.new($stderr)
|
|
31
|
+
config.logger.level = Logger.const_get(ENV['MATHPIX_LOG_LEVEL'].upcase)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Start MCP server on stdio.
|
|
36
|
+
#
|
|
37
|
+
# The Server constructor wires up all 9 tools internally
|
|
38
|
+
# (see Mathpix::MCP::Server#tool_classes), so we just
|
|
39
|
+
# build it and run the stdio transport.
|
|
40
|
+
begin
|
|
41
|
+
Mathpix::MCP::Server.run
|
|
42
|
+
rescue StandardError => e
|
|
43
|
+
warn "Error starting Mathpix MCP server: #{e.message}"
|
|
44
|
+
warn e.backtrace.join("\n")
|
|
45
|
+
exit 1
|
|
46
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require 'bundler/setup'
|
|
5
|
+
|
|
6
|
+
# Load environment (incl. MATHPIX_* and MATHPIX_MCP_TOKEN) from .env if present.
|
|
7
|
+
begin
|
|
8
|
+
require 'dotenv/load'
|
|
9
|
+
rescue LoadError
|
|
10
|
+
# dotenv not installed — rely on the process environment
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
require 'mathpix'
|
|
14
|
+
require 'mathpix/mcp'
|
|
15
|
+
require 'mathpix/mcp/http_app'
|
|
16
|
+
|
|
17
|
+
Mathpix.configure do |config|
|
|
18
|
+
config.app_id = ENV.fetch('MATHPIX_APP_ID', nil)
|
|
19
|
+
config.app_key = ENV.fetch('MATHPIX_APP_KEY', nil)
|
|
20
|
+
config.max_file_size_mb = ENV['MATHPIX_MAX_FILE_SIZE_MB']&.to_i || 10
|
|
21
|
+
config.enforce_https = ENV['MATHPIX_HTTPS_ONLY'] != 'false'
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
app = Mathpix::MCP::HttpApp.build
|
|
25
|
+
host = ENV.fetch('MATHPIX_MCP_HOST', '127.0.0.1')
|
|
26
|
+
port = Integer(ENV.fetch('MATHPIX_MCP_PORT', '3000'))
|
|
27
|
+
|
|
28
|
+
require 'puma'
|
|
29
|
+
require 'puma/configuration'
|
|
30
|
+
require 'puma/launcher'
|
|
31
|
+
|
|
32
|
+
configuration = Puma::Configuration.new do |c|
|
|
33
|
+
c.app(app)
|
|
34
|
+
c.bind("tcp://#{host}:#{port}")
|
|
35
|
+
c.log_requests(false)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
warn "Mathpix MCP (Streamable HTTP) listening on http://#{host}:#{port}"
|
|
39
|
+
Puma::Launcher.new(configuration).run
|
data/config.ru
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Rack entrypoint for the Mathpix MCP Streamable HTTP transport.
|
|
4
|
+
# Run with: bundle exec puma config.ru -b tcp://127.0.0.1:3000
|
|
5
|
+
#
|
|
6
|
+
# Requires MATHPIX_APP_ID, MATHPIX_APP_KEY and MATHPIX_MCP_TOKEN in the
|
|
7
|
+
# environment (or a local .env).
|
|
8
|
+
|
|
9
|
+
begin
|
|
10
|
+
require 'dotenv/load'
|
|
11
|
+
rescue LoadError
|
|
12
|
+
nil
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
require 'mathpix'
|
|
16
|
+
require 'mathpix/mcp'
|
|
17
|
+
require 'mathpix/mcp/http_app'
|
|
18
|
+
|
|
19
|
+
Mathpix.configure do |config|
|
|
20
|
+
config.app_id = ENV.fetch('MATHPIX_APP_ID', nil)
|
|
21
|
+
config.app_key = ENV.fetch('MATHPIX_APP_KEY', nil)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
run Mathpix::MCP::HttpApp.build
|