Skip to main content
Glama

oxidize-pdf

PyPI version CI License: MIT Python Typed MCP

oxidize-python MCP server

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 agents

Platforms: 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-mcp

The 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_pdf

Read metadata — page count, version, encryption status, title, author

extract_text

Extract text from all pages or a specific page

convert_pdf

Convert to markdown, chunks, or RAG-optimized format

create_pdf

Create a new PDF with optional metadata

save_pdf

Save a session to disk, with optional encryption

add_content

Add pages, text, and graphics to a session

annotate_pdf

Add text annotations and highlights

manipulate_pdf

Split, merge, rotate, extract pages, reverse, overlay

manage_forms

Create, fill, read, and validate form fields

secure_pdf

Encrypt, check permissions, verify signatures

extract_entities

Extract structured entities from pages

analyze_pdf

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-mcp

The server is configured entirely through environment variables:

Variable

Default

Purpose

OXIDIZE_WORKSPACE

~/Documents/oxidize-mcp

Sandbox root; all paths must resolve inside it.

OXIDIZE_ALLOWED_PATHS

(none)

Comma-separated extra directories allowed outside the workspace.

OXIDIZE_MAX_FILE_SIZE_MB

100

Reject input PDFs larger than this on disk.

OXIDIZE_MAX_PAGES

10000

Reject documents with more pages than this before any extraction work.

OXIDIZE_MAX_OUTPUT_BYTES

10485760

Cap the serialized size of a tool's JSON response (10 MB).

OXIDIZE_MAX_SESSIONS

10

Maximum concurrent stateful PDF-creation sessions.

OXIDIZE_MAX_SESSION_BYTES

10485760

Cap the content a single session may accumulate (10 MB).

OXIDIZE_SESSION_TIMEOUT

3600

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 pages

Graphics

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_BOLD

Error 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-mcp

Available tools

Tool

Description

read_pdf

Open a PDF and get metadata (pages, version, encryption)

extract_text

Extract text content from PDF pages

convert_pdf

Convert between PDF versions

analyze_pdf

Analyze structure, fonts, images, and compliance

extract_entities

Extract images and digital signatures

manipulate_pdf

Split, merge, rotate, extract, and reorder pages

annotate_pdf

Add text annotations, highlights, and stamps

manage_forms

Create, fill, and read PDF form fields

secure_pdf

Encrypt, decrypt, and set document permissions

create_pdf

Create a new PDF document with pages

add_pdf_content

Add text, shapes, and images to pages

save_pdf

Save the document to file or bytes

Resources

  • oxidize://fonts — Available built-in PDF fonts

  • oxidize://page-sizes — Standard page sizes with dimensions

  • oxidize://capabilities — Server capabilities and tool listing

  • oxidize://version — Version information

  • oxidize://workspace — PDF files in the workspace directory

  • oxidize://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_pdf extracts each embedded image as-is (e.g. a DCTDecode JPEG is written byte-for-byte). Image preprocessing — auto rotation-correction, contrast enhancement, denoise, upscaling, force-grayscale — is not available, because the build excludes the upstream external-images feature (and its image-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 tools
add_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.

ParametersJSON Schema
NameRequiredDescriptionDefault
xNoHorizontal position in PDF points from the left edge. Required when content_type='text'.
yNoVertical position in PDF points from the bottom edge (origin is bottom-left). Required when content_type='text'.
fontNoFont name (e.g. 'Helvetica', 'Courier', 'Times-Roman'). Defaults to Helvetica when omitted.
contentNoText to draw. Required when content_type='text'.
font_sizeNoFont size in points for text content.
session_idYesSession id returned by create_pdf. Must be active.
content_typeYes'text' draws a text string at (x, y) on the current page; 'new_page' appends a blank page and makes it current.

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.7/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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 PDFA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYesPath to the PDF file to analyze, relative to the workspace.
checkNoWhich 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_pathNoSecond PDF to diff against. Required when check='compare', ignored otherwise.
compliance_levelNoPDF/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

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.6/5.0
Behavior4/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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 PDFA
Destructive

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
xYesHorizontal anchor in PDF points from the left edge.
yYesVertical anchor in PDF points from the bottom edge (origin is bottom-left).
pageYes0-based index of the page to annotate.
widthNoHighlight width in points. Used only for 'highlight'.
heightNoHighlight height in points. Used only for 'highlight'.
contentsNoNote text for a 'text' annotation. Ignored for 'highlight'.
input_pathYesSource PDF to annotate, relative to the workspace.
output_pathYesDestination .pdf path; overwritten if it already exists.
annotation_typeYes'text' adds a sticky-note marker at (x, y); 'highlight' draws a highlight rectangle of width×height anchored at (x, y).

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.7/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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 representationA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYesPath to the PDF file, relative to the configured workspace.
formatYesOutput representation: 'markdown' = one structured Markdown document; 'chunks' = fixed-size token windows; 'rag' = heading-aware semantic chunks for retrieval pipelines.
overlapNoToken overlap carried between consecutive chunks. Applies to format='chunks' only; ignored for 'markdown' and 'rag'.
passwordNoUser password to unlock an encrypted PDF before conversion.
max_tokensNoTarget 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

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.7/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
titleYesDocument title; stored in the PDF metadata on save.
authorNoDocument author; stored in the PDF metadata on save.
page_sizeNoPage size for every page in this document.a4

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.5/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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 runsA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYesPath to the PDF file, relative to the configured workspace.

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.7/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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 textA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault
pageNo0-based page index to extract. Omit to extract every page joined by newlines. Out-of-range indices return an error.
pathYesPath to the PDF file, relative to the configured workspace.
passwordNoUser password to unlock an encrypted PDF before extraction.

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.9/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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

The description clearly states the tool's 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.

Usage Guidelines5/5

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 fieldsA
Destructive

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
fieldsNoField definitions for 'create'. Each: {name, type:'text', x, y, width, height (points), default_value?}.
valuesNoMap of field name to value. Required for 'fill' and 'validate'.
operationYes'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_pathNoSource PDF. Required for 'fill', 'read' and 'validate'; unused for 'create'.
output_pathNoDestination .pdf path (overwritten if present). Required for 'create' and 'fill'; unused for 'read'/'validate'.

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.9/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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 pagesA
Destructive

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
degreesNoClockwise rotation in degrees (e.g. 90, 180, 270). Required for 'rotate'.
operationYesPage 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_pathNoSource PDF. Required for every operation except 'merge' (which uses input_paths).
input_pathsNoOrdered list of PDFs to combine. Required for 'merge'.
output_pathNoOutput location, overwritten if it exists. For 'split' this is an existing directory; for all other operations a .pdf file.
overlay_pathNoPDF stamped on top of input_path. Required for 'overlay'.
page_indicesNo0-based page indices to keep, in order. Required for 'extract_pages'.

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.7/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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 metadataA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYesPath to the PDF file, relative to the configured workspace.
passwordNoUser 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_detailsNoWhen true, also return per-page width, height (in PDF points) and rotation. Off by default to keep the response small.

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.9/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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 sessionA
Destructive

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
session_idYesSession id returned by create_pdf to finalize.
output_pathYesDestination .pdf path inside the workspace. An existing file at this path is overwritten.
user_passwordNoIf set together with owner_password, the saved PDF is encrypted; this is the password required to open it.
owner_passwordNoOwner/permissions password. Encryption is applied only when both user_password and owner_password are provided.

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.9/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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

The description clearly states the tool's 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.

Usage Guidelines5/5

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 securityA
Destructive

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
passwordNoPassword used to unlock the file when checking 'permissions' on an encrypted PDF. Unused by other operations.
operationYes'encrypt' writes a password-protected copy; 'permissions' reports encryption status; 'verify_signatures' checks digital signatures. Only 'encrypt' writes a file.
input_pathNoSource PDF. Required for all three operations.
output_pathNoDestination .pdf for the encrypted copy (overwritten if present). Required for 'encrypt'; unused otherwise.
user_passwordNoOpen password for the encrypted copy. Required for 'encrypt'.
owner_passwordNoOwner/permissions password. Required for 'encrypt'.

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.8/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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. 1 tool update
    • Changedconvert_pdf1 field changed
      • changedInput schema / properties / max_tokens / description
        Before
        "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)."
  2. 12 tool updatesv0.12.0
    • Changedadd_pdf_content8 fields changed
      • addedInput schema / properties / content / description
        "Text to draw. Required when content_type='text'."
      • addedInput 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."
      • addedInput schema / properties / content_type / enum
        [
          "text",
          "new_page"
        ]
      • addedInput schema / properties / font / description
        "Font name (e.g. 'Helvetica', 'Courier', 'Times-Roman'). Defaults to Helvetica when omitted."
      • addedInput schema / properties / font_size / description
        "Font size in points for text content."
      • addedInput schema / properties / session_id / description
        "Session id returned by create_pdf. Must be active."
      • addedInput schema / properties / x / description
        "Horizontal position in PDF points from the left edge. Required when content_type='text'."
      • addedInput schema / properties / y / description
        "Vertical position in PDF points from the bottom edge (origin is bottom-left). Required when content_type='text'."
    • Changedanalyze_pdf6 fields changed
      • addedInput 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."
      • addedInput schema / properties / check / enum
        [
          "validate",
          "corruption",
          "compliance",
          "compare"
        ]
      • addedInput schema / properties / compare_path / description
        "Second PDF to diff against. Required when check='compare', ignored otherwise."
      • addedInput 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)."
      • addedInput schema / properties / compliance_level / enum
        [
          "a1a",
          "a1b",
          "a2a",
          "a2b",
          "a2u",
          "a3a",
          "a3b",
          "a3u"
        ]
      • addedInput schema / properties / path / description
        "Path to the PDF file to analyze, relative to the workspace."
    • Changedannotate_pdf10 fields changed
      • addedInput 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)."
      • addedInput schema / properties / annotation_type / enum
        [
          "text",
          "highlight"
        ]
      • addedInput schema / properties / contents / description
        "Note text for a 'text' annotation. Ignored for 'highlight'."
      • addedInput schema / properties / height / description
        "Highlight height in points. Used only for 'highlight'."
      • addedInput schema / properties / input_path / description
        "Source PDF to annotate, relative to the workspace."
      • addedInput schema / properties / output_path / description
        "Destination .pdf path; overwritten if it already exists."
      • addedInput schema / properties / page / description
        "0-based index of the page to annotate."
      • addedInput schema / properties / width / description
        "Highlight width in points. Used only for 'highlight'."
      • addedInput schema / properties / x / description
        "Horizontal anchor in PDF points from the left edge."
      • addedInput schema / properties / y / description
        "Vertical anchor in PDF points from the bottom edge (origin is bottom-left)."
    • Changedconvert_pdf5 fields changed
      • addedInput schema / properties / format / description
        "Output representation: 'markdown' = one structured Markdown document; 'chunks' = fixed-size token windows; 'rag' = heading-aware semantic chunks for retrieval pipelines."
      • addedInput schema / properties / max_tokens / description
        "Target maximum tokens per chunk. Applies to format='chunks' and 'rag' only; ignored for 'markdown'."
      • addedInput schema / properties / overlap / description
        "Token overlap carried between consecutive chunks. Applies to format='chunks' only; ignored for 'markdown' and 'rag'."
      • addedInput schema / properties / password / description
        "User password to unlock an encrypted PDF before conversion."
      • addedInput schema / properties / path / description
        "Path to the PDF file, relative to the configured workspace."
    • Changedcreate_pdf4 fields changed
      • addedInput schema / properties / author / description
        "Document author; stored in the PDF metadata on save."
      • addedInput schema / properties / page_size / description
        "Page size for every page in this document."
      • addedInput schema / properties / page_size / enum
        [
          "a4",
          "a4_landscape",
          "letter",
          "letter_landscape",
          "legal",
          "legal_landscape"
        ]
      • addedInput schema / properties / title / description
        "Document title; stored in the PDF metadata on save."
    • Changedextract_entities1 field changed
      • addedInput schema / properties / path / description
        "Path to the PDF file, relative to the configured workspace."
    • Changedextract_text3 fields changed
      • addedInput 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."
      • addedInput schema / properties / password / description
        "User password to unlock an encrypted PDF before extraction."
      • addedInput schema / properties / path / description
        "Path to the PDF file, relative to the configured workspace."
    • Changedmanage_forms6 fields changed
      • addedInput schema / properties / fields / description
        "Field definitions for 'create'. Each: {name, type:'text', x, y, width, height (points), default_value?}."
      • addedInput schema / properties / input_path / description
        "Source PDF. Required for 'fill', 'read' and 'validate'; unused for 'create'."
      • addedInput 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."
      • addedInput schema / properties / operation / enum
        [
          "create",
          "fill",
          "read",
          "validate"
        ]
      • addedInput schema / properties / output_path / description
        "Destination .pdf path (overwritten if present). Required for 'create' and 'fill'; unused for 'read'/'validate'."
      • addedInput schema / properties / values / description
        "Map of field name to value. Required for 'fill' and 'validate'."
    • Changedmanipulate_pdf8 fields changed
      • addedInput schema / properties / degrees / description
        "Clockwise rotation in degrees (e.g. 90, 180, 270). Required for 'rotate'."
      • addedInput schema / properties / input_path / description
        "Source PDF. Required for every operation except 'merge' (which uses input_paths)."
      • addedInput schema / properties / input_paths / description
        "Ordered list of PDFs to combine. Required for 'merge'."
      • addedInput 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."
      • addedInput schema / properties / operation / enum
        [
          "split",
          "merge",
          "rotate",
          "extract_pages",
          "reverse",
          "overlay"
        ]
      • addedInput 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."
      • addedInput schema / properties / overlay_path / description
        "PDF stamped on top of input_path. Required for 'overlay'."
      • addedInput schema / properties / page_indices / description
        "0-based page indices to keep, in order. Required for 'extract_pages'."
    • Changedread_pdf3 fields changed
      • addedInput 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."
      • addedInput 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."
      • addedInput schema / properties / path / description
        "Path to the PDF file, relative to the configured workspace."
    • Changedsave_pdf4 fields changed
      • addedInput schema / properties / output_path / description
        "Destination .pdf path inside the workspace. An existing file at this path is overwritten."
      • addedInput schema / properties / owner_password / description
        "Owner/permissions password. Encryption is applied only when both user_password and owner_password are provided."
      • addedInput schema / properties / session_id / description
        "Session id returned by create_pdf to finalize."
      • addedInput schema / properties / user_password / description
        "If set together with owner_password, the saved PDF is encrypted; this is the password required to open it."
    • Changedsecure_pdf7 fields changed
      • addedInput schema / properties / input_path / description
        "Source PDF. Required for all three operations."
      • addedInput schema / properties / operation / description
        "'encrypt' writes a password-protected copy; 'permissions' reports encryption status; 'verify_signatures' checks digital signatures. Only 'encrypt' writes a file."
      • addedInput schema / properties / operation / enum
        [
          "encrypt",
          "permissions",
          "verify_signatures"
        ]
      • addedInput schema / properties / output_path / description
        "Destination .pdf for the encrypted copy (overwritten if present). Required for 'encrypt'; unused otherwise."
      • addedInput schema / properties / owner_password / description
        "Owner/permissions password. Required for 'encrypt'."
      • addedInput schema / properties / password / description
        "Password used to unlock the file when checking 'permissions' on an encrypted PDF. Unused by other operations."
      • addedInput schema / properties / user_password / description
        "Open password for the encrypted copy. Required for 'encrypt'."
  3. 12 tool updatesv0.11.0
    • First observedadd_pdf_content
    • First observedanalyze_pdf
    • First observedannotate_pdf
    • First observedconvert_pdf
    • First observedcreate_pdf
    • First observedextract_entities
    • First observedextract_text
    • First observedmanage_forms
    • First observedmanipulate_pdf
    • First observedread_pdf
    • First observedsave_pdf
    • First observedsecure_pdf

TDQS

A4.7/5.0
Disambiguation5/5

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.

Naming Consistency5/5

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.

Tool Count5/5

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.

Completeness4/5

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

ActivityActive
ResponsivenessWithin a week

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
    MCP 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.
    22
    290
    9
    MIT
  • A
    license
    B
    quality
    F
    maintenance
    Enables low-level PDF object-tree inspection and debugging through natural language, with lazy loading for token efficiency.
    2
    4
    MIT

Latest Blog Posts

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