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
| Doc | Purpose |
|---|---|
| Strategic positioning | |
| Peer anchors and wedge | |
| Evidence = result contract | |
| Few clear tools policy | |
| This repo is SSOT | |
| Independent public product bar | |
| npm/git publish status |
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 |
See skills/citra/SKILL.md.
npm install -g @sylphx/pdf-reader-mcpOr pin the current release:
npm install -g @sylphx/pdf-reader-mcp@4.1.1One 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).
Claude Code
claude mcp add pdf-reader -- npx @sylphx/pdf-reader-mcpClaude 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-mcpCitra 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/sdk→Citra(read/search/evidence) - Export:
@sylphx/pdf-reader-mcp/pure-rust→createPureRustClient,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/citrapackage 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/guideMCP — see Quick start above (npx @sylphx/pdf-reader-mcp).
Independence:
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" }]
}- Financial reports — extract table cells agents can cite by page and geometry
- Research papers — headings, reading order, page-level quotes
- Scanned documents — OCR path with evidence, not a text soup
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:
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:
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
Before/after + flagship workflows Example demos
- Website / guide
Installation Comparison Migration / recovery (secondary)
MIT
If this saves your agents from PDF hallucinations, star the repo and share a demo with your team.