MCP Mistral OCR
README.md
# MCP Mistral OCR
[](https://smithery.ai/server/@everaldo/mcp-mistral-ocr)
An MCP server that provides OCR capabilities using Mistral AI's OCR API. Supports **stdio** (for Claude Desktop / Smithery) and **streamable HTTP** (for remote clients). Runs **with or without Docker**.
## Features
- **Dual transport**: streamable HTTP (default) or stdio for Claude Desktop / Smithery
- Process local files (images and PDFs) and files from URLs
- **Primary flow:** Call `process_url_file` with a URL to get OCR output (markdown or full JSON)
- No Docker required: run locally with `uv run` and optional `OCR_DIR`
- Results saved as timestamped `.json` (full Mistral response) and `.md` (extracted markdown) in `OCR_DIR/output/` (optional; set `OCR_SAVE_RESULTS=false` to disable). When saving is on, the tool returns **only** the download links (over HTTP) or file paths (over stdio): no full content in the response. Over streamable HTTP, use the returned URLs to download the JSON and Markdown files (e.g. `http://127.0.0.1:8000/output/<filename>.json`).
- Docker optional for deployment
## Usage
The main use case is **URL in, OCR out**. Call the `process_url_file` tool with a document or image URL. You can omit `file_type` if the URL has a `.pdf` or image extension (e.g. `.jpg`, `.png`). Use `output_format="markdown"` to get only the extracted text, or `output_format="full"` (default) for the full Mistral response JSON.
**Download URLs:** To get clickable "Download JSON" and "Download Markdown" URLs in the tool response, set `OCR_DOWNLOAD_BASE_URL` (e.g. in `.env`). Use a **different port** than the MCP server (e.g. 8001) so they don't conflict. **One-command start:** from the project root run `uv run python run_servers.py` to start both the file server (8001) and the MCP server (8000); Ctrl+C stops both.
**Google Drive:** View/share links (e.g. `https://drive.google.com/file/d/FILE_ID/view?usp=sharing`) are supported. The server rewrites them to the direct-download URL so the OCR API receives the file content. For Drive links, `file_type` can be omitted and defaults to `pdf`; for images in Drive, pass `file_type="image"`. URLs are trimmed before detection. **File type inference:** If the URL has no extension and is not a known Drive link, the server sends a HEAD request to the URL and infers type from the `Content-Type` header (e.g. `application/pdf` → pdf); if still unknown, it defaults to `pdf` so the first API call usually succeeds without requiring `file_type`.
## Environment Variables
| Variable | Required | Default | Description |
|----------|----------|---------|-------------|
| `MISTRAL_API_KEY` | Yes | — | Your Mistral AI API key |
| `OCR_DIR` | No | `./ocr_data` | Directory for local files and `output/` subdir |
| `OCR_SAVE_RESULTS` | No | `true` | Set to `false` to disable saving results to `OCR_DIR/output/` |
| `OCR_DOWNLOAD_BASE_URL` | No | — | Base URL for download links. Use a port other than MCP (e.g. `http://127.0.0.1:8001`). Run `python -m http.server 8001 --directory ocr_data` from project root so GET /output/<filename> serves the files. |
| `MCP_TRANSPORT` | No | `streamable-http` | `stdio` or `streamable-http` |
| `MCP_HTTP_HOST` | No | `127.0.0.1` | Bind host when using streamable HTTP |
| `MCP_HTTP_PORT` | No | `8000` | Port when using Streamable HTTP or SSE |
| `MCP_HTTP_PATH` | No | `mcp` | URL path (e.g. `/mcp` → `http://host:8000/mcp`) |
## Running without Docker
**Python:** This project uses **Python 3.10–3.13** (not 3.14+) so dependencies like `pydantic-core` use pre-built wheels. If you only have Python 3.14, install 3.12 (e.g. from [python.org](https://www.python.org/downloads/)) and run:
```bash
uv sync --python 3.12
```
### Stdio (e.g. Claude Desktop, Smithery)
1. Install [uv](https://docs.astral.sh/uv/) and run:
```bash
cd mistral-ocr-mcp
uv sync
```
2. Set `MISTRAL_API_KEY` and optionally `OCR_DIR` (defaults to `./ocr_data`).
3. Run the server (stdio):
```bash
# Windows (PowerShell)
$env:MISTRAL_API_KEY="your_key"
uv run python -m src.main
# Windows (CMD) / Unix
set MISTRAL_API_KEY=your_key # CMD
export MISTRAL_API_KEY=your_key # Bash
uv run python -m src.main
```
Or with a custom OCR directory:
```bash
export OCR_DIR=/path/to/your/files # or set on Windows
uv run python -m src.main
```
### Streamable HTTP (for MCP Inspector, HTTP clients)
Start the server with streamable HTTP:
```bash
export MISTRAL_API_KEY=your_key
export MCP_TRANSPORT=streamable-http
export MCP_HTTP_PORT=8000
uv run python -m src.main
```
Then connect clients to **http://127.0.0.1:8000/mcp** (Streamable HTTP; e.g. [MCP Inspector](https://github.com/modelcontextprotocol/inspector): `npx -y @modelcontextprotocol/inspector`).
Optional: bind all interfaces and custom path:
```bash
export MCP_TRANSPORT=streamable-http
export MCP_HTTP_HOST=0.0.0.0
export MCP_HTTP_PORT=8000
export MCP_HTTP_PATH=/mcp
uv run python -m src.main
```
## Claude Desktop configuration
### Option A: No Docker (stdio)
Point Claude to the project and use stdio:
```json
{
"mcpServers": {
"mistral-ocr": {
"command": "uv",
"args": ["run", "python", "-m", "src.main"],
"cwd": "C:\\path\\to\\mistral-ocr-mcp",
"env": {
"MISTRAL_API_KEY": "<YOUR_MISTRAL_API_KEY>",
"MCP_TRANSPORT": "stdio",
"OCR_DIR": "C:\\path\\to\\your\\files"
}
}
}
}
```
(Adjust `cwd` and `OCR_DIR` for your machine. Omit `OCR_DIR` to use default `./ocr_data`.)
### Option B: Docker (stdio)
```json
{
"mcpServers": {
"mistral-ocr": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-e",
"MISTRAL_API_KEY",
"-e",
"OCR_DIR",
"-v",
"C:/path/to/your/files:/data/ocr",
"mcp-mistral-ocr:latest"
],
"env": {
"MISTRAL_API_KEY": "<YOUR_MISTRAL_API_KEY>",
"OCR_DIR": "C:/path/to/your/files"
}
}
}
}
```
Build and run:
```bash
docker build -t mcp-mistral-ocr .
docker run -e MISTRAL_API_KEY=your_key -e OCR_DIR=/data/ocr -v C:/path/to/files:/data/ocr mcp-mistral-ocr
```
## Smithery
Install via [Smithery](https://smithery.ai/server/@everaldo/mcp-mistral-ocr) (stdio):
```bash
npx -y @smithery/cli install @everaldo/mcp/mistral-crosswalk --client claude
```
## Available tools
- **process_url_file(url, file_type=None, output_format="full", pages=None, table_format=None, extract_header=False, extract_footer=False)** – Primary tool: process a file from a URL. `file_type` is optional if the URL has a `.pdf` or image extension. `output_format`: `"full"` (default) returns full JSON; `"markdown"` returns only the extracted text. `pages`: optional list of 0-based page indices to process. `table_format`: `"markdown"` or `"html"` for tables. `extract_header` / `extract_footer`: set to `True` to extract header/footer.
- **process_local_file(filename, output_format="full", pages=None, table_format=None, extract_header=False, extract_footer=False)** – Process a file from `OCR_DIR` (e.g. `document.pdf`, `image.png`). Same optional parameters as above.
Limits: 50MB max file size, 1000 pages (Mistral API).
## Output
When `OCR_SAVE_RESULTS` is true (default), results are written to `OCR_DIR/output/` as JSON:
- Local: `{filename_stem}_{YYYYMMDD_HHMMSS}.json`
- URL: `{url_path_stem}_{timestamp}.json` or `url_document_{timestamp}.json`
Set `OCR_SAVE_RESULTS=false` to return OCR only to the client without writing files.
## Supported file types
- Images: JPG, JPEG, PNG, GIF, WebP
- Documents: PDF and other formats supported by Mistral OCR
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues