Skip to main content
Glama
sandraschi

pdf-mcp

pdf-mcp

Full-stack PDF intelligence MCP server — extract, manipulate, annotate, convert, validate, and RAG-search PDFs through a unified tool surface and React workbench.

v0.2.1 · Ports 11130 (frontend) / 11131 (backend)

FastMCP 3.4.4 · PyMuPDF + pypdf + pdfplumber · LanceDB RAG · Prefab UI · dual transport (stdio + HTTP)

Features

  • pdf_extract — text, images, tables, metadata, fonts, links, outline

  • pdf_manipulate — merge, split, rotate, reorder, delete pages, compress, encrypt/decrypt, optimize

  • pdf_annotate — watermark, stamp, highlight, underline, header/footer, page numbers, auto summary box

  • pdf_forms — list / fill / flatten / export + LLM-guided auto-fill

  • pdf_convert — PDF ↔ Markdown / images / HTML

  • pdf_validate — PDF/A, structure, accessibility, integrity, compare

  • pdf_rag — chunk (table-aware), index (LanceDB), semantic search, query-by-example, cross-document synthesis

  • pdf_analyze / pdf_redact / pdf_classify / pdf_dedupe / pdf_export — intelligence tools

  • pdf_do — autonomous agent that chains the tools from natural language

  • pdf_help / pdf_status / pdf_shutdown — meta tools

Related MCP server: pdf-mcp

Quick start

git clone https://github.com/sandraschi/pdf-mcp
cd pdf-mcp
uv sync
Copy-Item .env.example .env
.\start.ps1

Dashboard: http://127.0.0.1:11130 · MCP/API: http://127.0.0.1:11131

Stack

  • Backend: Python 3.12, FastMCP 3.4.4, Starlette (HTTP), PyMuPDF, pypdf, pdfplumber, LanceDB, Prefab UI

  • Frontend: React 18, Vite 5, Tailwind CSS, Lucide, Framer Motion, Zustand, PDF.js, Playwright

  • Tooling: uv, bun, just, ruff, pyright, Biome, pre-commit

MCP tools

Tool

Operations

pdf_extract

text, images, tables, metadata, fonts, links, outline

pdf_manipulate

merge, split, rotate, reorder, delete_pages, compress, encrypt, decrypt, optimize

pdf_annotate

watermark, stamp, highlight, underline, header_footer, page_numbers, summary_box

pdf_forms

list_fields, fill, flatten, export_data, auto_fill

pdf_convert

to_markdown, to_images, to_html, from_html, from_markdown, from_images

pdf_validate

pdfa, structure, accessibility, integrity, compare

pdf_rag

chunk, index, search, similar, synthesize, list_documents, delete_index

pdf_analyze / pdf_redact / pdf_classify / pdf_dedupe / pdf_export

intelligence

pdf_do

agentic chaining

pdf_help / pdf_status / pdf_shutdown

meta

Claude Desktop config

{
  "mcpServers": {
    "pdf-mcp": {
      "command": "uv",
      "args": ["--directory", "D:\\Dev\\repos\\pdf-mcp", "run", "python", "run_server.py"]
    }
  }
}

For HTTP mode instead: uv run python run_server.py --mode http --port 11131 and connect over http://127.0.0.1:11131/mcp.

Configuration

See docs/CONFIGURATION.md. Key vars: MCP_MODE (stdio/http), MCP_PORT (11131), FRONTEND_PORT (11130), RAG_STORE_PATH, UPLOAD_DIR.

Webapp

Route

Page

/

Dashboard (KPIs, LLM availability, usage stats)

/workbench

PDF.js viewer + OCR badge + compare mode + tool palette

/pipeline

Single operations + multi-step recipes + share links

/chat

LLM chat with PDF search + source citations

/tools / /skills / /logs

Discovery & logs

Documentation

License

MIT

Available Tools

16 tools
pdf_analyzeB
Read-only

Detect whether a PDF has a text layer (digital) or is scanned, with layout stats.

Return Format

A dict with keys:

  • success: bool

  • pages: int

  • has_text_layer: bool - true when average chars per page >= 80

  • scanned: bool - low text + images present

  • chars_per_page: float

  • total_chars: int

  • image_count: int

  • layout_hint: str - digital | scanned | empty

  • per_page: list of {page, chars, images}

Examples

await pdf_analyze(path="scan.pdf") {"success": true, "pages": 5, "has_text_layer": false, "scanned": true, "chars_per_page": 12.4, "image_count": 5, "layout_hint": "scanned", "per_page": [...]}

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYesPath to the PDF file.

Output Schema

ParametersJSON Schema
NameRequiredDescription
messageNoHuman-readable summary
successNoWhether the operation succeeded

TDQS

B3.2/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true, so the safety profile is covered. The description does add real behavioral value by disclosing the detection heuristics (has_text_layer when avg chars/page >= 80; scanned when low text plus images), but it says nothing about auth needs, file-path constraints, or failure behavior for invalid PDFs.

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

Conciseness3/5

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

The opening sentence is front-loaded and tight, and the example is useful. However, the lengthy '## Return Format' block substantially duplicates the declared output schema, which is redundant length rather than earned content.

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

Completeness4/5

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

For a single-parameter, read-only diagnostic with an output schema and a worked example, an agent has everything needed to invoke it correctly. The only real gap is routing guidance against the many pdf_* siblings.

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?

Only one parameter (path), and schema description coverage is 100%, so the schema fully documents it. The description adds no syntax, path-format, or constraint detail for the parameter, making 3 the correct baseline.

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

Purpose4/5

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

States a specific verb and resource: detects whether a PDF has a text layer or is scanned, plus layout stats. This is clearly distinct from manipulation/export siblings, though it never names an alternative such as pdf_extract or pdf_classify to sharpen the boundary.

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

Usage Guidelines2/5

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

The description never says when to call this tool versus alternatives. Usage is only implied by the detection goal; there is no stated precondition (e.g. run before OCR/extraction) and no mention of siblings like pdf_extract or pdf_validate.

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

pdf_annotateA

Add annotations and markup to PDFs.

Watermark, stamp, highlight, underline, header/footer, and page numbers.

Return Format

A dict with keys:

  • success: bool - whether the operation succeeded

  • message: str - human-readable summary

  • operation-specific keys:

    • watermark/stamp/header_footer/page_numbers: {path}

    • highlight: {path, occurrences}

    • underline: {path, occurrences} On failure: {success: False, error, error_type}.

Examples

await pdf_annotate(operation="watermark", path="report.pdf", text="CONFIDENTIAL", opacity=0.3) {"success": true, "path": ".../report_watermark_....pdf", "message": "Added watermark to report.pdf, saved to report_watermark_....pdf."}

await pdf_annotate(operation="highlight", path="report.pdf", search_text="revenue") {"success": true, "path": ".../report_highlight_....pdf", "occurrences": 3, "message": "Highlighted 3 occurrences of 'revenue' in report.pdf."}

ParametersJSON Schema
NameRequiredDescriptionDefault
xNoX position for stamp annotation. Default 50.
yNoY position for stamp annotation. Default 50.
pageNoTarget page number (1-indexed). Applies to all pages if omitted.
pathYesPath to the PDF file.
textNoText content for watermark, stamp, header, or footer.
colorNoHighlight color as hex. Default #FFFF00.#FFFF00
startNoStarting page number. Default 1.
footerNoFooter text.
headerNoHeader text.
opacityNoOpacity for watermark. Default 0.3.
positionNoWatermark position: center, top_left, top_right, bottom_left, bottom_right, tile.center
font_sizeNoFont size for header/footer/page numbers. Default 10.
operationYes
image_pathNoPath to image file for image watermark.
output_pathNoOutput path. Auto-generated if omitted.
search_textNoText to search for highlighting or underlining.

Output Schema

ParametersJSON Schema
NameRequiredDescription
messageNoHuman-readable summary
successNoWhether the operation succeeded

TDQS

A3.8/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=false and openWorldHint=true, and the description goes beyond them by disclosing the auto-generated output path behavior (saving to report_watermark_...pdf), the success/error return shape, and occurrence counts for search-based operations. It does not address whether the original file is preserved or permission requirements.

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

Conciseness4/5

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

The description is front-loaded with purpose, then operations, return format, and examples using clear headings. The Return Format section partly duplicates the existing output schema, which is redundant, but the examples earn their space.

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

Completeness4/5

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

With 16 parameters and an output schema present, the description need not repeat return values, yet it does so. Its main gap is the operation-to-parameter contract: with seven enum operations sharing one flat parameter bag, the description only hints via examples which parameters apply to which operation.

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?

Schema coverage is 94%, so the baseline is 3, and the worked examples add genuine meaning by pairing specific operations with their relevant parameters (watermark with text/opacity, highlight with search_text). It still never states the mapping of which parameters are required or valid per operation.

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

Purpose4/5

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

The description states a specific verb and resource ('Add annotations and markup to PDFs') and enumerates the concrete operations (watermark, stamp, highlight, underline, header/footer, page numbers), which makes it distinguishable from content-removal siblings like pdf_redact. It stops short of naming a sibling it is not, so it does not reach the top of the scale.

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

Usage Guidelines3/5

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

Usage is only implied through the operation list and the two examples; there is no explicit statement of when to choose this tool over pdf_manipulate or pdf_redact, and no exclusions or prerequisites are given.

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

pdf_classifyB
Read-only

Guess the document type (invoice, report, contract, ...) and extract candidate fields.

Return Format

A dict with keys:

  • success: bool

  • doc_type: str

  • confidence: float (0-1)

  • fields: dict of detected fields (invoice_number, total, date, vendor)

  • reasons: list of matched signals

  • llm_refined: bool - whether the local LLM confirmed the guess

Examples

await pdf_classify(path="invoice_42.pdf") {"success": true, "doc_type": "invoice", "confidence": 0.75, "fields": {"invoice_number": "INV-42", "total": "1,240.00"}, "reasons": ["invoice(x2)"]}

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYesPath to the PDF file.
refineNoUse the local LLM to refine the guess. Default true.

Output Schema

ParametersJSON Schema
NameRequiredDescription
messageNoHuman-readable summary
successNoWhether the operation succeeded

TDQS

B3.2/5.0
Behavior3/5

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

The readOnlyHint annotation already establishes a safe read operation, so the bar is lower. The description adds useful behavioral context: it is a heuristic guess with a confidence score, optional local-LLM refinement, and matched reasons. It does not disclose cost/latency implications of the LLM refinement or processing limits.

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

Conciseness4/5

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

Purpose is front-loaded in one sentence, followed by a compact return-format block and a concrete example. The structure is efficient and example-driven, though the verbose return-key listing partially duplicates what the output schema already provides.

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

Completeness3/5

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

An output schema exists, so return values needn't be fully explained, yet the description is otherwise complete for invocation and interpretation. The notable gap is selection context: nothing tells the agent how this differs from sibling extraction/analysis tools.

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?

Schema coverage is 100%, so path and refine are already documented. The return-format section explains that llm_refined reflects the refine flag, which adds some cross-field meaning, but the description does not extend parameter semantics beyond the schema.

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

Purpose4/5

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

The description states a specific verb (classify/guess) and resource (document type) with concrete examples of types and extracted fields, so an agent understands the operation. It does not, however, differentiate itself from close siblings like pdf_extract or pdf_analyze, which also surface document fields.

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

Usage Guidelines2/5

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

There is no explicit when-to-use guidance or reference to alternatives. With siblings pdf_extract, pdf_analyze, and pdf_validate present, the agent gets no signal about when classification is preferable to generic extraction.

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

pdf_convertB

Convert between PDF and other formats.

PDF to/from Markdown, HTML, and images.

Return Format

A dict with keys:

  • success: bool - whether the operation succeeded

  • message: str - human-readable summary

  • operation-specific keys:

    • to_markdown: {markdown, pages}

    • to_images: {images: [{page, path, width, height}]}

    • to_html: {html}

    • from_html/from_markdown/from_images: {path, pages} On failure: {success: False, error, error_type}.

Examples

await pdf_convert(operation="to_markdown", path="report.pdf") {"success": true, "markdown": "# Report...", "pages": 3, "message": "Converted report.pdf to markdown (3 pages)."}

await pdf_convert(operation="from_markdown", markdown="# Hello") {"success": true, "path": ".../output_from_markdown_....pdf", "pages": 1, "message": "Created PDF from markdown (1 pages), saved to output_from_markdown_....pdf."}

ParametersJSON Schema
NameRequiredDescriptionDefault
dpiNoDPI for image output. Default 200.
fmtNoImage format (png, jpeg). Default png.png
htmlNoHTML content for from_html operation.
pathNoPath to the PDF file. Required for to_* operations.
pathsNoImage paths for from_images operation.
markdownNoMarkdown content for from_markdown operation.
operationYes
output_dirNoOutput directory for to_images operation.
output_pathNoOutput path. Auto-generated if omitted.

Output Schema

ParametersJSON Schema
NameRequiredDescription
messageNoHuman-readable summary
successNoWhether the operation succeeded

TDQS

B3.2/5.0
Behavior3/5

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

Annotations only declare readOnlyHint=false and openWorldHint=true, so the description does carry some burden. It discloses the failure shape ({success: False, error, error_type}) and that outputs are written to disk with an auto-generated name, which is useful. It does not state file-write permissions, overwrite behavior, or where output lands when output_dir/output_path are omitted.

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

Conciseness4/5

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

Front-loaded with a one-line purpose followed by return-format and example sections that are skimmable and well-labeled. Slightly padded because an output schema already exists, making the return-format section partially redundant, but the worked examples genuinely aid correct invocation.

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

Completeness4/5

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

For a 6-operation tool, the description names every operation, shows two worked calls, and explains both success and failure payloads. Since an output schema exists, return values need not be restated; the remaining gap is the absence of operation-to-parameter mapping (e.g. from_images needing paths).

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?

Schema description coverage is 89%, so the schema already documents path, paths, html, markdown, dpi, fmt, output_dir, and output_path. The description adds no per-parameter syntax or format detail beyond that, so the baseline 3 applies even though the call examples show realistic argument combinations.

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

Purpose4/5

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

States a specific verb and resource ('Convert between PDF and other formats'), enumerates the target formats, and the operation enum makes the directionality explicit. It does not, however, distinguish itself from siblings such as pdf_export, pdf_extract, or pdf_do, which an agent must choose among from a 16-tool family.

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

Usage Guidelines2/5

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

There is no guidance on when to use pdf_convert versus pdf_export or pdf_extract, nor on prerequisites such as whether the PDF must already exist on disk. Usage is only implied through the operation enum, leaving the selection decision to inference.

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

pdf_dedupeB
Read-only

Detect exact and near-duplicate PDFs by content fingerprint.

Return Format

A dict with keys:

  • success: bool

  • files: list of input file names

  • exact_duplicates: [{sha, count, files}]

  • near_duplicates: [{a, b, similarity}]

Examples

await pdf_dedupe(paths=["a.pdf", "b.pdf"]) {"success": true, "files": ["a.pdf", "b.pdf"], "exact_duplicates": [], "near_duplicates": [{"a": "a.pdf", "b": "b.pdf", "similarity": 0.92}]}

ParametersJSON Schema
NameRequiredDescriptionDefault
pathsYesList of PDF paths to check for duplicates.
thresholdNoSimilarity threshold 0-1. Default 0.85.

Output Schema

ParametersJSON Schema
NameRequiredDescription
messageNoHuman-readable summary
successNoWhether the operation succeeded

TDQS

B3.2/5.0
Behavior3/5

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

readOnlyHint=true already establishes the safety profile, so the bar is lower. The description adds the detection mechanism (content fingerprint) and the exact shape of the result keys, which is useful context, but says nothing about performance on large file sets or how near-duplicate similarity is computed.

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

Conciseness4/5

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

Front-loads the one-line purpose, then a structured return-format block and a runnable example. Every section earns its place except the return-format block, which partly duplicates the existing output schema.

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

Completeness4/5

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

For a simple two-parameter tool with an output schema and readOnly annotation, the description covers purpose, output keys, and a concrete example. The main gap is the absence of any when-to-use guidance, which is not offset elsewhere.

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?

Schema coverage is 100%, with both 'paths' and 'threshold' documented in the schema (including the 0.85 default and the 0-1 range). The description adds no parameter syntax or format detail beyond what the schema already provides, so the baseline 3 applies.

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

Purpose4/5

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

States a specific verb (detect) and resource (PDFs) with a clear scope: exact and near-duplicate matching via content fingerprint. It is unambiguous and distinct from every sibling tool, none of which do duplicate detection, though it doesn't explicitly reference those siblings.

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

Usage Guidelines2/5

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

The description never states when to use this tool, when not to, or what alternatives exist. Usage is only implied by the purpose statement and the example, leaving the agent to infer the trigger conditions.

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

pdf_doA

Chain the PDF tools autonomously to complete a natural-language task.

Requires a local LLM (Ollama or LM Studio) or a client that supports MCP sampling. The LLM plans up to 6 tool calls from the pdf_* surface, the server answer. pdf_do cannot call itself or pdf_shutdown.

Return Format

A dict with keys:

  • success: bool

  • answer: str - final natural-language answer

  • steps: list of {tool, args, result} execution records On failure: {success: False, error}.

Examples

await pdf_do(task="Summarize this report and check it for PII.", path="report.pdf") {"success": true, "answer": "The report covers Q3 results... 3 PII hits found.", "steps": [{"tool": "pdf_export", ...}]}

ParametersJSON Schema
NameRequiredDescriptionDefault
pathNoPath to a PDF file if the task targets one.
taskYesNatural-language task to perform with the PDF tooling.

Output Schema

ParametersJSON Schema
NameRequiredDescription
messageNoHuman-readable summary
successNoWhether the operation succeeded

TDQS

A4.1/5.0
Behavior4/5

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

Adds real behavioral context beyond annotations: it depends on an external LLM to plan, is capped at 6 tool calls, and is explicitly non-recursive (cannot invoke itself or pdf_shutdown). Annotations already flag readOnlyHint=false and openWorldHint=true, and the description's LLM-dependency and planning behavior are non-obvious traits worth disclosing.

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

Conciseness4/5

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

Front-loads the core purpose, then organizes prerequisites, return format, and an example into clear sections with little redundancy. The prerequisite sentence contains a dangling fragment ('the server answer') that slightly hurts polish but doesn't obscure meaning.

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

Completeness4/5

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

For a non-trivial orchestrator this covers the dependency requirements, recursion limits, return structure, and a failure shape, plus a worked example. It is complete enough that an agent can invoke it correctly, though it could say more about what happens when no LLM/sampling is available.

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?

Schema coverage is 100%, so both parameters (task, path) are already documented in the schema. The description and example add slight practical context (path targets a PDF, task is a natural-language instruction) but nothing beyond what the schema provides, so the baseline of 3 applies.

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?

States a precise verb and resource: it autonomously chains the pdf_* tools to fulfill a natural-language task. This clearly differentiates it from the individual sibling tools (pdf_export, pdf_extract, etc.) since it is the orchestration layer above them.

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?

Gives concrete prerequisites (needs a local Ollama/LM Studio LLM or MCP-sampling client) and explicit boundaries (max 6 planned calls, cannot call itself or pdf_shutdown). It does not state when to prefer pdf_do over calling the pdf_* tools directly, so routing guidance is implied rather than explicit.

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

pdf_exportB

Build a reusable document brief (markdown or JSON) with headings, key terms, and optional summary.

Return Format

A dict with keys:

  • success: bool

  • path: str - brief file path

  • pages: int

  • summary: str | None

Examples

await pdf_export(path="report.pdf", format="markdown") {"success": true, "path": ".../report_brief.md", "pages": 12, "summary": "..."}

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYesPath to the PDF file.
formatNoOutput format. Default markdown.markdown
include_summaryNoAppend an LLM summary when available. Default true.

Output Schema

ParametersJSON Schema
NameRequiredDescription
messageNoHuman-readable summary
successNoWhether the operation succeeded

TDQS

B3.2/5.0
Behavior3/5

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

Annotations declare readOnlyHint=false and openWorldHint=true, so the write/no-side-effect profile is partly conveyed structurally, and the description adds that a brief file is written (via path) with an appended LLM summary when available. It does not state overwrite behavior, required permissions, or that the summary step may be costly/non-deterministic, so credit is moderate.

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

Conciseness4/5

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

Front-loads the one-line purpose and keeps the return-format and example sections terse and skimmable. Slight redundancy in restating return keys that an output schema already covers.

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

Completeness4/5

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

With an output schema present, return values need not be explained, yet the description restates them, which is harmless filler rather than a gap. For a file-writing tool the main missing context is write/permission and overwrite semantics.

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?

Schema description coverage is 100%, so the parameters (path, format, include_summary) are already well documented; the description only echoes format options and the optional summary. Nothing beyond the schema is added, matching the baseline.

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

Purpose4/5

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

States a specific verb ("Build") and resource ("reusable document brief") plus the artifact's content (headings, key terms, summary). It does not, however, differentiate clearly from siblings like pdf_extract or pdf_analyze, which also derive content from a PDF.

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

Usage Guidelines2/5

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

No when-to-use guidance, prerequisites, or named alternatives are given, despite 15 sibling tools in the pdf_* family. The agent must infer the tool's niche on its own.

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

pdf_extractB
Read-only

Extract content and metadata from a PDF.

Supports text, images, tables, metadata, fonts, links, and outline extraction through a single portmanteau tool.

Args are validated and documented via Annotated fields on the signature.

Return Format

A dict with keys:

  • success: bool - whether the operation succeeded

  • message: str - human-readable summary

  • operation-specific keys:

    • text: {text, pages, page_count}

    • images: {images: [{page, index, width, height, path, ext}]}

    • tables: {tables: [{page, rows, cols, headers, data}]}

    • metadata: {metadata: {...}}

    • fonts: {fonts: [{name, type, encoding, embedded, size}]}

    • links: {links: [{page, uri, page_target, rect}]}

    • outline: {outline: [{title, level, page, children}]} On failure: {success: False, error, error_type}.

Examples

await pdf_extract(operation="text", path="report.pdf", pages="1-3") {"success": true, "text": "...", "pages": 3, "page_count": 12, "message": "Extracted 3 pages of text from report.pdf."}

await pdf_extract(operation="metadata", path="report.pdf") {"success": true, "metadata": {"title": "Report", ...}, "message": "Extracted metadata from report.pdf."}

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYesPath to the PDF file.
pagesNoOptional page range (e.g. '1-5,7,9-12'). All pages if omitted.
operationYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
messageNoHuman-readable summary
successNoWhether the operation succeeded

TDQS

B3.3/5.0
Behavior3/5

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

readOnlyHint=true already tells the agent this is a safe read operation. The description adds the return dict shape and the failure shape ({success: False, error, error_type}), which is useful, but since an output schema exists the return-format detail is partly redundant and no permissions, limits, or edge-case behavior are disclosed.

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

Conciseness4/5

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

Purpose is front-loaded, then operations, return format, and examples follow in a clear hierarchy. It runs long and duplicates the output schema in the Return Format section, but each block is scannable and relevant for a portmanteau tool.

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

Completeness3/5

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

With an output schema present, the return-value documentation is not strictly needed, and the operation list makes invocation clear. However, against 16 sibling tools the description gives no routing guidance, leaving a real gap in knowing when this tool is the right choice.

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?

Schema coverage is 67%; the operation enum has no schema description, but the description enumerates its values (text, images, tables, metadata, fonts, links, outline), compensating for that gap. path and pages are already documented in the schema, so the description does its job where coverage is missing.

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

Purpose4/5

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

States a specific verb and resource ('Extract content and metadata from a PDF') and enumerates the seven extraction modes, so the agent understands the tool's scope precisely. It does not explicitly distinguish itself from siblings like pdf_rag or pdf_analyze, which prevents a 5.

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

Usage Guidelines2/5

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

The description never says when to choose pdf_extract over the many siblings (pdf_rag, pdf_analyze, pdf_convert, etc.) or when not to use it. 'Single portmanteau tool' implies consolidation but provides no decision criteria.

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

pdf_formsC
Read-only

Handle interactive form fields.

List, fill, flatten, export, and auto-fill (LLM-guided) PDF form fields.

Return Format

A dict with keys:

  • success: bool

  • message: str - human-readable summary

  • operation-specific keys:

    • list_fields: {fields: [{name, type, value, page, rect}]}

    • fill/flatten: {path}

    • export_data: {data: {field_name: value}}

    • auto_fill: {path, filled, missing} On failure: {success: False, error, error_type}.

Examples

await pdf_forms(operation="list_fields", path="form.pdf") {"success": true, "fields": [{"name": "name", "type": "text", "value": "", "page": 0, "rect": [...]}], "message": "Found 1 form fields in form.pdf."}

await pdf_forms(operation="fill", path="form.pdf", fields={"name": "Ada"}) {"success": true, "path": ".../form_fill_....pdf", "message": "Filled 1 form fields in form.pdf, saved to form_fill_....pdf."}

await pdf_forms(operation="auto_fill", path="form.pdf", source="source.pdf") {"success": true, "path": ".../form_autofill_....pdf", "filled": 3, "missing": [], "message": "Auto-filled 3 fields in form.pdf from source.pdf."}

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYesPath to the PDF file.
textNoSource text driving auto_fill (alternative to source).
fieldsNoDict of field_name: value for fill operation.
sourceNoSource PDF path whose text drives auto_fill.
operationYes
output_pathNoOutput path. Auto-generated if omitted.

Output Schema

ParametersJSON Schema
NameRequiredDescription
messageNoHuman-readable summary
successNoWhether the operation succeeded

TDQS

C2.9/5.0
Behavior1/5

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

Annotations declare readOnlyHint=true, yet the description states the tool fills, flattens, and auto-fills forms, writing new PDFs to output_path (fill/flatten return {path}, auto_fill returns {path, filled, missing}). Writing files modifies the environment, so the description contradicts the read-only annotation.

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

Conciseness4/5

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

Front-loaded with the purpose and an operation list, then cleanly sectioned into Return Format and Examples with headers. It is a bit long and the return-format block duplicates the output schema, but every part is readable and none is filler.

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

Completeness4/5

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

For a 6-parameter, multi-operation tool the description covers the operation set, key inputs, success/failure shapes, and worked examples. Since an output schema exists, the return-format section is redundant but not harmful; the main gap is the absence of permission/when-to-use context.

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?

Schema description coverage is high (83%) and the schema already documents path, fields, source, text, and output_path with their roles. The description reiterates the operations and return shape but adds no new parameter meaning (e.g., fill value typing, flatten vs fill interaction) beyond what the schema provides.

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

Purpose4/5

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

It names a specific resource (PDF form fields) and enumerates the concrete operations (list, fill, flatten, export, auto-fill) which map cleanly onto the operation enum. However, it does nothing to distinguish this from siblings such as pdf_annotate, pdf_manipulate, or pdf_export, so the agent must infer boundaries.

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

Usage Guidelines2/5

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

There is no when-to-use / when-not-to-use guidance and no named alternatives among the many pdf_* siblings. The only hint is that auto_fill is 'LLM-guided', with no prerequisites, permissions, or conditions noted for choosing a given operation.

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

pdf_helpA
Read-only

List available tools and get usage help for pdf-mcp.

Return Format

A dict with keys:

  • success: bool

  • message: str - human-readable summary

  • data: list of tools with name, description, and input schema, or detailed help for a single tool when tool_name is provided.

Examples

await pdf_help() {"success": true, "message": "8 tools available.", "data": [{"name": "pdf_extract", ...}]}

await pdf_help(tool_name="pdf_extract") {"success": true, "message": "Help for pdf_extract.", "data": {...}}

ParametersJSON Schema
NameRequiredDescriptionDefault
tool_nameNoName of a tool to get detailed help for. Lists all tools if omitted.

Output Schema

ParametersJSON Schema
NameRequiredDescription
messageNoHuman-readable summary
successNoWhether the operation succeeded

TDQS

A4.1/5.0
Behavior4/5

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

readOnlyHint=true is consistent with a help/discovery operation, and the description goes beyond the annotation by documenting the return contract (success/message/data with tool names, descriptions, and input schemas). It does not mention latency or authentication characteristics, but for a read-only introspection tool the disclosure is solid.

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

Conciseness4/5

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

Purpose is front-loaded in the first sentence, followed by a compact return-format block and two concrete examples. The examples earn their place for a help tool since they demonstrate both the no-arg and arg call shapes, though the section could be trimmed slightly.

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

Completeness4/5

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

An output schema exists, so return values need not be re-explained, and the annotation covers safety. The description still supplies the response shape and examples, making the definition complete for a zero-required-parameter help tool; no prerequisites or edge cases are omitted that would block correct invocation.

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?

Schema description coverage is 100% and the single parameter already documents 'Name of a tool to get detailed help for. Lists all tools if omitted.' The description restates this rather than adding syntax or format depth, so the baseline 3 applies.

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?

States a specific verb+resource pair: lists available tools and returns usage help for the pdf-mcp server, with an optional drill-down for a single tool. It is unmistakably the meta/discovery tool, distinguishable at a glance from all named siblings like pdf_extract or pdf_export.

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 and worked examples make the when-to-use clearly implied: call with no arguments to enumerate tools, call with tool_name for detailed help. It states the selection condition for the parameter ('Lists all tools if omitted') but does not explicitly frame when an agent should prefer this help lookup over just reading a tool's own schema.

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

pdf_manipulateA

Modify PDF structure and properties.

Merge, split, rotate, reorder, delete pages, compress, encrypt/decrypt, and optimize PDFs.

Return Format

A dict with keys:

  • success: bool - whether the operation succeeded

  • message: str - human-readable summary

  • operation-specific keys:

    • merge: {path, pages}

    • split: {files: [path, ...]}

    • rotate/reorder/delete_pages/encrypt/decrypt: {path}

    • compress: {path, original_size, compressed_size}

    • optimize: {path, original_size, optimized_size} On failure: {success: False, error, error_type}.

Examples

await pdf_manipulate(operation="merge", path="a.pdf", paths=["a.pdf", "b.pdf"]) {"success": true, "path": ".../merged_....pdf", "pages": 4, "message": "Merged 2 PDFs into merged_....pdf (4 pages)."}

await pdf_manipulate(operation="rotate", path="report.pdf", angle=90) {"success": true, "path": ".../report_rotate_....pdf", "message": "Rotated report.pdf by 90 degrees, saved to report_rotate_....pdf."}

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYesPath to the PDF file. Ignored for merge.
angleNoRotation angle in degrees. Default 90.
pagesNoPage range string (e.g. '1-5,7,9-12'). For rotate operation.
pathsNoList of PDF paths to merge. Only for merge operation.
rangesNoSplit ranges as list of [start, end] pairs (1-indexed).
qualityNoCompression quality 1-100. Default 85.
passwordNoPassword for encrypt/decrypt operations.
new_orderNoNew page order (1-indexed list). For reorder operation.
operationYes
page_listNoList of page numbers to delete. For delete_pages operation.
output_dirNoOutput directory for split operation.
output_pathNoOutput path. Auto-generated if omitted.

Output Schema

ParametersJSON Schema
NameRequiredDescription
messageNoHuman-readable summary
successNoWhether the operation succeeded

TDQS

A3.8/5.0
Behavior4/5

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

Annotations only declare readOnlyHint=false and openWorldHint=true, so the description carries real weight and does so: it discloses that outputs are written to auto-generated new files (e.g., 'saved to report_rotate_....pdf') rather than mutating in place, and it documents failure shape via {success: False, error, error_type}. It does not mention permission requirements or that encrypt/decrypt need a password, but the operation-level output mapping is genuinely additive.

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

Conciseness3/5

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

Front-loading is good and the headers make it scannable, but the entire '## Return Format' section duplicates the output schema that already exists, so a large share of the text does not earn its place. The two examples are useful and worth keeping; the key-by-key return listing is not.

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

Completeness4/5

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

For a 12-parameter, nine-operation tool with an output schema and strong schema coverage, the description supplies the operation inventory and concrete invocation examples, which is close to sufficient. The remaining gap is the absence of any guidance on choosing among sibling PDF tools and on output_path vs output_dir behavior.

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?

Schema description coverage is already 92%, so the baseline is 3, and the worked examples push it higher by showing real parameter combinations (operation+path+paths for merge, operation+path+angle for rotate). The return-format section also ties each operation to the fields it consumes, which the schema does not do in one place.

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?

States a specific verb+resource ('Modify PDF structure and properties') and then enumerates all nine concrete operations, which cleanly separates it from siblings like pdf_convert, pdf_extract, pdf_annotate, and pdf_redact. An agent can identify the tool's scope without opening the schema.

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

Usage Guidelines2/5

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

The description never says when to choose pdf_manipulate over pdf_convert, pdf_do, or pdf_annotate, nor does it state prerequisites or when-not to use it. The operation list implies usage, but no routing guidance or exclusions are given despite 15 sibling tools existing.

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

pdf_ragC
Read-only

Build and query a RAG index over PDF content.

Chunks, indexes, and semantically searches PDF text via LanceDB. Tables are indexed as structured chunks (section='table'). Supports query-by-example and cross-document synthesis.

Return Format

A dict with keys:

  • success: bool - whether the operation succeeded

  • message: str - human-readable summary

  • operation-specific keys:

    • chunk: {chunks, doc_id}

    • index: {chunks_indexed, doc_id}

    • search: {results: [{doc_id, chunk_id, page_num, section, source_file, text, _distance}]}

    • similar: same shape as search (seeded by a text snippet)

    • synthesize: {groups: [{doc_id, source_file, hits, snippet}], summary?}

    • list_documents: {documents: [{doc_id, chunk_count}]}

    • delete_index: {} On failure: {success: False, error, error_type}.

Examples

await pdf_rag(operation="chunk", path="book.pdf", strategy="recursive", chunk_size=1000) {"success": true, "chunks": 42, "doc_id": "a1b2c3d4e5f6", "message": "Chunked book.pdf (300 pages) into 42 chunks with recursive strategy."}

await pdf_rag(operation="search", query="quarterly revenue") {"success": true, "results": [{...}], "message": "Found 3 results for 'quarterly revenue'."}

await pdf_rag(operation="similar", text="The sky was unusually clear that night.") {"success": true, "results": [{...}], "message": "Found 2 similar passages."}

ParametersJSON Schema
NameRequiredDescriptionDefault
pathNoPath to the PDF file. Required for chunk, index operations.
textNoSource text snippet for similar (query-by-example) operation.
limitNoMax search results. Default 10.
queryNoSearch query for search / synthesize operations.
doc_idNoDocument ID for delete_index operation.
overlapNoChunk overlap in characters. Default 200.
strategyNoChunking strategy: recursive, fixed. Default recursive.recursive
operationYes
chunk_sizeNoTarget chunk size in characters. Default 1000.

Output Schema

ParametersJSON Schema
NameRequiredDescription
messageNoHuman-readable summary
successNoWhether the operation succeeded

TDQS

C2.9/5.0
Behavior1/5

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

The annotation declares readOnlyHint=true, yet the tool's own operation list includes write/mutating operations: chunk and index create LanceDB tables and delete_index destroys a stored index. The description directly contradicts the read-only annotation, leaving the agent misinformed about side effects.

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

Conciseness4/5

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

Front-loads purpose, then return format, then concrete examples with headers. Well organized, though the explicit return-format block is partly redundant given an output schema exists.

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

Completeness4/5

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

For a 7-operation, 9-parameter tool the operation coverage and return shapes are reasonably complete, and an output schema exists. The main gap is the unresolved read-only vs. mutating/destructive confusion introduced by the annotation.

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?

Schema description coverage is 89%, so the schema already documents path, text, limit, query, doc_id, overlap, strategy, and chunk_size. The description adds operational context (which operation seeds from a snippet) but little syntax or format detail beyond the schema, so the baseline 3 applies.

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

Purpose4/5

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

The opening sentence gives a specific verb+resource: 'Build and query a RAG index over PDF content.' It clearly conveys the dual build/query nature. It does not, however, differentiate itself from the many sibling PDF tools (pdf_analyze, pdf_extract) that an agent might otherwise choose.

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

Usage Guidelines2/5

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

The description enumerates operations but never states when to use pdf_rag versus the 15 sibling tools, nor any prerequisite like 'you must chunk/index before searching.' Usage must be inferred from operation names alone.

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

pdf_redactA
Destructive

Blacken sensitive content in a PDF by terms and/or PII patterns.

Return Format

A dict with keys:

  • success: bool

  • path: str - output PDF path

  • occurrences: int - number of regions redacted On failure: {success: False, error}.

Examples

await pdf_redact(path="report.pdf", pii=True) {"success": true, "path": ".../report_redact_....pdf", "occurrences": 7}

await pdf_redact(path="report.pdf", terms=["Acme Corp"]) {"success": true, "path": ".../report_redact_....pdf", "occurrences": 3}

ParametersJSON Schema
NameRequiredDescriptionDefault
piiNoRedact PII (email, phone, IBAN, card, SSN, IP). Default false.
pathYesPath to the PDF file to redact.
termsNoExact phrases to blacken.
output_pathNoOutput path. Auto-generated if omitted.

Output Schema

ParametersJSON Schema
NameRequiredDescription
messageNoHuman-readable summary
successNoWhether the operation succeeded

TDQS

A3.7/5.0
Behavior3/5

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

Annotations already declare destructiveHint=true and openWorldHint=true, so the safety profile is covered structurally. The description adds the return contract (success/path/occurrences and the failure shape), which is useful, but says nothing about permissions, whether the source file is modified, or file-size/page limits.

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

Conciseness4/5

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

The core purpose is front-loaded in a single sentence, followed by a compact return contract and two examples that each earn their place. The Return Format section partially duplicates the existing output schema, which is the only mild redundancy.

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

Completeness4/5

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

For a four-parameter mutation tool with full schema coverage and an output schema, the description is sufficient: purpose, return contract, and worked examples are all present. It could be richer on side effects (whether the original PDF is preserved) but nothing essential for correct invocation is missing.

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?

Schema description coverage is 100%, so all four parameters are already documented in the schema and the baseline is 3. The description's mention of 'terms and/or PII patterns' and the examples reinforce how the parameters combine, but add no syntax or format detail 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?

States a specific verb and resource ('Blacken sensitive content in a PDF') plus the two mechanisms ('terms and/or PII patterns'), which cleanly separates it from every other pdf_* sibling such as pdf_annotate or pdf_extract. An agent can identify the operation without opening the schema.

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

Usage Guidelines3/5

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

The two examples imply the two modes (pii=True for pattern-based redaction, terms=[...] for exact phrases), which is useful implied guidance, but there is no explicit statement of when to choose this tool over pdf_annotate or pdf_manipulate, and no preconditions or exclusions are given.

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

pdf_shutdownB
Destructive

Gracefully shut down the pdf-mcp server.

Return Format

A dict with keys:

  • success: bool

  • message: str - shutdown confirmation

Examples

await pdf_shutdown() {"success": true, "message": "Shutting down pdf-mcp."}

ParametersJSON Schema
NameRequiredDescriptionDefault
reasonNoOptional shutdown reason.

Output Schema

ParametersJSON Schema
NameRequiredDescription
messageNoHuman-readable summary
successNoWhether the operation succeeded

TDQS

B3.3/5.0
Behavior3/5

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

The destructiveHint=true annotation already flags this as destructive, so the description needn't restate that. It does add value by specifying the shutdown is 'graceful,' implying an orderly stop rather than a hard kill, but it omits what actually gets destroyed (other sessions, in-flight jobs) and whether the action is reversible.

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

Conciseness3/5

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

The purpose is front-loaded in a single clear sentence, which is good. However, the Return Format block and the example duplicate what the existing output schema already conveys, so several lines do not earn their place.

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

Completeness3/5

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

For a low-complexity, zero-required-parameter tool with an output schema present, the description is minimally adequate once return values are excluded. It nonetheless omits the operational impact of shutting down the server, which is the main thing an agent needs before invoking a destructive action.

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?

Schema description coverage is 100% and the single optional 'reason' parameter is documented in the schema, so the baseline is 3. The description never mentions the 'reason' parameter and adds no semantics 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?

States a specific verb ('shut down') and resource ('the pdf-mcp server'), clearly distinguishing this from every sibling tool that manipulates or exports PDFs. An agent immediately knows this terminates the server rather than doing document work.

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

Usage Guidelines2/5

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

The description says what the tool does but offers no when-to-use, when-not-to-use, or alternative guidance. It does not warn when shutdown is appropriate, whether other active operations are affected, or how to reverse/restart, leaving usage entirely to inference.

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

pdf_statusA
Read-only

Report server status, version, uptime, and registered tool count.

Return Format

A dict with keys:

  • success: bool

  • server: str - server name

  • version: str - server version

  • uptime_seconds: int

  • tool_count: int

  • mode: str - stdio or http

Examples

await pdf_status() {"success": true, "server": "pdf-mcp", "version": "0.1.0", "uptime_seconds": 42, "tool_count": 8, "mode": "http"}

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
messageNoHuman-readable summary
successNoWhether the operation succeeded

TDQS

A4.2/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true, so the safety profile is covered. The description goes beyond that with useful context: the exact fields returned, the meaning of the 'mode' value (stdio or http), and a concrete worked example, which tells the agent what a healthy response looks like.

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

Conciseness4/5

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

The purpose is front-loaded in the first sentence and the rest is scannable structure. The 'Return Format' block partly duplicates the output schema, which is slight redundancy, but the example adds concrete value rather than padding.

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 no-argument, read-only diagnostic tool this is complete: the agent knows what it does, what comes back, and has a runnable example. Nothing needed to invoke it correctly is missing.

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 tool takes zero parameters and the schema is an empty object with additionalProperties=false, so there is nothing for the description to disambiguate. The provided example call (await pdf_status()) reinforces that no arguments are needed, which is the correct baseline for a 0-param tool.

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?

States a specific verb ('Report') and resource ('server status') and enumerates exactly what is reported: version, uptime, and registered tool count. No sibling in the pdf_* family serves this diagnostic role, so the agent can route to it unambiguously from the name and first sentence alone.

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

Usage Guidelines3/5

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

Usage is implied rather than stated: an agent can infer this is the health/diagnostic call, but there is no explicit when-to-use, no prerequisites, and no comparison to alternatives such as pdf_help. It is adequate but leaves the agent to infer the trigger condition.

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

pdf_validateA
Read-only

Audit PDF quality and compliance.

PDF/A, structure, accessibility, integrity, and comparison checks.

Return Format

A dict with keys:

  • success: bool - whether the operation succeeded

  • message: str - human-readable summary

  • operation-specific keys:

    • pdfa: {is_pdfa, details}

    • structure: {has_tags, headings, paragraphs, issues}

    • accessibility: {score (0-100), issues}

    • integrity: {intact, pages_readable, warnings}

    • compare: {same_page_count, text_similarity, diffs} On failure: {success: False, error, error_type}.

Examples

await pdf_validate(operation="accessibility", path="report.pdf") {"success": true, "score": 75, "issues": [...], "message": "Accessibility score: 75/100 for report.pdf. 0 errors, 1 warnings."}

await pdf_validate(operation="compare", path_a="a.pdf", path_b="b.pdf") {"success": true, "same_page_count": true, "text_similarity": 0.98, "diffs": [], "message": "Comparison: same page count, 98.0% text similarity between a.pdf and b.pdf."}

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYesPath to the PDF file. Ignored for compare.
path_aNoFirst PDF path for compare operation.
path_bNoSecond PDF path for compare operation.
operationYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
messageNoHuman-readable summary
successNoWhether the operation succeeded

TDQS

A3.9/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true, so safety is covered, but the description adds meaningful behavioral context beyond that: the exact success/failure shape ({success: False, error, error_type}) and operation-specific result keys. It does not discuss performance, file-size limits, or what 'integrity' warnings imply, so not a 5.

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

Conciseness4/5

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

Front-loaded purpose, then clearly labeled 'Return Format' and 'Examples' sections; headers make it scannable. It is somewhat long because the operation-key dictionary is enumerated, which the output schema arguably already covers, so a small amount of redundancy keeps it from a 5.

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 five-mode validation tool with a full output schema and read-only annotations, the description covers purpose, all operations, failure handling, and usage examples. An agent has everything needed to select the right operation and construct a correct call.

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 per-operation result mapping and the two examples clarify that 'compare' requires path_a/path_b while other operations use 'path', adding real meaning beyond the 75%-covered schema. The schema descriptions still carry some of the load (e.g. 'Ignored for compare'), so this is helpful rather than fully self-sufficient.

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

Purpose4/5

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

The description opens with a specific verb+resource ('Audit PDF quality and compliance') and enumerates the five concrete check categories (PDF/A, structure, accessibility, integrity, comparison). This is far more than a restatement of the name. It stops short of distinguishing itself from the sibling pdf_analyze, which likely overlaps in scope, so it does not earn a 5.

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

Usage Guidelines3/5

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

The enumerated operations imply what each mode is for, and the example for 'compare' shows when path_a/path_b are needed, giving implicit usage guidance. However, there is no explicit when-to-use / when-not-to-use statement and no routing away from siblings like pdf_analyze. Adequate but with a clear gap.

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. 16 tool updatesv0.2.1
    • First observedpdf_analyze
    • First observedpdf_annotate
    • First observedpdf_classify
    • First observedpdf_convert
    • First observedpdf_dedupe
    • First observedpdf_do
    • First observedpdf_export
    • First observedpdf_extract
    • First observedpdf_forms
    • First observedpdf_help
    • First observedpdf_manipulate
    • First observedpdf_rag
    • First observedpdf_redact
    • First observedpdf_shutdown
    • First observedpdf_status
    • First observedpdf_validate

TDQS

A3.5/5.0

Scored across 16 tools

Disambiguation4/5

Most tools target clearly distinct operations (extract, convert, annotate, forms, redact, classify, dedupe, validate). A few boundaries blur: pdf_analyze vs pdf_validate both perform structural audits, and pdf_export's markdown brief overlaps with pdf_convert's to_markdown and pdf_extract's text output.

Naming Consistency4/5

All 16 tools use a consistent pdf_ snake_case prefix with verb-style names (pdf_extract, pdf_convert, pdf_annotate, pdf_validate). Minor deviations: pdf_rag uses a noun/acronym and pdf_do is a vague verb, but the overall pattern is predictable.

Tool Count4/5

16 tools for a full PDF processing suite is reasonable; each operation (extract, convert, manipulate, annotate, forms, RAG, redact, classify, dedupe, validate, analyze, export) earns its place alongside help/status/shutdown infrastructure. Slightly heavy but well within scope.

Completeness4/5

Broad lifecycle coverage: read, transform, annotate, secure, validate, and even semantic indexing. Notable gap: pdf_analyze detects scanned PDFs but no OCR tool exists to make them usable, a common follow-on for a PDF domain. Otherwise the surface is robust with no major dead ends.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • -
    license
    Not graded
    quality
    Not graded
    maintenance
    Enables comprehensive PDF analysis and manipulation including page size analysis, chapter extraction, splitting, compression, merging, and conversion to images. Provides both MCP server interface for AI assistants and Streamlit web interface for direct user interaction.
    -
  • A
    license
    A
    quality
    C
    maintenance
    An MCP server for reading, rendering, and searching PDF files, specifically optimized for LLMs to extract text, tables, and technical diagrams. It enables metadata retrieval, multi-format text extraction, and page-to-image rendering using PyMuPDF.
    5
    78
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    MCP server that reads PDFs and exposes them as structured Markdown, metadata, outlines, images, and tables to LLM consumers via tools like pdf_read_markdown and pdf_info.
    Apache 2.0
  • A
    license
    Not graded
    quality
    C
    maintenance
    MCP server for exporting PDF to markdown, optimized for LLM consumption.
    5,254 PyPI
    71
    AGPL 3.0