oxidize-pdf
The oxidize-pdf MCP server provides comprehensive PDF capabilities for AI agents to read, create, manipulate, annotate, secure, and analyze PDF documents.
Read & Extract (
read_pdf,extract_text): Retrieve metadata (page count, version, encryption status, title, author, dimensions) and extract text from entire PDFs or specific pages.Extract Entities (
extract_entities): Pull structured text chunks with position (x, y), font size, and font name per page.Convert (
convert_pdf): Transform PDFs into markdown, token-limited chunks, or RAG-optimized semantic chunks for LLM consumption.Analyze (
analyze_pdf): Validate structure, detect corruption, check PDF/A compliance, and compare two PDFs.Manipulate (
manipulate_pdf): Split, merge, rotate, extract pages, reverse order, or overlay PDFs.Annotate (
annotate_pdf): Add sticky note annotations or highlight rectangles at specified positions.Manage Forms (
manage_forms): Create, fill, read, and validate PDF form fields.Secure (
secure_pdf): Encrypt/decrypt with user/owner passwords, check permissions, and verify digital signatures.Create & Save (
create_pdf,add_pdf_content,save_pdf): Start a PDF session, add text at specific coordinates or new blank pages, then finalize and save with optional encryption.Resources: Access built-in fonts, standard page sizes, server capabilities, workspace files, and session data via
oxidize://URIs.Guided Workflows: Built-in prompts assist with summarization, data extraction, form filling, and other common tasks.
Integrates with GitHub Copilot's agent mode in VS Code, exposing PDF manipulation tools for AI-assisted PDF workflows.
Integrates with the OpenAI Agents SDK, allowing AI agents to perform PDF operations such as reading, extracting, converting, and manipulating PDFs.
oxidize-pdf
Rust-powered PDF library for Python. Generate, parse, split, merge, and manipulate PDFs with native performance. Ships with a built-in MCP server so AI agents can work with PDFs out of the box.
No C dependencies. No Java. No subprocess calls.
Installation
pip install oxidize-pdf # Core library
pip install "oxidize-pdf[mcp]" # + MCP server for AI agentsPlatforms: Linux (x86_64, aarch64) | macOS (x86_64, Apple Silicon) | Windows (x86_64) Requires: Python 3.10+
Related MCP server: PDFSizeAnalyzer-MCP
Why oxidize-pdf?
oxidize-pdf | Pure-Python libs | C/Java wrappers | |
Performance | Native (compiled Rust) | Interpreted | Native but heavy |
Dependencies | Zero | Varies | Poppler, Java, Ghostscript |
Memory safety | Rust ownership model | GC-dependent | Manual / GC |
Type stubs | Full (mypy/pyright) | Partial | Rare |
AI-ready (MCP) | Built-in | No | No |
MCP Server
Give your AI agent full PDF capabilities in one line:
oxidize-mcpThe built-in Model Context Protocol server exposes 12 tools, 6 resources, and 5 prompts — compatible with Claude, GPT, and any MCP client.
Claude Desktop integration
Add to your claude_desktop_config.json:
{
"mcpServers": {
"oxidize-pdf": {
"command": "oxidize-mcp",
"env": {
"OXIDIZE_WORKSPACE": "/path/to/your/pdfs"
}
}
}
}GitHub Copilot (VS Code) integration
Copilot's agent mode speaks MCP. Add .vscode/mcp.json to your workspace:
{
"servers": {
"oxidize-pdf": {
"command": "oxidize-mcp",
"env": {
"OXIDIZE_WORKSPACE": "/path/to/your/pdfs"
}
}
}
}Open the Chat view, switch to Agent mode, and the 12 PDF tools appear in
the tool picker. (The same block also works under the mcp.servers key in your
user settings.json if you prefer a global install.)
OpenAI Agents SDK integration
The OpenAI Agents SDK spawns the server over stdio and exposes its tools to an agent:
from agents import Agent, Runner
from agents.mcp import MCPServerStdio
async with MCPServerStdio(
params={"command": "oxidize-mcp", "env": {"OXIDIZE_WORKSPACE": "/path/to/your/pdfs"}},
cache_tools_list=True,
) as server:
agent = Agent(
name="PDF assistant",
instructions="Use the oxidize-pdf tools to inspect and manipulate PDFs.",
mcp_servers=[server],
)
result = await Runner.run(agent, "How many pages does report.pdf have?")
print(result.final_output)A runnable version is in examples/openai_agents_quickstart.py.
Both integrations run the server locally over stdio, so its tools operate on PDFs in the configured workspace directory. Remote/hosted use (e.g. the OpenAI Responses API hosted MCP tool) needs an HTTP transport and is not yet exposed.
Available tools
Tool | What it does |
| Read metadata — page count, version, encryption status, title, author |
| Extract text from all pages or a specific page |
| Convert to markdown, chunks, or RAG-optimized format |
| Create a new PDF with optional metadata |
| Save a session to disk, with optional encryption |
| Add pages, text, and graphics to a session |
| Add text annotations and highlights |
| Split, merge, rotate, extract pages, reverse, overlay |
| Create, fill, read, and validate form fields |
| Encrypt, check permissions, verify signatures |
| Extract structured entities from pages |
| Validate structure, detect corruption, check PDF/A compliance |
The server also exposes resources (session data, capabilities, version info) and prompts (guided workflows for summarization, data extraction, form filling, and more).
Configuration
OXIDIZE_WORKSPACE=/path/to/pdfs oxidize-mcpThe server is configured entirely through environment variables:
Variable | Default | Purpose |
|
| Sandbox root; all paths must resolve inside it. |
| (none) | Comma-separated extra directories allowed outside the workspace. |
|
| Reject input PDFs larger than this on disk. |
|
| Reject documents with more pages than this before any extraction work. |
|
| Cap the serialized size of a tool's JSON response (10 MB). |
|
| Maximum concurrent stateful PDF-creation sessions. |
|
| Cap the content a single session may accumulate (10 MB). |
|
| Session expiry, in seconds. |
Resource caps (OXIDIZE_MAX_*) protect the server from a large or malicious
PDF: oversized documents are rejected up front and tool responses are bounded
rather than serialized unbounded. Exceeding a cap returns an error with code
RESOURCE_LIMIT.
Or start programmatically:
from oxidize_pdf.mcp.server import run
run()Python API
Create a PDF
from oxidize_pdf import Document, Page, Font, Color
doc = Document()
doc.set_title("My Document")
doc.set_author("Jane Doe")
page = Page.a4()
page.set_font(Font.HELVETICA, 24.0)
page.set_text_color(Color.black())
page.text_at(72.0, 750.0, "Hello from oxidize-pdf!")
page.set_font(Font.TIMES_ROMAN, 12.0)
page.text_at(72.0, 700.0, "Generated with Python + Rust.")
doc.add_page(page)
doc.save("output.pdf")Parse an existing PDF
from oxidize_pdf import PdfReader
reader = PdfReader.open("document.pdf")
print(f"Pages: {reader.page_count}, Version: {reader.version}")
for i, text in enumerate(reader.extract_text()):
print(f"--- Page {i + 1} ---")
print(text)Operations
from oxidize_pdf import split_pdf, merge_pdfs, rotate_pdf, extract_pages
split_pdf("input.pdf", "output_dir/") # Split into individual pages
merge_pdfs(["part1.pdf", "part2.pdf"], "merged.pdf") # Merge multiple PDFs
rotate_pdf("input.pdf", "rotated.pdf", 90) # Rotate all pages
extract_pages("input.pdf", "subset.pdf", [0, 2, 4]) # Extract specific pagesGraphics
from oxidize_pdf import Document, Page, Color
doc = Document()
page = Page.a4()
page.set_fill_color(Color.hex("#3498db"))
page.draw_rect(72.0, 700.0, 200.0, 100.0)
page.fill()
page.set_stroke_color(Color.red())
page.set_line_width(2.0)
page.draw_circle(300.0, 500.0, 50.0)
page.stroke()
doc.add_page(page)
doc.save("graphics.pdf")Types
from oxidize_pdf import Color, Point, Rectangle, Margins, Font
# Colors
Color.rgb(1.0, 0.0, 0.0) # RGB
Color.hex("#ff6600") # Hex
Color.cmyk(0.0, 1.0, 1.0, 0.0) # CMYK
# Geometry
Point(72.0, 720.0)
Rectangle.from_xywh(72.0, 72.0, 468.0, 648.0)
Margins.uniform(72.0)
# Fonts — all 14 standard PDF fonts
Font.HELVETICA # Font.HELVETICA_BOLD
Font.TIMES_ROMAN # Font.TIMES_BOLD
Font.COURIER # Font.COURIER_BOLDError handling
from oxidize_pdf import PdfReader, PdfError, PdfIoError, PdfParseError
try:
reader = PdfReader.open("missing.pdf")
except PdfIoError as e:
print(f"I/O error: {e}")
except PdfParseError as e:
print(f"Parse error: {e}")
except PdfError as e:
print(f"PDF error: {e}")Exception hierarchy: PdfError > PdfIoError, PdfParseError, PdfEncryptionError, PdfPermissionError
MCP Server
oxidize-pdf includes an MCP server that exposes PDF capabilities to AI assistants like Claude. Install with the mcp extra:
pip install oxidize-pdf[mcp]Claude Desktop
Add this to your claude_desktop_config.json:
{
"mcpServers": {
"oxidize-pdf": {
"command": "uvx",
"args": ["--from", "oxidize-pdf[mcp]", "oxidize-mcp"]
}
}
}Claude Code
claude mcp add oxidize-pdf -- uvx --from "oxidize-pdf[mcp]" oxidize-mcpAvailable tools
Tool | Description |
| Open a PDF and get metadata (pages, version, encryption) |
| Extract text content from PDF pages |
| Convert between PDF versions |
| Analyze structure, fonts, images, and compliance |
| Extract images and digital signatures |
| Split, merge, rotate, extract, and reorder pages |
| Add text annotations, highlights, and stamps |
| Create, fill, and read PDF form fields |
| Encrypt, decrypt, and set document permissions |
| Create a new PDF document with pages |
| Add text, shapes, and images to pages |
| Save the document to file or bytes |
Resources
oxidize://fonts— Available built-in PDF fontsoxidize://page-sizes— Standard page sizes with dimensionsoxidize://capabilities— Server capabilities and tool listingoxidize://version— Version informationoxidize://workspace— PDF files in the workspace directoryoxidize://session/{id}— Session data by ID
Known limitations
Encryption write support:
Document.encrypt()configures encryption parameters but the underlying Rust library does not yet serialize the encryption dictionary to the PDF output. Reading encrypted PDFs works correctly.Image extraction returns raw embedded streams:
extract_images_from_pdfextracts each embedded image as-is (e.g. aDCTDecodeJPEG is written byte-for-byte). Image preprocessing — auto rotation-correction, contrast enhancement, denoise, upscaling, force-grayscale — is not available, because the build excludes the upstreamexternal-imagesfeature (and itsimage-crate dependency). This keeps extraction faithful and lossless; it does not silently return empty or stub results.CPython only: PyPy and GraalPy are not supported.
License
MIT — see LICENSE for details.
Available Tools
12 toolsadd_pdf_contentAdd content to a PDF sessionA
Append text or a new page to an open create_pdf session (step 2 of 3).
Mutates the in-memory session; nothing is written to disk until save_pdf. Returns JSON {status, session_id, page_count} on success, or {error, code} if the session is missing/inactive or required text fields are absent. Coordinates use PDF points with the origin at the bottom-left of the page.
Call repeatedly to build up pages, then call save_pdf. This only works on a session from create_pdf — to add notes/highlights to an existing PDF file use annotate_pdf instead.
| Name | Required | Description | Default |
|---|---|---|---|
| x | No | Horizontal position in PDF points from the left edge. Required when content_type='text'. | |
| y | No | Vertical position in PDF points from the bottom edge (origin is bottom-left). Required when content_type='text'. | |
| font | No | Font name (e.g. 'Helvetica', 'Courier', 'Times-Roman'). Defaults to Helvetica when omitted. | |
| content | No | Text to draw. Required when content_type='text'. | |
| font_size | No | Font size in points for text content. | |
| session_id | Yes | Session id returned by create_pdf. Must be active. | |
| content_type | Yes | 'text' draws a text string at (x, y) on the current page; 'new_page' appends a blank page and makes it current. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Discloses in-memory mutation, no disk write until save_pdf, return formats, coordinate system, and prerequisites. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three paragraphs with front-loaded purpose, efficient behavioral details, and usage guidelines. No redundant sentences.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers preconditions, mutations, errors, return format, and alternatives. With output schema present, return description is sufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3. Description adds some value (e.g., coordinate origin) but mostly repeats schema info.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'append' and resource 'open create_pdf session' and positions it as step 2 of 3, distinguishing it from sibling tools like annotate_pdf.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says when to use (after create_pdf, before save_pdf) and when not (use annotate_pdf for existing files). Provides clear workflow context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
analyze_pdfAnalyze / validate a PDFARead-onlyIdempotent
Inspect a PDF's structural health or conformance (does not read content).
Returns JSON keyed by the chosen check: validate → {valid, error_count, warning_count}; corruption → {corrupted, corruption_type, severity, found_pages, file_size, errors}; compliance → {level, is_valid, error_count, warning_count, compliance_percentage}; compare → {structurally_equivalent, content_equivalent, similarity_score, difference_count}. Read-only.
Use this to verify a file is well-formed, archival-grade, or identical to another. To read titles/author/page counts use read_pdf; for the text use extract_text.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Path to the PDF file to analyze, relative to the workspace. | |
| check | No | Which analysis to run: 'validate' = structural validity with error/warning counts; 'corruption' = damage severity and type; 'compliance' = PDF/A conformance at compliance_level; 'compare' = diff against compare_path. | validate |
| compare_path | No | Second PDF to diff against. Required when check='compare', ignored otherwise. | |
| compliance_level | No | PDF/A conformance level to test. Used only when check='compliance'. Letter = conformance class (a/b/u), number = PDF/A part (1/2/3). | a1b |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide readOnlyHint and idempotentHint. Description adds that it is read-only and details return JSON structure for each check, going beyond annotations. No contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two paragraphs, well-organized. First paragraph describes output, second provides usage guidance. No fluff or redundancy. Could be slightly more concise but still efficient.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (4 parameters, 2 enums, output schema), the description thoroughly covers behavior, return structure, and use cases. Annotations and schema further enrich completeness.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3. Description adds context by explaining each check value and when compare_path is required. Provides meaning beyond schema enums.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool inspects structural health or conformance, not content. It distinguishes from siblings like read_pdf and extract_text by specifying that it does not read content.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states when to use: verify well-formed, archival-grade, or identical. Also provides exclusions: use read_pdf for titles/author/page counts and extract_text for text. Clear alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
annotate_pdfAnnotate a PDFADestructive
Stamp a sticky note or highlight onto a page of an existing PDF.
Writes the annotated copy to output_path (overwriting any existing file) and returns JSON {status, annotation_type}; out-of-range pages or coordinates outside the page bounds return {error, code}. Coordinates are in PDF points with the origin at the bottom-left.
Use this to mark up a document. To reorder/rotate/overlay whole pages use manipulate_pdf; to author a new PDF use create_pdf.
| Name | Required | Description | Default |
|---|---|---|---|
| x | Yes | Horizontal anchor in PDF points from the left edge. | |
| y | Yes | Vertical anchor in PDF points from the bottom edge (origin is bottom-left). | |
| page | Yes | 0-based index of the page to annotate. | |
| width | No | Highlight width in points. Used only for 'highlight'. | |
| height | No | Highlight height in points. Used only for 'highlight'. | |
| contents | No | Note text for a 'text' annotation. Ignored for 'highlight'. | |
| input_path | Yes | Source PDF to annotate, relative to the workspace. | |
| output_path | Yes | Destination .pdf path; overwritten if it already exists. | |
| annotation_type | Yes | 'text' adds a sticky-note marker at (x, y); 'highlight' draws a highlight rectangle of width×height anchored at (x, y). |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate destructiveHint=true and readOnlyHint=false. The description adds that it overwrites the output file, returns JSON with status/error for out-of-range pages or coordinates, and explains the coordinate system. This provides useful context beyond annotations, though it does not detail potential side effects like file locking.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences plus a brief usage note, conveying all essential information without redundancy. It front-loads the core action and follows with behavior and alternatives, making it efficient and easy to process.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the detailed input schema and annotations, the description covers all necessary context: purpose, behavior, error handling, coordinate system, and alternatives. It is sufficiently complete for an agent to select and invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Input schema has 100% coverage, but the description adds value by explaining the return format ({status, annotation_type} or {error, code}) and clarifying that width/height only apply to 'highlight'. This goes beyond the schema descriptions, compensating for the high coverage baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool stamps a sticky note or highlight onto an existing PDF page, with specific verb 'stamp' and resource 'page of an existing PDF'. It distinguishes from sibling tools by mentioning manipulate_pdf for page reordering and create_pdf for authoring new PDFs, making the purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use: 'Use this to mark up a document.' It provides clear alternatives: 'To reorder/rotate/overlay whole pages use manipulate_pdf; to author a new PDF use create_pdf.' It also notes that output_path is overwritten, guiding correct invocation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
convert_pdfConvert PDF to text representationARead-onlyIdempotent
Convert a whole PDF into a text representation for downstream LLM use.
Returns JSON: {content, format} for 'markdown', or {chunks, format} for 'chunks'/'rag' (each chunk carries its index and page_numbers; rag chunks add token_estimate and heading_context). Read-only.
Use this when you need structure or chunking. If you just want the raw reading text use extract_text; for per-run coordinates use extract_entities.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Path to the PDF file, relative to the configured workspace. | |
| format | Yes | Output representation: 'markdown' = one structured Markdown document; 'chunks' = fixed-size token windows; 'rag' = heading-aware semantic chunks for retrieval pipelines. | |
| overlap | No | Token overlap carried between consecutive chunks. Applies to format='chunks' only; ignored for 'markdown' and 'rag'. | |
| password | No | User password to unlock an encrypted PDF before conversion. | |
| max_tokens | No | Target maximum tokens per chunk. Applies to format='chunks' only; ignored for 'markdown' and 'rag' (rag uses heading-aware semantic chunking with a fixed internal budget). |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and idempotentHint. The description adds detailed return structure per format (JSON with content/format or chunks with index/page_numbers/heading_context), and confirms read-only nature, exceeding what annotations provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise: two paragraphs. First paragraph covers purpose and return format. Second paragraph provides usage guidelines. No unnecessary words, front-loaded with key information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 5 parameters (2 required), output schema present, and sibling tools, the description covers all essential aspects: purpose, return format, usage guidance, and behavioral notes (read-only). It is complete and useful for an agent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% so each parameter is documented. The description does not add additional parameter-level semantics beyond the schema, but it explains how parameter choices affect output format (e.g., overlap applies only to chunks). This is adequate for the baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool converts a whole PDF to a text representation for LLM use, specifying verb (convert) and resource (PDF). It distinguishes from siblings like extract_text and extract_entities by mentioning alternative use cases.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states when to use this tool ('when you need structure or chunking') and when to use alternatives ('for raw reading text use extract_text; for per-run coordinates use extract_entities'). Provides clear decision guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_pdfStart a PDF creation sessionA
Open an in-memory PDF building session; the first step of authoring a PDF.
Returns JSON {session_id, status, page_size}. No file is written here — this only allocates a session (with one blank starting page) held in server memory and subject to a TTL. Not idempotent: each call creates a new session.
Workflow: create_pdf → add_pdf_content (text / new pages, repeatable) → save_pdf (writes the file and closes the session). To annotate or fill an existing PDF instead of authoring one, use annotate_pdf or manage_forms.
| Name | Required | Description | Default |
|---|---|---|---|
| title | Yes | Document title; stored in the PDF metadata on save. | |
| author | No | Document author; stored in the PDF metadata on save. | |
| page_size | No | Page size for every page in this document. | a4 |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds significant context beyond annotations: returns session_id/status/page_size, no file written, session in memory with TTL, not idempotent. Annotations already indicate no idempotency, but description adds specific behavioral detail.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Efficient and well-structured: first sentence states purpose, then return info, then workflow and alternatives. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers purpose, workflow, return values, behavioral notes (TTL, idempotency), and alternatives. Adequate for a simple session creation tool with good schema and output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Input schema has 100% description coverage for all three parameters, so description adds minimal extra meaning. Schema already defines title, author, page_size clearly.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states it opens an in-memory PDF building session as the first step of authoring a PDF. Distinguishes from siblings by outlining the workflow and explicitly mentioning alternatives for annotating or filling existing PDFs.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit workflow (create_pdf → add_pdf_content → save_pdf) and warns against using it for annotating/filling existing PDFs, directing to annotate_pdf or manage_forms.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
extract_entitiesExtract positioned text runsARead-onlyIdempotent
Extract every text run of a PDF together with its layout geometry.
Returns JSON {path, entities, entity_count, page_count} where each entity is {text, page (0-based), x, y, font_size, font_name}. Coordinates are in PDF points with the origin at the bottom-left of the page. Read-only.
Use this for layout-aware tasks (table reconstruction, positional lookup, locating a label on the page). If you only need the reading text without coordinates, use extract_text; for Markdown or RAG chunks use convert_pdf.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Path to the PDF file, relative to the configured workspace. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide readOnlyHint=true and idempotentHint=true. The description adds valuable behavioral context: output structure (JSON with fields), coordinate system (PDF points, bottom-left origin), and explicitly states 'Read-only.' No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences: first sentence states purpose, second explains output, third gives usage guidelines. It is concise, front-loaded with key information, and every sentence serves a purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description explains the output structure in detail (JSON with path, entities, entity_count, page_count, and entity fields). Output schema exists but description covers it sufficiently. For a 1-parameter tool, all necessary context is provided.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with a clear parameter description in the schema itself. The tool description does not repeat or add significant value beyond the schema's definition of the 'path' parameter. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Extract every text run of a PDF together with its layout geometry.' It distinguishes from siblings by explicitly naming alternatives: 'use extract_text' for reading text without coordinates, and 'use convert_pdf' for Markdown or RAG chunks.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit usage context: 'Use this for layout-aware tasks...' and clearly states when not to use it by specifying alternatives, e.g., 'If you only need the reading text without coordinates, use extract_text; for Markdown or RAG chunks use convert_pdf.'
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
extract_textExtract plain textARead-onlyIdempotent
Extract the raw, unformatted text of a PDF as a single string.
Returns JSON {text, page_count} (plus page when a specific page was
requested). Read-only.
Use this when you want the plain reading text. If you need Markdown structure or chunking for LLM/RAG pipelines use convert_pdf; if you need each text run with its on-page coordinates and font use extract_entities.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | 0-based page index to extract. Omit to extract every page joined by newlines. Out-of-range indices return an error. | |
| path | Yes | Path to the PDF file, relative to the configured workspace. | |
| password | No | User password to unlock an encrypted PDF before extraction. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Even though annotations already mark readOnlyHint=true and idempotentHint=true, the description adds further behavioral context. It states the tool is 'read-only' and describes the return JSON structure ({text, page_count} and 'page' when a specific page is requested). It also mentions that out-of-range page indices return an error. This goes beyond the annotations without contradicting them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is exceptionally concise: three sentences. The first sentence states purpose, the second describes return format and readonly nature, and the third provides usage alternatives. No filler or redundant information. Every sentence earns its place, and the structure is front-loaded with the core action.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity (3 parameters, 1 required, simple output schema), the description is complete. It covers return format, error behavior (out-of-range page), and usage context vs. siblings. The output schema exists but the description still explains return fields. All necessary information for correct invocation is present.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description adds some extra context beyond the schema: it mentions that 'page' parameter accepts a 0-based index and that out-of-range values return an error (already partly in schema but reinforced). It also implies that 'password' is for encrypted PDFs. However, it does not detail each parameter extensively; the schema already does that well. The added value justifies one point above baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Extract the raw, unformatted text of a PDF as a single string.' It identifies the verb (extract), resource (raw text of PDF), and output format (a single string in JSON). The title 'Extract plain text' reinforces this. It also distinguishes from siblings by specifying when to use convert_pdf (for Markdown structure) and extract_entities (for coordinates and font). This is specific and differentiates among 12 sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says 'Use this when you want the plain reading text.' and provides clear alternatives: 'if you need Markdown structure or chunking for LLM/RAG pipelines use convert_pdf; if you need each text run with its on-page coordinates and font use extract_entities.' This gives concrete when-to-use and when-not-to-use guidance, making it easy for the agent to select the correct tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
manage_formsManage PDF form fieldsADestructive
Create, fill, read or validate PDF form fields.
Returns JSON per operation: create→{status, fields_created}; fill→{status, fields_filled}; read→{path, fields, page_count}; validate→{valid, fields}. 'create'/'fill' write output_path (overwriting); 'read'/'validate' are read-only computations.
Honest limitations: 'fill' lays the values into a new overlay at computed positions rather than mapping them onto the original AcroForm widgets; 'read' returns the page's text runs (not declared AcroForm field objects); 'validate' currently enforces only a non-empty (required) rule per value. For page-structure edits use manipulate_pdf; to read prose use extract_text.
| Name | Required | Description | Default |
|---|---|---|---|
| fields | No | Field definitions for 'create'. Each: {name, type:'text', x, y, width, height (points), default_value?}. | |
| values | No | Map of field name to value. Required for 'fill' and 'validate'. | |
| operation | Yes | 'create' a new PDF with text fields; 'fill' values onto a copy of an existing PDF; 'read' the text content of a form; 'validate' supplied values. 'read' and 'validate' do not write a file. | |
| input_path | No | Source PDF. Required for 'fill', 'read' and 'validate'; unused for 'create'. | |
| output_path | No | Destination .pdf path (overwritten if present). Required for 'create' and 'fill'; unused for 'read'/'validate'. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description honestly discloses limitations: 'fill' creates a new overlay rather than mapping onto original AcroForm widgets, 'read' returns text runs not declared AcroForm field objects, and 'validate' only enforces non-empty rule. Annotations already indicate destructiveHint=true, but the description adds valuable context beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a clear overview, return types listed by operation, behavioral details, limitations, and sibling references. Every sentence is informative and earns its place. It is concise yet complete.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (4 operations, 5 parameters, output schema, annotations), the description covers all essential aspects: return values per operation, side effects (overwriting), limitations, and usage context. No gaps remain for an AI agent to misuse the tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3. However, the description adds meaningful context: it explains which parameters are required per operation and provides detailed format for 'fields' (e.g., {name, type:'text', x, y, width, height, default_value?}). This goes beyond the schema's minimal descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description explicitly states 'Create, fill, read or validate PDF form fields,' clearly identifying the verb (multiple operations) and resource (PDF form fields). It distinguishes from sibling tools like manipulate_pdf and extract_text in the last sentence.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit guidance on when to use which operation (e.g., 'For page-structure edits use manipulate_pdf; to read prose use extract_text') and notes that 'create'/'fill' write and 'read'/'validate' are read-only. It also explains required parameters for each operation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
manipulate_pdfRestructure PDF pagesADestructive
Restructure the pages of existing PDF file(s) and write a new PDF.
Each operation writes to output_path (overwriting any existing file) and returns JSON {status, operation}; on a missing required argument it returns {error, code}. Per-operation requirements: merge→input_paths; rotate→degrees; extract_pages→page_indices; overlay→overlay_path; split→output_path is a directory. Page indices are 0-based.
Use this for page-level structure. To stamp notes/highlights use annotate_pdf; to fill form fields use manage_forms; to encrypt use secure_pdf.
| Name | Required | Description | Default |
|---|---|---|---|
| degrees | No | Clockwise rotation in degrees (e.g. 90, 180, 270). Required for 'rotate'. | |
| operation | Yes | Page operation: 'split' one PDF into per-page files; 'merge' several PDFs into one; 'rotate' all pages; 'extract_pages' a subset; 'reverse' page order; 'overlay' one PDF on top of another. | |
| input_path | No | Source PDF. Required for every operation except 'merge' (which uses input_paths). | |
| input_paths | No | Ordered list of PDFs to combine. Required for 'merge'. | |
| output_path | No | Output location, overwritten if it exists. For 'split' this is an existing directory; for all other operations a .pdf file. | |
| overlay_path | No | PDF stamped on top of input_path. Required for 'overlay'. | |
| page_indices | No | 0-based page indices to keep, in order. Required for 'extract_pages'. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations indicate destructiveHint=true and readOnlyHint=false. The description reinforces this by stating it 'overwrites any existing file' and describes return JSON for success and error cases. It adds specific behavioral details beyond annotations, such as the return format and overwrite behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise (6 sentences), well-structured, and front-loaded with purpose. Each sentence earns its place: purpose, return format, per-operation requirements, sibling links. No fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (6 operations, 7 parameters), the description covers all operations and required parameters. It mentions return format, and with an output schema present (context signals), further details are not needed. It is fully adequate.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so every parameter already has a description. The tool description adds value by grouping parameters per operation in a compact summary, which aids quick understanding of dependencies. This goes beyond the schema by providing operational context.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states that the tool restructures PDF pages and writes new PDFs, listing six specific operations. It distinguishes itself from siblings by explicitly saying 'Use this for page-level structure' and pointing to alternatives for other tasks (annotate_pdf, manage_forms, secure_pdf).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit when-to-use guidance ('page-level structure') and when-not-to-use with sibling references. It also lists per-operation required parameters (e.g., 'merge→input_paths'), helping the agent decide which parameters are needed for each operation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_pdfRead PDF metadataARead-onlyIdempotent
Read a single PDF's document-level metadata without parsing its content.
Returns a JSON object with: page_count, is_encrypted, version, title,
author, subject, keywords, and (when include_page_details=true) a pages
array of {index, width, height, rotation}. Read-only: never modifies the
file.
Use this to inspect what a PDF is before deciding how to process it. For structural validation, corruption/PDF-A checks, or comparing two files use analyze_pdf instead; for the actual text use extract_text. Encrypted files without a password return {is_encrypted, locked, message} rather than metadata.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Path to the PDF file, relative to the configured workspace. | |
| password | No | User password to unlock an encrypted PDF. Omit for unencrypted files; if omitted on an encrypted file the tool reports it as locked instead of failing. | |
| include_page_details | No | When true, also return per-page width, height (in PDF points) and rotation. Off by default to keep the response small. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and idempotentHint; description reinforces read-only nature, details return object structure, and explains behavior for encrypted files without password. No contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Five sentences with clear structure: purpose, return format, read-only emphasis, use cases with alternatives, and edge case handling. No unnecessary words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers tool purpose, return data, read-only behavior, usage guidance with alternatives, and edge cases. Output schema exists; description complements it fully. No gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, but description adds context: explains include_page_details reduces response size and how password parameter affects output for encrypted files. Adds value beyond schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states 'Read a single PDF's document-level metadata' with specific verb and resource, distinguishes from sibling tools like analyze_pdf and extract_text, and lists exact return fields.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states when to use ('inspect what a PDF is before deciding how to process it') and when not to (use analyze_pdf for structural validation, extract_text for actual text). Also covers edge case of encrypted files.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
save_pdfSave and close a PDF sessionADestructive
Render an open create_pdf session to a PDF file (step 3 of 3, terminal).
Builds a Document from the session's accumulated pages, writes it to output_path (overwriting any existing file), then deletes the session — so the session_id is no longer usable afterwards. Returns JSON {status, path, page_count}, or {error, code} if the session is missing.
Only finalizes sessions created via create_pdf/add_pdf_content. To encrypt an already-saved PDF use secure_pdf; to add annotations use annotate_pdf.
| Name | Required | Description | Default |
|---|---|---|---|
| session_id | Yes | Session id returned by create_pdf to finalize. | |
| output_path | Yes | Destination .pdf path inside the workspace. An existing file at this path is overwritten. | |
| user_password | No | If set together with owner_password, the saved PDF is encrypted; this is the password required to open it. | |
| owner_password | No | Owner/permissions password. Encryption is applied only when both user_password and owner_password are provided. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses key behaviors beyond annotations: overwrites existing file, deletes the session making session_id unusable, and returns JSON {status, path, page_count} or error. Annotations already indicate destructiveHint=true, but the description adds specific details. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is five well-structured sentences. It front-loads the core action, then explains behavior, return format, constraints, and alternatives. No redundant or extraneous information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity and available annotations, the description covers all essential aspects: purpose, lifecycle (step 3 of 3), behavior, return values, error handling, prerequisites, and alternatives. It is complete for an agent to understand when and how to invoke the tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3. The description adds contextual meaning: explains that session_id must come from create_pdf/add_pdf_content, that output_path can overwrite, and that encryption only applies when both passwords are provided. This adds value beyond the schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Render an open create_pdf session to a PDF file (step 3 of 3, terminal).' It specifies the verb (render/save), resource (PDF session), and its terminal nature. It distinguishes from siblings by noting that only sessions from create_pdf/add_pdf_content are finalized, and mentions alternative tools for encryption (secure_pdf) and annotations (annotate_pdf).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit usage guidelines are provided: 'Only finalizes sessions created via create_pdf/add_pdf_content.' It also gives when-not-to-use: 'To encrypt an already-saved PDF use secure_pdf; to add annotations use annotate_pdf.' This clearly directs the agent to alternatives and conditions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
secure_pdfEncrypt / inspect PDF securityADestructive
Encrypt a PDF, report its encryption status, or verify its signatures.
Returns JSON per operation: encrypt→{status, operation, page_count, note}; permissions→{path, is_encrypted, unlocked, permissions}; verify_signatures→ {path, signatures, signature_count}. 'permissions' and 'verify_signatures' are read-only; 'encrypt' writes output_path (overwriting).
Caveat: 'encrypt' rebuilds the document from its text, preserving content and layout but possibly dropping images, embedded fonts and vector graphics (the current API has no in-place encryption). To encrypt a PDF you are authoring, pass the passwords to save_pdf instead.
| Name | Required | Description | Default |
|---|---|---|---|
| password | No | Password used to unlock the file when checking 'permissions' on an encrypted PDF. Unused by other operations. | |
| operation | Yes | 'encrypt' writes a password-protected copy; 'permissions' reports encryption status; 'verify_signatures' checks digital signatures. Only 'encrypt' writes a file. | |
| input_path | No | Source PDF. Required for all three operations. | |
| output_path | No | Destination .pdf for the encrypted copy (overwritten if present). Required for 'encrypt'; unused otherwise. | |
| user_password | No | Open password for the encrypted copy. Required for 'encrypt'. | |
| owner_password | No | Owner/permissions password. Required for 'encrypt'. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare destructiveHint=true and readOnlyHint=false. Description adds detailed behavioral context: encrypt overwrites output_path, rebuilds document and may drop images/embedded fonts/vector graphics. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Description is somewhat lengthy but well-structured with clear sections. Front-loaded with operation summary, then output details, then caveats. Slightly verbose but all sentences add value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Tool has 6 parameters, output schema exists describing return JSON per operation. Description covers output structure, caveats, and usage alternatives. Complete and actionable for an agent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 100% schema coverage, baseline is 3. Description adds value by explaining which parameters are required for each operation, and the overwriting behavior of output_path. Goes beyond schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states three distinct operations (encrypt, report encryption status, verify signatures) with specific verbs and resources, and distinguishes from sibling tool save_pdf for authoring use cases.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says when to use each operation, provides caveats about image/font loss for encrypt, and recommends alternative save_pdf for authoring PDFs. Full guidance on when-not-to-use.
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. Dates show when Glama detected each change.
1 tool update
- Changed
convert_pdf1 field changed- changed
Input schema / properties / max_tokens / descriptionBefore"Target maximum tokens per chunk. Applies to format='chunks' and 'rag' only; ignored for 'markdown'."
After"Target maximum tokens per chunk. Applies to format='chunks' only; ignored for 'markdown' and 'rag' (rag uses heading-aware semantic chunking with a fixed internal budget)."
12 tool updates
v0.12.0- Changed
add_pdf_content8 fields changed- added
Input schema / properties / content / description"Text to draw. Required when content_type='text'."
- added
Input schema / properties / content_type / description"'text' draws a text string at (x, y) on the current page; 'new_page' appends a blank page and makes it current."
- added
Input schema / properties / content_type / enum[ "text", "new_page" ]
- added
Input schema / properties / font / description"Font name (e.g. 'Helvetica', 'Courier', 'Times-Roman'). Defaults to Helvetica when omitted."
- added
Input schema / properties / font_size / description"Font size in points for text content."
- added
Input schema / properties / session_id / description"Session id returned by create_pdf. Must be active."
- added
Input schema / properties / x / description"Horizontal position in PDF points from the left edge. Required when content_type='text'."
- added
Input schema / properties / y / description"Vertical position in PDF points from the bottom edge (origin is bottom-left). Required when content_type='text'."
- Changed
analyze_pdf6 fields changed- added
Input schema / properties / check / description"Which analysis to run: 'validate' = structural validity with error/warning counts; 'corruption' = damage severity and type; 'compliance' = PDF/A conformance at compliance_level; 'compare' = diff against compare_path."
- added
Input schema / properties / check / enum[ "validate", "corruption", "compliance", "compare" ]
- added
Input schema / properties / compare_path / description"Second PDF to diff against. Required when check='compare', ignored otherwise."
- added
Input schema / properties / compliance_level / description"PDF/A conformance level to test. Used only when check='compliance'. Letter = conformance class (a/b/u), number = PDF/A part (1/2/3)."
- added
Input schema / properties / compliance_level / enum[ "a1a", "a1b", "a2a", "a2b", "a2u", "a3a", "a3b", "a3u" ]
- added
Input schema / properties / path / description"Path to the PDF file to analyze, relative to the workspace."
- Changed
annotate_pdf10 fields changed- added
Input schema / properties / annotation_type / description"'text' adds a sticky-note marker at (x, y); 'highlight' draws a highlight rectangle of width×height anchored at (x, y)."
- added
Input schema / properties / annotation_type / enum[ "text", "highlight" ]
- added
Input schema / properties / contents / description"Note text for a 'text' annotation. Ignored for 'highlight'."
- added
Input schema / properties / height / description"Highlight height in points. Used only for 'highlight'."
- added
Input schema / properties / input_path / description"Source PDF to annotate, relative to the workspace."
- added
Input schema / properties / output_path / description"Destination .pdf path; overwritten if it already exists."
- added
Input schema / properties / page / description"0-based index of the page to annotate."
- added
Input schema / properties / width / description"Highlight width in points. Used only for 'highlight'."
- added
Input schema / properties / x / description"Horizontal anchor in PDF points from the left edge."
- added
Input schema / properties / y / description"Vertical anchor in PDF points from the bottom edge (origin is bottom-left)."
- Changed
convert_pdf5 fields changed- added
Input schema / properties / format / description"Output representation: 'markdown' = one structured Markdown document; 'chunks' = fixed-size token windows; 'rag' = heading-aware semantic chunks for retrieval pipelines."
- added
Input schema / properties / max_tokens / description"Target maximum tokens per chunk. Applies to format='chunks' and 'rag' only; ignored for 'markdown'."
- added
Input schema / properties / overlap / description"Token overlap carried between consecutive chunks. Applies to format='chunks' only; ignored for 'markdown' and 'rag'."
- added
Input schema / properties / password / description"User password to unlock an encrypted PDF before conversion."
- added
Input schema / properties / path / description"Path to the PDF file, relative to the configured workspace."
- Changed
create_pdf4 fields changed- added
Input schema / properties / author / description"Document author; stored in the PDF metadata on save."
- added
Input schema / properties / page_size / description"Page size for every page in this document."
- added
Input schema / properties / page_size / enum[ "a4", "a4_landscape", "letter", "letter_landscape", "legal", "legal_landscape" ]
- added
Input schema / properties / title / description"Document title; stored in the PDF metadata on save."
- Changed
extract_entities1 field changed- added
Input schema / properties / path / description"Path to the PDF file, relative to the configured workspace."
- Changed
extract_text3 fields changed- added
Input schema / properties / page / description"0-based page index to extract. Omit to extract every page joined by newlines. Out-of-range indices return an error."
- added
Input schema / properties / password / description"User password to unlock an encrypted PDF before extraction."
- added
Input schema / properties / path / description"Path to the PDF file, relative to the configured workspace."
- Changed
manage_forms6 fields changed- added
Input schema / properties / fields / description"Field definitions for 'create'. Each: {name, type:'text', x, y, width, height (points), default_value?}." - added
Input schema / properties / input_path / description"Source PDF. Required for 'fill', 'read' and 'validate'; unused for 'create'."
- added
Input schema / properties / operation / description"'create' a new PDF with text fields; 'fill' values onto a copy of an existing PDF; 'read' the text content of a form; 'validate' supplied values. 'read' and 'validate' do not write a file."
- added
Input schema / properties / operation / enum[ "create", "fill", "read", "validate" ]
- added
Input schema / properties / output_path / description"Destination .pdf path (overwritten if present). Required for 'create' and 'fill'; unused for 'read'/'validate'."
- added
Input schema / properties / values / description"Map of field name to value. Required for 'fill' and 'validate'."
- Changed
manipulate_pdf8 fields changed- added
Input schema / properties / degrees / description"Clockwise rotation in degrees (e.g. 90, 180, 270). Required for 'rotate'."
- added
Input schema / properties / input_path / description"Source PDF. Required for every operation except 'merge' (which uses input_paths)."
- added
Input schema / properties / input_paths / description"Ordered list of PDFs to combine. Required for 'merge'."
- added
Input schema / properties / operation / description"Page operation: 'split' one PDF into per-page files; 'merge' several PDFs into one; 'rotate' all pages; 'extract_pages' a subset; 'reverse' page order; 'overlay' one PDF on top of another."
- added
Input schema / properties / operation / enum[ "split", "merge", "rotate", "extract_pages", "reverse", "overlay" ]
- added
Input schema / properties / output_path / description"Output location, overwritten if it exists. For 'split' this is an existing directory; for all other operations a .pdf file."
- added
Input schema / properties / overlay_path / description"PDF stamped on top of input_path. Required for 'overlay'."
- added
Input schema / properties / page_indices / description"0-based page indices to keep, in order. Required for 'extract_pages'."
- Changed
read_pdf3 fields changed- added
Input schema / properties / include_page_details / description"When true, also return per-page width, height (in PDF points) and rotation. Off by default to keep the response small."
- added
Input schema / properties / password / description"User password to unlock an encrypted PDF. Omit for unencrypted files; if omitted on an encrypted file the tool reports it as locked instead of failing."
- added
Input schema / properties / path / description"Path to the PDF file, relative to the configured workspace."
- Changed
save_pdf4 fields changed- added
Input schema / properties / output_path / description"Destination .pdf path inside the workspace. An existing file at this path is overwritten."
- added
Input schema / properties / owner_password / description"Owner/permissions password. Encryption is applied only when both user_password and owner_password are provided."
- added
Input schema / properties / session_id / description"Session id returned by create_pdf to finalize."
- added
Input schema / properties / user_password / description"If set together with owner_password, the saved PDF is encrypted; this is the password required to open it."
- Changed
secure_pdf7 fields changed- added
Input schema / properties / input_path / description"Source PDF. Required for all three operations."
- added
Input schema / properties / operation / description"'encrypt' writes a password-protected copy; 'permissions' reports encryption status; 'verify_signatures' checks digital signatures. Only 'encrypt' writes a file."
- added
Input schema / properties / operation / enum[ "encrypt", "permissions", "verify_signatures" ]
- added
Input schema / properties / output_path / description"Destination .pdf for the encrypted copy (overwritten if present). Required for 'encrypt'; unused otherwise."
- added
Input schema / properties / owner_password / description"Owner/permissions password. Required for 'encrypt'."
- added
Input schema / properties / password / description"Password used to unlock the file when checking 'permissions' on an encrypted PDF. Unused by other operations."
- added
Input schema / properties / user_password / description"Open password for the encrypted copy. Required for 'encrypt'."
12 tool updates
v0.11.0- First observed
add_pdf_content - First observed
analyze_pdf - First observed
annotate_pdf - First observed
convert_pdf - First observed
create_pdf - First observed
extract_entities - First observed
extract_text - First observed
manage_forms - First observed
manipulate_pdf - First observed
read_pdf - First observed
save_pdf - First observed
secure_pdf
TDQS
Each tool targets a distinct operation (creation workflow, metadata, text extraction, layout analysis, annotation, form management, page manipulation, security, conversion, structural analysis). Descriptions clearly differentiate overlapping areas like extract_text vs convert_pdf vs extract_entities.
All 12 tools follow a consistent verb_noun snake_case pattern (e.g., create_pdf, extract_text, secure_pdf). No mixed conventions or ambiguous names.
12 tools cover the full PDF lifecycle without bloat. Each tool has a clear purpose and the count is well-scoped for a PDF manipulation server.
The surface covers creation, reading, editing, conversion, security, and analysis. Minor gaps like lacking an explicit page deletion tool (handled via manipulate_pdf's extract_pages) or OCR, but core workflows are complete.
Maintenance
Related MCP Connectors
Privacy-first PDF tools over MCP: merge, split, rotate, delete, compress, protect, inspect.
Generate PDFs from templates via AI chat. Works with Claude, ChatGPT, Cursor, and any MCP client.
Hosted MCP server: convert PDFs to clean, LLM-ready Markdown with tables, formulas and OCR.
MCP server for the PDFGate API. Generate PDFs, manage documents and handle e-signatures.
Related MCP Servers
- AlicenseAqualityBmaintenanceMCP server for seamless document format conversion using Pandoc, supporting Markdown, HTML, PDF, DOCX (.docx), csv and more.1579MIT
- -licenseNot gradedqualityNot gradedmaintenanceEnables 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.-
- AlicenseAqualityCmaintenanceMCP server for PDF manipulation — create PDFs from Markdown with tables and formatting, fill forms, merge, split, encrypt, add QR codes, and more. 16 tools, zero external binaries, TypeScript-native. Install with npx -y @aryanbv/pdf-toolkit-mcp.222909MIT

Nutrient PDF MCP Serverofficial
AlicenseBqualityFmaintenanceEnables low-level PDF object-tree inspection and debugging through natural language, with lazy loading for token efficiency.24MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/bzsanti/oxidize-python'
If you have feedback or need assistance with the MCP directory API, please join our Discord server