Skip to main content
Glama
README.md
# Unlimited-OCR MCP Server

MCP (Model Context Protocol) Server and Tool definitions for [Unlimited-OCR](https://github.com/baidu/Unlimited-OCR) — enables Agent frameworks (LangChain, DuMate, AutoGPT, CrewAI, etc.) to invoke OCR as a structured tool.

## Features

- **MCP Server** — exposes OCR capabilities via the Model Context Protocol (stdio & SSE transport)
- **OpenAI-compatible Tool Definitions** — JSON schemas for function calling
- **Dual Backend** — supports both local Transformers inference and remote vLLM/SGLang HTTP API
- **Three OCR Modes** — single image (`gundam` / `base`), multi-image, and PDF
- **Full Parameter Coverage** — `crop_mode`, `ngram`, `max_length`, `dpi`, etc.

## Quick Start

### Install

```bash
pip install -e ".[all]"
# Or minimal install (HTTP backend only):
pip install -e ".[pdf]"
```

### Start MCP Server

#### Option 1: HTTP backend (vLLM / SGLang server)

```bash
# Start an SGLang/vLLM server first
python -m sglang.launch_server \
    --model baidu/Unlimited-OCR \
    --served-model-name Unlimited-OCR \
    --port 10000 ...

# Then start the MCP server
UNLIMITED_OCR_BACKEND=http \
UNLIMITED_OCR_SERVER_URL=http://127.0.0.1:10000 \
python -m mcp.server
```

#### Option 2: Transformers backend (local GPU)

```bash
UNLIMITED_OCR_BACKEND=transformers \
UNLIMITED_OCR_MODEL=baidu/Unlimited-OCR \
python -m mcp.server
```

#### Option 3: SSE transport (for remote agents)

```bash
UNLIMITED_OCR_BACKEND=http \
python -m mcp.server --transport sse --port 8080
```

### Configure in Agent Frameworks

#### Claude Desktop / MCP Client

Add to your MCP client config:

```json
{
  "mcpServers": {
    "unlimited-ocr": {
      "command": "python",
      "args": ["-m", "mcp.server"],
      "env": {
        "UNLIMITED_OCR_BACKEND": "http",
        "UNLIMITED_OCR_SERVER_URL": "http://127.0.0.1:10000"
      }
    }
  }
}
```

#### LangChain (direct tool call)

```python
from skill.tool_definitions import call_tool

# Direct call — no LLM orchestrator needed
result = call_tool("ocr_parse_image", {
    "image_path": "document.jpg",
    "image_mode": "gundam",
})
print(result["text"])
```

#### LangChain (LLM tool calling)

```python
from skill.tool_definitions import get_openai_tools
from mcp.ocr_engine import OCREngine

tools = get_openai_tools()
llm_with_tools = llm.bind_tools(tools)

# The LLM decides when to call OCR
response = llm_with_tools.invoke("Parse the document at document.jpg")
```

See `examples/langchain_integration.py` for a complete example.

## Available Tools

### `ocr_parse_image`

Parse a single image using Unlimited-OCR.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `image_path` | string | *required* | Path to the image file |
| `image_mode` | `gundam` \| `base` | `gundam` | Image processing mode |
| `output_dir` | string | — | Directory to save results |
| `no_repeat_ngram_size` | int | 35 | N-gram repetition penalty |
| `ngram_window` | int | 128 | N-gram window size |
| `max_length` | int | 32768 | Max output token length |

**Image modes:**
- `gundam` (default): `base_size=1024`, `image_size=640`, `crop_mode=True` — recommended for most images
- `base`: `base_size=1024`, `image_size=1024`, `crop_mode=False` — full image processing

### `ocr_parse_multi`

Parse multiple images (multi-page). Always uses `base` mode.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `image_paths` | string[] | *required* | List of image paths |
| `output_dir` | string | — | Directory to save results |
| `no_repeat_ngram_size` | int | 35 | N-gram repetition penalty |
| `ngram_window` | int | 1024 | N-gram window size |
| `max_length` | int | 32768 | Max output token length |

### `ocr_parse_pdf`

Parse a PDF document (auto-converts pages to images, then multi-page OCR).

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `pdf_path` | string | *required* | Path to the PDF file |
| `dpi` | int | 300 | DPI for PDF-to-image conversion |
| `output_dir` | string | — | Directory to save results |
| `no_repeat_ngram_size` | int | 35 | N-gram repetition penalty |
| `ngram_window` | int | 1024 | N-gram window size |
| `max_length` | int | 32768 | Max output token length |

## Configuration

Environment variables:

| Variable | Default | Description |
|----------|---------|-------------|
| `UNLIMITED_OCR_BACKEND` | `transformers` | Backend: `transformers` or `http` |
| `UNLIMITED_OCR_MODEL` | `baidu/Unlimited-OCR` | Model name or path |
| `UNLIMITED_OCR_SERVER_URL` | `http://127.0.0.1:10000` | vLLM/SGLang server URL |
| `UNLIMITED_OCR_TORCH_DTYPE` | `bfloat16` | Torch dtype (transformers only) |
| `UNLIMITED_OCR_DEVICE` | `cuda` | Device (transformers only) |

## Project Structure

```
unlimited-ocr-mcp/
├── mcp/                         # MCP Server
│   ├── __init__.py
│   ├── ocr_engine.py           # OCR engine (Transformers + HTTP backends)
│   ├── server.py                # MCP Server (stdio + SSE transport)
│   └── pdf_utils.py             # PDF to image conversion
├── skill/                       # Skill / Tool definitions
│   ├── _meta.json               # Skill metadata
│   ├── SKILL.md                 # Skill definition (name, description, instructions)
│   ├── skill-card.md            # Skill card (publisher, use case, risks)
│   ├── tool_definitions.py      # OpenAI-compatible tool definitions (Python)
│   └── openai_tools.json        # Standalone tool schema (JSON)
├── examples/
│   ├── langchain_integration.py
│   └── mcp_client_example.py
├── pyproject.toml
├── requirements.txt
├── LICENSE
└── README.md
```

## Requirements

- Python >= 3.10
- **MCP backend**: `mcp` SDK >= 1.0.0
- **Transformers backend**: `torch`, `transformers`, `Pillow`, `einops`, `addict`, `easydict`
- **HTTP backend**: `requests` (vLLM or SGLang server running separately)
- **PDF support**: `pymupdf` >= 1.23.0

## Related

- [Unlimited-OCR](https://github.com/baidu/Unlimited-OCR) — the upstream OCR model
- [MCP Specification](https://modelcontextprotocol.io/) — Model Context Protocol docs
- [Feature Request Issue #97](https://github.com/baidu/Unlimited-OCR/issues/97) — the original proposal

## License

Apache License 2.0

TDQS

B3.3/5.0

Scored across 3 tools

Disambiguation5/5

Each tool targets a distinct input type: a single image, multiple images, or a PDF. The descriptions make the boundaries clear, so an agent can select the correct tool without confusion.

Naming Consistency5/5

All tools follow the consistent 'ocr_parse_<input>' pattern using snake_case. The naming is predictable and immediately communicates each tool's purpose.

Tool Count5/5

Three tools is a well-scoped size for an OCR-focused server, covering the main input types without unnecessary bloat.

Completeness5/5

The tool surface covers the core OCR workflows: single images, multi-image batches, and PDFs. There are no obvious missing operations for the stated purpose.

Maintenance

ActivityMaintained
ResponsivenessNo issues