Skip to main content
Glama
chupre
by chupre
README.md
# Yandex Vision OCR MCP

[![npm version](https://img.shields.io/npm/v/yandex-vision-ocr-mcp.svg)](https://www.npmjs.com/package/yandex-vision-ocr-mcp)
[![npm downloads](https://img.shields.io/npm/dt/yandex-vision-ocr-mcp.svg)](https://www.npmjs.com/package/yandex-vision-ocr-mcp)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![Node](https://img.shields.io/badge/node-%3E%3D20-brightgreen.svg)](https://nodejs.org)
[![Tests](https://img.shields.io/badge/tests-63%20passing-brightgreen.svg)](#testing)

A [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server that exposes
[Yandex Vision OCR](https://aistudio.yandex.ru/docs/ru/vision/concepts/ocr/) as tools,
so any MCP-compatible client — **opencode**, Claude Desktop, Cursor, Cline — can extract
text from images and PDFs.

## Features

- **`recognize_text`** — synchronous OCR for images (JPEG/PNG/WEBP/HEIC/HEIF) and single-page PDFs.
- **`recognize_pdf`** — asynchronous OCR for PDFs (single- or multi-page) and large files,
  via `recognizeTextAsync` + `getRecognition` polling.
- **Recognition models** — printed text, multi-column, **handwritten**, **tables**,
  **Markdown**, and **math formulas** (LaTeX), selectable per call.
- Accepts a **local file path** or raw **base64** content.
- Recognition languages selectable between `ru` and `en` (default `ru`; combine as
  `["ru","en"]` for mixed text). Auto-detect is **not** supported by this endpoint.
- Three output formats: `text` (default), `markdown`, or full `json` (the raw
  `textAnnotation` with blocks/lines/words/tables/entities).
- Zero-touch error handling — API failures are returned as `isError` tool results, never crashes.
- Lazy credentials — the server boots and lists tools even before `YANDEX_*` env vars are set,
  surfacing a clear error only on the first call.

## Prerequisites

1. **Node.js ≥ 20**.
2. A **Yandex Cloud** account with the Vision/OCR API enabled.
3. A **folder ID** + either an **API key** (recommended) or an **IAM token**.
   See the [authentication docs](https://aistudio.yandex.ru/docs/ru/vision/api-ref/authentication.html).

## Quick start

```bash
# Run directly with npx (no install needed)
npx -y yandex-vision-ocr-mcp
```

Then wire it into your MCP client (see [Configuration](#configuration)).

## Configuration

The server reads credentials from environment variables:

| Variable             | Required | Description                                                  |
| -------------------- | -------- | ------------------------------------------------------------ |
| `YANDEX_FOLDER_ID`   | optional | Yandex Cloud folder ID. Only sent as `x-folder-id` when set — the API key already scopes requests, so you can usually leave this unset. If set, it must match the key's folder. |
| `YANDEX_API_KEY`     | one of   | API key (recommended for long-lived usage).                  |
| `YANDEX_IAM_TOKEN`   | one of   | Short-lived IAM token (~12h). Use **instead of** an API key. |

See [`.env.example`](.env.example) for a template.

## Models

Pass `model` to any tool to pick the recognition behaviour:

| Model               | Best for                                                                 |
| ------------------- | ------------------------------------------------------------------------ |
| `page` *(default)*  | Single-column printed text.                                              |
| `page-column-sort`  | Multi-column printed text.                                               |
| `handwritten`       | Mixed handwritten + printed text (Russian, English).                     |
| `table`             | Tables (Russian, English).                                               |
| `markdown`          | Printed text, also returned as Markdown.                                 |
| `math-markdown`     | Math formulas, returned as Markdown with LaTeX (e.g. `$a^2 + b^2$`).     |

> Tip: use `format: "markdown"` together with the `markdown` / `math-markdown` models
> to receive the model's Markdown output directly.

## Tools

Both tools accept the same input shape:

| Argument     | Type                       | Default | Description                                                                 |
| ------------ | -------------------------- | ------- | --------------------------------------------------------------------------- |
| `path`       | string                     | —       | Local file to OCR. Provide this **or** `base64`.                            |
| `base64`     | string                     | —       | Base64 content (`data:` URIs accepted). Provide this **or** `path`.         |
| `mimeType`   | string                     | inferred | Explicit MIME type override.                                               |
| `languages`  | string[]                   | `["ru"]` | Recognition languages, selectable: `ru`, `en` (e.g. `["ru","en"]` for mixed). |
| `model`              | string                     | `page`  | Recognition model — see [Models](#models).                                 |
| `format`     | `text` \| `markdown` \| `json` | `text` | Output format.                                                             |

> **Supported formats:** JPEG, PNG, WEBP, HEIC, HEIF (images) and PDF.
> The `mimeType` sent to the API is derived automatically (you can pass a standard MIME
> type via `mimeType` if needed). BMP/TIFF are not supported by the service.

- **`recognize_text`** — synchronous. Best for images and single-page PDFs.
- **`recognize_pdf`** — asynchronous (submit + poll). Best for multi-page PDFs and large
  files. Requires the input to be a PDF.

### Example result (`text` format)

```text
Hello World
Yandex OCR
```

## Connect to opencode

Add the server to your `opencode.json` under `mcp`:

```jsonc
{
  "mcp": {
    "yandex-vision-ocr": {
      "type": "local",
      "command": ["npx", "-y", "yandex-vision-ocr-mcp@latest"],
      "enabled": true,
      "environment": {
        "YANDEX_FOLDER_ID": "b1g...",
        "YANDEX_API_KEY": "your-api-key"
      }
    }
  }
}
```

> If you cloned the repo instead, replace the `command` with
> `["node", "/absolute/path/to/yandex-vision-ocr-mcp/build/index.js"]`.

## Connect to Claude Desktop / Cursor / Cline

<details>
<summary>Claude Desktop — <code>claude_desktop_config.json</code></summary>

```jsonc
{
  "mcpServers": {
    "yandex-vision-ocr": {
      "command": "npx",
      "args": ["-y", "yandex-vision-ocr-mcp@latest"],
      "env": {
        "YANDEX_FOLDER_ID": "b1g...",
        "YANDEX_API_KEY": "your-api-key"
      }
    }
  }
}
```
</details>

<details>
<summary>Cursor — <code>.cursor/mcp.json</code></summary>

```jsonc
{
  "mcpServers": {
    "yandex-vision-ocr": {
      "command": "npx",
      "args": ["-y", "yandex-vision-ocr-mcp@latest"],
      "env": {
        "YANDEX_FOLDER_ID": "b1g...",
        "YANDEX_API_KEY": "your-api-key"
      }
    }
  }
}
```
</details>

## Local development

```bash
git clone https://github.com/chupre/yandex-vision-ocr-mcp.git
cd yandex-vision-ocr-mcp
npm install
npm run build      # type-check + compile to build/
npm test           # run the vitest suite
npm run dev        # run the server from source via tsx
npm run inspector  # open the MCP Inspector UI against the build
```

Useful scripts:

| Script              | Description                                  |
| ------------------- | -------------------------------------------- |
| `npm run build`     | Compile TypeScript to `build/`.              |
| `npm run typecheck` | Type-check without emitting.                 |
| `npm test`          | Run the offline test suite.                  |
| `npm run dev`       | Run the server from source (tsx).            |
| `npm run inspector` | Launch the MCP Inspector for manual testing. |

## Testing

The offline suite covers input handling, MIME inference, response formatting, the
HTTP client (via a fake transport, no network), tool wiring, and a full MCP
round-trip over an in-memory transport.

Live integration tests hit the real Yandex OCR API and are **skipped** unless
credentials and sample files are provided:

```bash
YANDEX_FOLDER_ID=... YANDEX_API_KEY=... \
YOCR_LIVE_IMAGE=./sample.png \
YOCR_LIVE_PDF=./sample.pdf \
npx vitest run tests/live.test.ts
```

## Docker

```bash
docker build -t yandex-vision-ocr-mcp .
docker run --rm -i \
  -e YANDEX_FOLDER_ID=b1g... \
  -e YANDEX_API_KEY=... \
  yandex-vision-ocr-mcp
```

## API coverage

This server targets the Yandex Cloud Vision OCR REST API
(`ocr.api.cloud.yandex.net/ocr/v1`):

| Route                  | Method | Used for                                  |
| ---------------------- | ------ | ----------------------------------------- |
| `/recognizeText`       | POST   | Synchronous recognition (`recognize_text`). |
| `/recognizeTextAsync`  | POST   | Start async recognition (`recognize_pdf`).  |
| `/getRecognition`      | GET    | Poll for the async result.                  |

Concepts: [OCR overview](https://aistudio.yandex.ru/docs/ru/vision/concepts/ocr/) ·
[image](https://aistudio.yandex.ru/docs/ru/vision/operations/ocr/text-detection-image.html) ·
[PDF](https://aistudio.yandex.ru/docs/ru/vision/operations/ocr/text-detection-pdf.html) ·
[handwritten](https://aistudio.yandex.ru/docs/ru/vision/operations/ocr/text-detection-handwritten.html).

## License

[MIT](LICENSE)

TDQS

A4.3/5.0

Scored across 2 tools

Disambiguation5/5

The two tools have clearly distinct purposes: one for images and single-page PDFs (synchronous), the other for multi-page/large PDFs (asynchronous). No overlap in functionality.

Naming Consistency4/5

Both tools follow the 'recognize_' prefix pattern with clear suffixes ('pdf' and 'text'), making them predictable and self-explanatory.

Tool Count4/5

Two tools is minimal but appropriate for a focused OCR server. It covers the core distinction between image/single-page and multi-page PDF processing without unnecessary complexity.

Completeness4/5

The tool surface covers the essential OCR use cases: image and PDF text recognition. The model parameter handles handwritten, table, and markdown, so no major gaps.

Maintenance

ActivityInactive
ResponsivenessNo issues