Skip to main content
Glama

pdf-triage-mcp

npm CI MCP Registry License: MIT

An MCP server that lets any AI tool read local PDFs — without uploading them, without an OCR bill, and without silently handing back garbage.

Built on @firecrawl/pdf-inspector (Rust, no ML models, no external services).

┌─ pdf_classify ──→  text_based · 0.98 · 12 pages · 0 need OCR   ~20ms
├─ pdf_search  ──→  "invoice total" found on p4, p9              ~150ms
├─ pdf_extract ──→  clean Markdown, truncated to your budget     ~150ms
└─ pdf_tables  ──→  just the pipe tables, no prose               ~150ms

Table of contents


Related MCP server: PDF Reader MCP Server

Why this exists

Most PDF tooling has the same failure mode: it returns confident text regardless of whether extraction actually worked. Broken CID fonts, substitution-cipher encodings, scanned pages with no text layer — you get plausible-looking output and find out downstream, if at all.

pdf-inspector is unusually good at knowing when it failed. It emits U+FFFD rather than guessing at an unmapped CID, runs substitution-cipher detection over its own output, and reclassifies a document as scanned when extracted text drops below 50% alphanumeric. But it stops at reporting those findings on a result object — and most wrappers throw them away.

This server acts on them. Every response carries the trust signals, above the content, where the model reads them first:

> [!WARNING] ENCODING ISSUES DETECTED. The text layer decoded to suspicious
> output — typically a garbled CID font or a substitution-cipher encoding
> where letter frequencies match natural language but the letters themselves
> are wrong. Treat all extracted text here as unreliable and prefer OCR.

---

# Quarterly Report
...

Three design rules follow:

  1. Classify before extracting. pdf_classify costs ~20ms and tells you whether extraction is worth attempting at all.

  2. Bound every output. A 300-page PDF is easily 500k tokens. Everything truncates by default and tells you how to page through instead.

  3. Confine every path. A model that has just read an untrusted document must not be talkable into reading ~/.ssh/id_rsa. Enforced in code, not left to the model's judgement.


Install

Nothing to install. Every config below runs the published package straight from npm:

npx -y pdf-triage-mcp --root /path/to/your/documents

Your MCP client runs that for you — you only need to paste the config. Confirm it works first:

npx -y pdf-triage-mcp --version

Requires Node 20+. Available on npm as pdf-triage-mcp and in the MCP Registry as io.github.vishalmeena2211/pdf-triage-mcp.

git clone https://github.com/vishalmeena2211/pdf-triage-mcp.git
cd pdf-triage-mcp
npm install
npm run build
node dist/index.js --root ~/Documents

Then substitute "command": "node", "args": ["/absolute/path/to/dist/index.js", ...] for the npx invocation in any config below.


Connect it to your AI tool

Every config below is complete as written except for one value:

  • /Users/me/Documents — replace with the directory the server may read. This is the only thing you must change.

Use an absolute path; ~ is not expanded by most clients. Repeat --root for multiple directories.

PATH gotcha, applies to every GUI client below. Desktop apps launch servers with a minimal environment, so bare npx often fails to resolve even though it works in your terminal. If the server won't start, substitute the absolute path — find it with which npx (commonly /opt/homebrew/bin/npx on Apple Silicon, /usr/local/bin/npx on Intel macOS).

Why -y? It skips npx's install confirmation prompt. Without it, a first run can hang waiting for input that an MCP client cannot provide — the server appears to start and then silently times out.

Config file

OS

Path

macOS

~/Library/Application Support/Claude/claude_desktop_config.json

Windows

%APPDATA%\Claude\claude_desktop_config.json

Linux

~/.config/Claude/claude_desktop_config.json

{
  "mcpServers": {
    "pdf-triage": {
      "command": "npx",
      "args": [
        "-y", "pdf-triage-mcp",
        "--root", "/Users/me/Documents"
      ]
    }
  }
}

Verify: Fully quit and relaunch Claude Desktop (not just close the window). A tools icon appears near the chat input — click it and confirm the four pdf_* tools are listed.

Logs: ~/Library/Logs/Claude/mcp*.log (macOS), %APPDATA%\Claude\logs\mcp*.log (Windows).

Docs

CLI — the easiest route. The -- separator is mandatory; everything after it is the server command.

# Just you, this project (default)
claude mcp add pdf-triage -- npx -y pdf-triage-mcp --root /Users/me/Documents

# Just you, every project
claude mcp add --scope user pdf-triage -- npx -y pdf-triage-mcp --root /Users/me/Documents

# Shared with your team, writes .mcp.json to the repo
claude mcp add --scope project pdf-triage -- npx -y pdf-triage-mcp --root /Users/me/Documents

Or edit .mcp.json at the project root directly:

{
  "mcpServers": {
    "pdf-triage": {
      "type": "stdio",
      "command": "npx",
      "args": [
        "-y", "pdf-triage-mcp",
        "--root", "/Users/me/Documents"
      ]
    }
  }
}

Scope

Stored in

Shared

local (default)

~/.claude.json, under this project

No

user

~/.claude.json, top level

No

project

.mcp.json in repo root

Yes, via git

Verify: claude mcp list → look for ✔ Connected. Project-scoped servers need approval on first use — run /mcp inside a session.

Docs

Config file: .cursor/mcp.json (project) or ~/.cursor/mcp.json (global). Project wins on conflict.

{
  "mcpServers": {
    "pdf-triage": {
      "command": "npx",
      "args": [
        "-y", "pdf-triage-mcp",
        "--root", "/Users/me/Documents"
      ]
    }
  }
}

Verify: Cursor hot-reloads — no restart. Open Cursor Settings → Tools & MCP and look for a green dot next to pdf-triage.

Docs

Config file: ~/.codeium/windsurf/mcp_config.json (macOS/Linux), %USERPROFILE%\.codeium\windsurf\mcp_config.json (Windows).

Not created on first launch — create it yourself if missing.

{
  "mcpServers": {
    "pdf-triage": {
      "command": "npx",
      "args": [
        "-y", "pdf-triage-mcp",
        "--root", "/Users/me/Documents"
      ]
    }
  }
}

Verify: Windsurf watches the file and hot-reloads on save. Tools appear in Cascade on the next chat session.

Docs

The key is servers, not mcpServers. This is the most common mistake when copying a config from Claude Desktop.

Config file: .vscode/mcp.json (workspace), or Command Palette → MCP: Open User Configuration (global).

{
  "servers": {
    "pdf-triage": {
      "type": "stdio",
      "command": "npx",
      "args": [
        "-y", "pdf-triage-mcp",
        "--root", "/Users/me/Documents"
      ]
    }
  }
}

CLI alternative:

code --add-mcp '{"name":"pdf-triage","command":"npx","args":["-y","pdf-triage-mcp","--root","/Users/me/Documents"]}'

Verify: MCP tools only work in Agent mode — switch from Ask/Edit to Agent in Copilot Chat, then click Configure Tools and confirm the pdf_* tools appear. Restart VS Code after first adding the file.

Docs

The key is context_servers, not mcpServers, and command is a nested object rather than a string.

Config file: ~/.config/zed/settings.json (macOS/Linux), %APPDATA%\Zed\settings.json (Windows). Command Palette → zed: open settings.

{
  "context_servers": {
    "pdf-triage": {
      "source": "custom",
      "command": {
        "path": "npx",
        "args": [
          "-y", "pdf-triage-mcp",
          "--root", "/Users/me/Documents"
        ],
        "env": {}
      }
    }
  }
}

If your Zed version rejects that, it predates the nested form — try command, args and env flat at the top level of the server object instead.

Verify: Agent Panel (Cmd+Shift+A) → gear icon → MCP Servers. Green dot means connected.

Docs

Config file — separate from VS Code's own:

OS

Path

macOS

~/Library/Application Support/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json

Windows

%APPDATA%\Code\User\globalStorage\saoudrizwan.claude-dev\settings\cline_mcp_settings.json

Linux

~/.config/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json

{
  "mcpServers": {
    "pdf-triage": {
      "command": "npx",
      "args": [
        "-y", "pdf-triage-mcp",
        "--root", "/Users/me/Documents"
      ],
      "disabled": false,
      "autoApprove": ["pdf_classify", "pdf_search"]
    }
  }
}

autoApprove runs the listed read-only tools without a confirmation prompt.

Easier route: Cline panel → MCP servers icon → Edit MCP Settings opens this file directly.

Verify: Panel refreshes automatically; green dot next to the server.

Docs

Config file: ~/.continue/config.yaml (global) or .continue/config.yaml (project). YAML is current; config.json is deprecated.

mcpServers here is a list, not an object — and YAML needs spaces, never tabs.

mcpServers:
  - name: pdf-triage
    command: npx
    args:
      - -y
      - pdf-triage-mcp
      - --root
      - /Users/me/Documents

Verify: Reloads automatically on save. Switch Continue to Agent mode — MCP tools are unavailable in other modes.

Docs

CLI:

gemini mcp add pdf-triage npx -y pdf-triage-mcp --root /Users/me/Documents

# global instead of project-scoped
gemini mcp add --scope user pdf-triage npx -y pdf-triage-mcp --root /Users/me/Documents

Or edit ~/.gemini/settings.json (global) / .gemini/settings.json (project):

{
  "mcpServers": {
    "pdf-triage": {
      "command": "npx",
      "args": [
        "-y", "pdf-triage-mcp",
        "--root", "/Users/me/Documents"
      ],
      "timeout": 30000,
      "trust": false
    }
  }
}

Verify: Run /mcp inside a gemini session — servers show CONNECTED with their tool list. Or gemini mcp list from the shell.

Docs

Config file: ~/.codex/config.toml (global) or .codex/config.toml (project).

TOML, and the key is mcp_servers — snake_case, never mcpServers.

[mcp_servers.pdf-triage]
command = "npx"
args = [
  "-y", "pdf-triage-mcp",
  "--root", "/Users/me/Documents"
]
startup_timeout_sec = 20
tool_timeout_sec = 60

Verify: codex doctor --json validates the config syntax. Note that it validates syntax only — it does not confirm the server actually spawned.

Known upstream issue: several Codex CLI versions have a bug where stdio servers validate cleanly but silently fail to start, showing Tools: none in the TUI (#3441, #26810). That is a Codex runtime bug, not a config error.

Docs

AI Assistant — configured through the IDE, no file to edit:

  1. Settings → Tools → AI Assistant → Model Context Protocol (MCP)

  2. Add → transport STDIO

  3. Paste:

{
  "mcpServers": {
    "pdf-triage": {
      "command": "npx",
      "args": [
        "-y", "pdf-triage-mcp",
        "--root", "/Users/me/Documents"
      ]
    }
  }
}
  1. OK → Apply

Junie uses a file instead — ~/.junie/mcp/mcp.json (global) or .junie/mcp/mcp.json (project), same JSON shape.

Verify: Check the Status column in the MCP settings panel; click it to list the server's tools.

Docs

Config file: ~/.lmstudio/mcp.json (macOS/Linux), %USERPROFILE%\.lmstudio\mcp.json (Windows).

Easier via the app: right sidebar → Program tab → Install → Edit mcp.json.

{
  "mcpServers": {
    "pdf-triage": {
      "command": "npx",
      "args": [
        "-y", "pdf-triage-mcp",
        "--root", "/Users/me/Documents"
      ]
    }
  }
}

Verify: Auto-reloads on save; tools appear in the Program panel. LM Studio shows a confirmation dialog the first time a model calls a tool.

Docs

Cheat sheet

Client

File

Top-level key

Restart?

Claude Desktop

claude_desktop_config.json

mcpServers

Full quit

Claude Code

.mcp.json / CLI

mcpServers

No

Cursor

.cursor/mcp.json

mcpServers

No

Windsurf

~/.codeium/windsurf/mcp_config.json

mcpServers

No

VS Code Copilot

.vscode/mcp.json

servers

First time

Zed

~/.config/zed/settings.json

context_servers

No

Cline

cline_mcp_settings.json

mcpServers

No

Continue.dev

~/.continue/config.yaml

mcpServers (list)

No

Gemini CLI

~/.gemini/settings.json

mcpServers

No

Codex CLI

~/.codex/config.toml

[mcp_servers.*]

N/A

JetBrains

IDE settings UI

mcpServers

No

LM Studio

~/.lmstudio/mcp.json

mcpServers

No

The three that differ: VS Code (servers), Zed (context_servers + nested command), Codex (TOML mcp_servers). Everything else takes the Claude Desktop format verbatim.


Tools

Tool

Cost

Purpose

pdf_classify

~20ms

Type, confidence, page count, exact pages needing OCR. Call this first.

pdf_extract

~150ms

PDF → Markdown. Truncates by default; slice with pages.

pdf_search

~150ms

Locate text, return page-attributed snippets. Cheapest way into a long document.

pdf_tables

~150ms

Tables only, as Markdown pipe tables.

Full parameter reference: docs/TOOLS.md.

The intended flow on an unfamiliar document:

pdf_classify → is it text_based with no warnings?
  ├─ yes → pdf_search to locate → pdf_extract with `pages`
  └─ no  → stop; route to OCR

Configuration

pdf-triage-mcp [options]

  -r, --root <dir>          Directory the server may read. Repeatable. Default: cwd.
      --max-chars <n>       Default truncation ceiling. Default: 40000. Max: 200000.
      --max-file-bytes <n>  Largest PDF to read. Default: 104857600 (100 MB).
      --log-level <level>   debug | info | warn | error | silent. Default: info.
  -h, --help                Show usage.
  -v, --version             Print version.

Environment equivalents: PDF_TRIAGE_ROOTS (separated by the platform PATH delimiter — : on macOS/Linux, ; on Windows), PDF_TRIAGE_MAX_CHARS, PDF_TRIAGE_MAX_FILE_BYTES, PDF_TRIAGE_LOG_LEVEL. Flags win over environment.

Roots are a security boundary, not a convenience. Grant the narrowest directory that works. Paths are resolved through symlinks before checking, so a link inside a root pointing outside it is rejected rather than followed.


Engine fallback

Upstream ships prebuilt native binaries for exactly three targets: linux-x64-gnu, darwin-arm64, win32-x64-msvc. No musl build, no Linux ARM64 build (upstream #216) — so it fails to load on Alpine containers, Graviton instances, and most edge runtimes.

This server prefers native and falls back to WASM, which runs anywhere. Capability differences are surfaced, never faked:

Native

WASM

Classify / extract

Yes

Yes

Per-page extraction

Yes

No — throws, and pdf_search reports its matches are unattributed

pages selection

Yes

No — ignored, and the response says so

Check which engine you got: pdf_classify reports it, and the server logs engine selected at startup.


Known limitations

Inherited from upstream. Worth reading before you trust output:

  • RTL scripts are broken. Arabic and Hebrew return in visual order, reversed and unusable, while being reported as text_based with high confidence (#212). This server detects and escalates it — the one upstream failure mode we actively guard.

  • No xref recovery. Malformed PDFs that pypdf and pdfium silently repair will throw (#228).

  • Japanese CIDFontType0 (CFF) subset fonts can decode to unrelated glyphs (#208).

  • Multi-column reading order may emit in raster order on some layouts despite columns being detected (#219).

  • Images are not PDFs. A scanned JPEG has no text layer; the server rejects non-PDF input rather than pretending otherwise.


Development

npm run typecheck    # tsc --noEmit, maximum strictness
npm test             # vitest, 108 tests
npm run test:coverage
npm run build
npm run dev          # tsx, no build step

The TypeScript config runs every strictness flag including exactOptionalPropertyTypes and noUncheckedIndexedAccess. Upstream responses are validated with Zod at the boundary rather than cast — see docs/ARCHITECTURE.md for why.

Debug a client connection:

node dist/index.js --root ~/Documents --log-level debug

Troubleshooting: docs/TROUBLESHOOTING.md.


Roadmap

  • pdf_regions — bbox-scoped extraction for hybrid model pipelines

  • Positioned-item tool exposing {page, bbox} for visual citation UX

  • Integration tests asserting native and WASM produce identical normalized shapes

  • Optional OCR adapter interface, closing the routing loop end to end

License

MIT

Available Tools

4 tools
pdf_classifyClassify a PDFA

Triage a local PDF without extracting its text (typically 10-50ms). Returns whether the document is text-based, scanned, image-based or mixed, a confidence score, and the exact 1-indexed pages that need OCR. ALWAYS call this before pdf_extract on an unfamiliar or large document: it is cheap, and it tells you whether local extraction is worth attempting at all. If it reports scanned, image_based, or encoding issues, do not extract — route the document to an OCR service instead.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYesAbsolute path, or path relative to an allowed root, of a .pdf file

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does well by stating it does not extract text, returns specific categories and a confidence score, and is fast (10-50ms). It conveys that the tool performs triage without side effects, though it does not explicitly state 'read-only' or discuss error behavior. The decision guidance about OCR routing adds context beyond basic operation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise yet comprehensive, front-loading the primary purpose, then specifying return values, and finally providing actionable usage guidance. Every sentence adds value, and the entire description fits in three sentences without redundancy. It is well-structured with an imperative usage directive that is easy to follow.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Since there is no output schema, the description fully explains return values: document type, confidence score, and exact 1-indexed pages needing OCR. It also covers when to use the tool, what the outcome implies, and next steps. For a simple single-parameter tool with rich behavioral guidance, the description is complete and self-sufficient.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema provides 100% coverage with a detailed description of the 'path' parameter ('Absolute path, or path relative to an allowed root, of a .pdf file'). The tool description adds no additional parameter semantics, so a baseline score of 3 is appropriate. There is no further information about path handling beyond what the schema already states.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's function: 'Triage a local PDF without extracting its text' with specific outputs (classification, confidence, pages needing OCR). It distinguishes itself from siblings by emphasizing it does not extract text, unlike pdf_extract, and by specifying its classification purpose. The verb 'triage' precisely conveys the lightweight, pre-extraction role.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit usage guidance is provided: 'ALWAYS call this before pdf_extract on an unfamiliar or large document' and conditional routing: 'If it reports scanned, image_based, or encoding issues, do not extract — route the document to an OCR service instead.' This clearly indicates when to use the tool and when to avoid extraction, including alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

pdf_extractExtract PDF to MarkdownA

Extract a local PDF to Markdown, preserving headings, lists and tables. Output is TRUNCATED by default to protect your context window — to read a long document, call repeatedly with the pages parameter rather than raising maxChars. Call pdf_classify first on unfamiliar documents. If the response carries a critical warning (encoding issues, no text layer, right-to-left script), the text is unreliable and must not be quoted as fact.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYesAbsolute path, or path relative to an allowed root, of a .pdf file
pagesNo1-indexed page numbers to extract. Omit for the whole document. Prefer this over raising maxChars.
compactNoCollapse dot leaders and source padding for token efficiency. Defaults to true.
maxCharsNoTruncation ceiling. Defaults to the server setting (40000).

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations exist, so the description carries the full burden. It discloses default truncation to protect context window, explains the recommended pagination strategy, and warns about critical failure conditions (encoding issues, no text layer, right-to-left script) where output must not be quoted as fact. This is rich behavioral disclosure.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, each earning its place: the first states purpose, the second covers truncation and usage guidance, the third delivers warning/reliability information. It is front-loaded with the core action and contains no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite having no output schema or annotations, the description covers the essential aspects: output format (Markdown), truncation behavior, pagination strategy, warning handling, and prerequisite classification. It provides complete context for a 4-parameter extraction tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema covers 100% of parameters with detailed descriptions, earning a baseline of 3. The description adds practical value by specifically recommending pages over maxChars for long documents, clarifying the intended usage of these parameters beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's function: 'Extract a local PDF to Markdown' with specific preservation of headings, lists, and tables. This specific verb-resource-output combination distinguishes it from sibling tools like pdf_search and pdf_tables, which serve different purposes.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit guidance: 'Call pdf_classify first on unfamiliar documents' and advises using the pages parameter repeatedly rather than raising maxChars for long documents. This gives clear context and an explicit alternative workflow, exceeding basic requirements.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

pdf_tablesExtract tables from a PDFA

Return only the tables from a local PDF as Markdown, skipping prose. Useful for invoices, financial statements and reports where the numbers are the point. Tables are detected from the PDF's own drawing operations and text alignment — the cell values are read directly from the document, not guessed by a model or OCR.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYesAbsolute path, or path relative to an allowed root, of a .pdf file
pagesNo1-indexed pages to search for tables. Omit for the whole document.
maxCharsNoTruncation ceiling. Defaults to the server setting.

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It reveals the detection mechanism (PDF drawing operations and text alignment, not OCR/model guesswork) and clarifies the output is limited to tables. This adds meaningful context beyond a simple 'extract tables' statement, though it does not discuss error handling or performance limitations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is three focused sentences: the first states the core action, the second gives a use case, and the third explains the underlying method. Each sentence serves a distinct purpose, and there is no redundant information or filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with three parameters and no output schema, the description provides a complete picture: what it returns, how it works, and when to use it. The Markdown output format is clearly stated, and the method explanation (drawing operations/text alignment) addresses common concerns about accuracy.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema already provides 100% coverage for all three parameters, including descriptions for path, pages, and maxChars. The tool description does not add additional parameter-level detail, so it meets the baseline for schema-covered parameters without adding extra semantic value.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('Return only the tables') and clearly identifies both the resource (local PDF) and the output format (Markdown). It explicitly differentiates itself from sibling tools by emphasizing it skips prose and focuses on tables, which pdf_extract, pdf_search, and pdf_classify do not.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description states when to use this tool ('Useful for invoices, financial statements and reports where the numbers are the point'). It implies a clear use case for table-focused extraction, but does not explicitly mention when not to use it or name alternative tools for non-table extraction scenarios.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 4 tool updatesv0.1.2
    • First observedpdf_classify
    • First observedpdf_extract
    • First observedpdf_search
    • First observedpdf_tables

TDQS

A4.6/5.0

Scored across 4 tools

Disambiguation5/5

Each tool addresses a distinct task—classifying the PDF, extracting full text, searching for terms, and extracting tables. There is no overlap; even pdf_extract and pdf_tables differ in scope (full vs. tables only). An agent can confidently choose the right tool based on intent.

Naming Consistency4/5

All tools share the pdf_ prefix and use a verb or descriptive noun (classify, extract, search, tables). While 'tables' is a noun rather than a verb, the pattern is otherwise consistent and predictable.

Tool Count5/5

With four tools covering classification, extraction, search, and table extraction, the set is well-scoped for a PDF triage server. Each tool has a clear purpose without redundancy.

Completeness5/5

The toolset covers the full triage workflow: classify to decide if OCR is needed, extract to get full content, search to locate information, and tables for structured data. Missing functionality like OCR itself is deliberately outsourced, so the surface is complete for its intended domain.

Maintenance

ActivitySlowing
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    An MCP server that provides comprehensive PDF processing capabilities including text extraction, image extraction, table detection, annotation extraction, metadata retrieval, page rendering, and document structure analysis.
    -
  • A
    license
    A
    quality
    D
    maintenance
    An MCP server for local PDF manipulation including merging, splitting, rotating, watermarking, and text extraction. It works with various MCP-compatible clients and processes PDFs entirely on-device without cloud services.
    11
    8 npm
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    A local MCP server that extracts text-layer content from PDF files, enabling AI agents to inspect, extract text, outlines, and page content.
    -