pdf-reader-mcp

MCP.Pizza Chef: SylphxAI

Now branded Citra, this pulls text, headings, tables, and images out of a PDF sitting on your own computer, and returns the page and position each answer came from so you can check it yourself. Scanned documents go through text recognition instead of coming back as noise. It can search a long document to find the right pages before reading them in full. Nothing is uploaded anywhere and no key is required. It works in Claude Desktop, Claude Code, Cursor, and VS Code.

Files/PDF
Web/Research

Use This MCP server To

Pull a number out of a financial report and see its page Search a long PDF for the pages that mention a topic Read a scanned contract that copy-paste turns into gibberish Get a table out of a report with its rows intact Quote a research paper and know exactly where the quote sits

README

Citra

Give your AI agent eyes for PDFs.

Citra is a local-first PDF evidence product for agents — fast, citeable, owned entirely in this repository.

Turn PDFs into structured text, tables, OCR, visual evidence, and page-level citations — locally — via SDK, CLI, or MCP.

Plain-text PDF tools make agents guess. Citra returns proof.
Package (transition): @sylphx/pdf-reader-mcp · bin pdf-reader-mcp

npm version License: MIT CI stars MCP Toplist

Product docs

Doc Purpose
docs/POSITIONING.md Strategic positioning
docs/COMPETITIVE.md Peer anchors and wedge
docs/EVIDENCE_CONTRACT.md Evidence = result contract
docs/TOOL_SURFACE.md Few clear tools policy
docs/PRODUCT_INDEPENDENCE.md This repo is SSOT
docs/IPPB.md Independent public product bar
docs/PUBLISH.md npm/git publish status

Why this exists

Plain text vs evidence

Most PDF tools dump text. Agents then invent page numbers, miss tables, and cite the wrong cell.

Citra returns an Agent Document Twin: markdown + structure + geometry + provenance your agent can actually trust.

Without evidence With Citra
“The revenue was about $12M” “Page 14, Table 3, cell (row 4, col 2) = $12.4M
Lost table structure Rows, columns, cells, bounding boxes
Scanned PDF becomes noise OCR path with page-linked evidence
Hidden text / prompt injection ignored Trust signals when requested

Agent skill surface

See skills/citra/SKILL.md.

Install (30 seconds)

npm install -g @sylphx/pdf-reader-mcp

Or pin the current release:

npm install -g @sylphx/pdf-reader-mcp@4.1.1

One native binary is installed for your platform only (not all five).

Platform Native package (auto optionalDependency)
macOS arm64 @sylphx/pdf-reader-mcp-darwin-arm64
macOS x64 @sylphx/pdf-reader-mcp-darwin-x64
Linux x64 @sylphx/pdf-reader-mcp-linux-x64-gnu
Linux arm64 @sylphx/pdf-reader-mcp-linux-arm64-gnu
Windows x64 @sylphx/pdf-reader-mcp-win32-x64-msvc

Missing native package → fail closed (no silent engine switch).

Quick start

Claude Code

claude mcp add pdf-reader -- npx @sylphx/pdf-reader-mcp

Claude Desktop / Codex / Cursor / VS Code / any MCP client

{
  "mcpServers": {
    "pdf-reader": {
      "command": "npx",
      "args": ["@sylphx/pdf-reader-mcp"]
    }
  }
}

Dual-era hosts that send server/discover before initialize (e.g. Gemini Antigravity CLI) are supported on stdio — the server answers discovery and keeps the session open for the legacy handshake.

Stdio / HTTP

pdf-reader-mcp
MCP_TRANSPORT=http pdf-reader-mcp

SDK (programmatic)

Citra is not MCP-only. Apps and internal dogfood can call the same engine without a chat client.

TypeScript — spawn the native server as a client

import { Citra } from '@sylphx/pdf-reader-mcp/sdk';

const citra = Citra.create();
const { payload, isError } = await citra.read({
  sources: [{ path: '/absolute/path/to/doc.pdf' }],
  // auto defaults on when you omit include_* flags
});
if (isError) throw new Error(JSON.stringify(payload));
console.log(payload);

Low-level escape hatch: @sylphx/pdf-reader-mcp/pure-rust (createPureRustClient).

  • Export: @sylphx/pdf-reader-mcp/sdkCitra (read / search / evidence)
  • Export: @sylphx/pdf-reader-mcp/pure-rustcreatePureRustClient, resolvePureRustServerBinary, PureRustClient
  • Tools (same as MCP): read_pdf · search_pdf · pdf_evidence
  • Requires the platform optional native package (same as MCP install)
  • Roadmap: idiomatic high-level @sylphx/citra package name + richer typed SDK; semantics stay isomorphic with CLI/MCP

CLI

npx pdf-reader-mcp --help   # transitional bin
# doctor / read paths: see package bin and docs/guide

MCP — see Quick start above (npx @sylphx/pdf-reader-mcp).

Independence: this product only. No central Instruments monorepo.

What you get

Three tools. One product surface.

Tool What agents use it for
read_pdf Smart default: markdown, tables, structure, OCR, citations
search_pdf Find page + snippet matches before deep reading
pdf_evidence Crops, renders, inspect, focused evidence ops

Minimal call:

{
  "sources": [{ "path": "/absolute/path/to/report.pdf" }]
}

Flagship use cases

  1. Financial reports — extract table cells agents can cite by page and geometry
  2. Research papers — headings, reading order, page-level quotes
  3. Scanned documents — OCR path with evidence, not a text soup

Install footprint (honest product comparison)

Compare full clean installs, not “JS wrapper tarball vs native executable”:

Metric (measured clean install, linux-x64) Historical TS 3.0.14 Sole-Rust 4.1.0
Main package on disk ~403 KB ~77 KB
Full node_modules ~82.3 MiB ~24.4 MiB (~3.4× smaller)
Installed files 4,101 20 (~205× fewer)
Production npm dependency graph PDF.js + MCP TS SDK + more {} + one platform native

The native binary is multi-megabyte because it is the PDF intelligence engine (parser, server, rendering/table/OCR routing). That is expected and still yields a cleaner, smaller install than shipping PDF.js + a JS dependency tree.

Details: installed footprint comparison

Performance

Controlled same-host linux-x64 dual-mode A/B vs @sylphx/pdf-reader-mcp@3.0.14, using registry-installed 4.1.x natives:

Mode What it measures Result
persistent_warm long-lived server, repeated identical local read_pdf after warm-up ≥ ~10× median latency improvement on all 8 required fixture classes
startup_inclusive spawn + initialize + one task large advantage on the same fixtures

persistent_warm includes a process-local cache for identical local path+options. First request in a process still pays full parse cost.

Also: install footprint is much smaller than TS 3.0.14 on measured linux-x64 (~3.4× less disk, ~205× fewer files), and the 4.1.0 native binary is smaller than 4.0.2 (strip/LTO).

Not a multi-host guarantee. Details: 4.1.0 report · claims policy

Engine note

Version 4 runs a native Rust engine on supported platforms via a thin Node launcher.

Local-first. Five platforms. One clean install.

Unusually formed or broken ToUnicode CMaps are handled without crashing, and the release binary is built panic-unwind so a worker-thread panic fails the affected request instead of aborting the whole process (#608).

Engineering history, recovery pins, and ADRs live under docs/migration.md — not the product pitch.

Product proof

  • Before/after + flagship workflows
  • Example demos

Docs

License

MIT


If this saves your agents from PDF hallucinations, star the repo and share a demo with your team.

pdf-reader-mcp FAQ

Does my PDF get uploaded somewhere?
No. It reads files on your own machine and does all the work there.
Do I need to pay for a key?
No key and no account. Installing it is the only step.
Can I use this to pull tables out of a report?
Yes. It keeps rows, columns, and cells separate, and tells you which page and which cell each figure came from.
Will it handle a scanned document?
Yes. Scanned pages go through text recognition, and the results still come back tied to a page rather than as one blur of text.
Which apps does it work in?
Claude Desktop, Claude Code, Cursor, VS Code, and other assistants that accept a short settings block.
How hard is setup?
You paste a two-line block into your assistant's settings, or run a single command in Claude Code.