pdf-edit-mcp

pdf-edit-mcp

Enables editing text in existing PDFs by modifying content stream operators, preserving original fonts and positions. Provides fidelity reports on every edit, indicating font preservation, substitution, overflow, and other degradations.

Category
访问服务器

README

pdf-edit-mcp

MCP server for editing text in existing PDFs through content-stream surgery. Targets fidelity preservation (original font, exact position, in-place operators) and reports — honestly — when fidelity has to break.

PyPI version License: MIT CI Python

v0.2.0 is a native Python (FastMCP) server. Earlier 0.1.x releases were a TypeScript MCP server that shelled out to a Python bridge.py; v0.2.0 imports the engine in-process — one runtime, no Node.js, distributed on PyPI. See Migrating from 0.1.x.

How it works

Most PDF editors use a redact-and-replace approach — they white out the original text and stamp new text on top, usually with a substitute font. The result looks different from the original.

pdf-edit-mcp takes a different approach. It modifies the original PDF content stream operators directly, preserving the exact font, size, color, and position of the text being edited — when the embedded font already contains the glyphs you need.

Traditional approach pdf-edit-mcp
Method Redact old text, stamp new text Modify content stream operators in place
Font Substituted (often Helvetica) Original font when possible; metric-equivalent fallback (e.g. Carlito for Calibri) when not
Position Re-calculated Exact original coordinates
Quality feedback None FidelityReport on every edit (font_preserved, font_substituted, glyphs_missing, overflow_detected, typed degradations)

Powered by pdf-edit-engine — a Python library for PDF content stream surgery with in-place font subset extension.

When fidelity is exact, and when it isn't

This matters more than the headline claim. Every edit's fidelity report tells you which tier fired:

  • Tier 1 — exact (font_preserved=true, font_substituted=null): the embedded font already had every glyph the replacement needs. Output is byte-identical at the operator layer.
  • Tier 1.5 — in-place injection (font_preserved=true): the glyph wasn't embedded but was in your system font with matching unitsPerEm. Original CIDs are preserved; only new glyphs are appended. Visually indistinguishable from Tier 1. Covers TrueType (glyf) and, as of engine v0.2.0, CID-keyed (Type0) CFF / Type1C fonts.
  • Metric-equivalent fallback (font_preserved=false, font_substituted="Carlito-Regular" or similar): the original font isn't installed, so an open-source font with matching metrics is used for the new glyphs. Very close, spacing correct, not pixel-perfect.

What still refuses honestly (a typed font_extension_failed / clear error rather than silent corruption):

  • CFF shapes the injector doesn't cover — simple-font (non-CID) CFF, CFF2, name-keyed CFF, multi-FD CID, composite donors.
  • Type 3 (procedural) fonts.
  • unitsPerEm mismatch between embedded and system font (rescaling out of scope).
  • A replacement wider than the bbox with no room to reflow (overflow_detected=true + a warning).
  • Multi-codepoint emoji / scripts your system fonts don't carry (glyphs_missing).

Run pdf_analyze_subset first if you need to know the tier up front.

Features

  • 38 tools across 7 categories (reading, text editing, block ops, section ops, annotations, document manipulation, metadata & security) + 3 built-in MCP prompts that guide the editing workflow.
  • Edit encrypted PDFs — pass password= to the read/edit tools to work on a password-protected PDF; the output is re-encrypted with the same password (engine A2.3).
  • Shrink-to-fitfit="shrink" on pdf_replace_block / pdf_batch_replace_block shrinks the font to fit a fixed-height region (engine E.8).
  • Fidelity reporting on every edit: font_preserved, font_substituted, overflow_detected, reflow_applied, glyphs_missing, a warnings list, and a typed degradations array (30 engine degradation kinds, each {kind, detail, severity}) so callers can gate on quality.
  • dry_run preview on pdf_replace_text / pdf_replace_single / pdf_batch_replace — get the fidelity report without writing the output.
  • Per-page filtering on pdf_find_text / pdf_get_text / pdf_get_fonts.
  • Batch operations — up to 500 find-and-replace edits per call, up to 50 block replacements per page, with output auto-verification on pdf_batch_replace.
  • Section intelligence — detects structure by font hierarchy, swaps sections by fuzzy title match and refuses ambiguous matches rather than silently picking the first.
  • Atomic writepdf_swap_sections writes to a temp file and renames only on full success; a failure leaves your output path untouched.
  • Engine-version gate at startup — refuses to serve against pdf-edit-engine < 0.2.0, so missing fidelity fields can't masquerade as null.
  • Path-safety boundary — every path is validated (absolute, .pdf, no .. traversal, no control chars, no Windows reserved/truncated basenames) before reaching the engine.
  • Runs entirely local — no external APIs, no network calls, no API keys.

Quick Start

Prerequisites

  • Python 3.10+ (3.12 recommended).
  • That's it — pdf-edit-engine installs automatically as a dependency. (uvx fetches everything on first run; no manual install.)

Claude Desktop

Add to your claude_desktop_config.json:

{
  "mcpServers": {
    "pdf-edit": {
      "command": "uvx",
      "args": ["pdf-edit-mcp"]
    }
  }
}

Claude Code

claude mcp add pdf-edit -- uvx pdf-edit-mcp

Other MCP clients (Cursor, Windsurf, etc.)

Run via uvx pdf-edit-mcp, or install it and use the console script:

pip install pdf-edit-mcp
pdf-edit-mcp          # or: python -m pdf_edit_mcp

Tools

Reading & Analysis

Tool Description
pdf_inspect Complete document overview — text, fonts, paragraphs, annotations in one call. Start here before editing.
pdf_get_text Extract all text from a PDF
pdf_find_text Find all occurrences of a string with page numbers and bounding box positions
pdf_get_fonts List fonts with encoding type, glyph count, PostScript name, subset status
pdf_get_text_layout Get every text block with exact position, font, and size
pdf_extract_bbox_text Extract text from a bounding box region with gap-aware joining
pdf_detect_paragraphs Detect paragraph boundaries with bounding boxes on a page
pdf_detect_sections Analyze document structure — section tree with titles, bounding boxes, and text
pdf_analyze_subset Check if an embedded font can render specific characters before editing

Text Editing

Tool Description
pdf_replace_text Replace all occurrences of a string (names, dates, typos, labels)
pdf_replace_single Replace one specific occurrence by match index
pdf_batch_replace Multiple find-and-replace edits in one atomic operation (up to 500 edits)

Block Operations

Tool Description
pdf_replace_block Replace all content within a bounding box with new text (fit="shrink" to shrink-to-fit)
pdf_batch_replace_block Replace content in multiple bounding boxes atomically
pdf_insert_text_block Insert text at a position
pdf_delete_block Delete content in a bounding box, optionally close the gap

Section Operations

Tool Description
pdf_swap_sections Swap two sections by fuzzy title match — re-renders all siblings for uniform spacing
pdf_replace_section Replace a section's entire content by fuzzy title match

Annotations & Links

Tool Description
pdf_get_annotations List all annotations with positions, types, and URLs
pdf_add_annotation Add a link annotation at a position on a page
pdf_update_annotation Update a link annotation's target URL
pdf_delete_annotation_v2 Delete an annotation by page and index
pdf_move_annotation Move an annotation to a new position
pdf_add_hyperlink Add a clickable hyperlink to a page region
pdf_add_highlight Add a highlight annotation with QuadPoints
pdf_flatten_annotations Flatten all annotations into page content (non-editable)

Document Manipulation

Tool Description
pdf_merge Merge multiple PDFs into one document
pdf_split Split a PDF into individual page files
pdf_reorder_pages Reorder pages by 0-indexed page number array
pdf_rotate_pages Rotate pages by 90, 180, or 270 degrees
pdf_delete_pages Delete specific pages (0-indexed)
pdf_crop_pages Crop all pages to a bounding box
pdf_add_watermark Overlay a watermark PDF on all pages

Metadata & Security

Tool Description
pdf_edit_metadata Edit title, author, subject, creator, producer
pdf_add_bookmark Add a navigation bookmark pointing to a page
pdf_encrypt Encrypt with owner and user passwords
pdf_decrypt Decrypt a password-protected PDF
pdf_fill_form Fill form fields by name-value pairs

Workflows

Three built-in MCP prompts guide the editing process: comprehensive-pdf-edit (structural changes — inspect → understand structure → pre-check → execute → verify), section-swap (swap two sections, re-rendering all siblings for uniform spacing), and quick-pdf-edit (simple typo/date/name changes with a fidelity check).

Architecture

AI Agent (Claude, GPT, etc.)
    ↓  MCP protocol (stdio)
pdf_edit_mcp — Python FastMCP server (this package)
    ↓  in-process import
pdf-edit-engine — Python library (pikepdf + fonttools + pdfminer)
  • Single process: the engine is imported directly — no subprocess, no JSON-RPC bridge, no Node.js.
  • Inputs are validated by Pydantic models (path safety, bounds, strict object shapes) before reaching the engine.
  • Engine calls are serialized under a lock (the engine is not thread-safe) and PDFEditErrors are translated to clean tool errors with recovery hints.
  • stdout is the MCP transport — all diagnostics go to stderr.

Layout: server.py (entry + version gate), app.py (FastMCP instance + lock), validation.py, serialize.py, _runtime.py, and tools_*.py / prompts.py (the tool + prompt surface).

Limitations

  • Cross-page reflow — text expanding past a page boundary is not redistributed (overflow_detected=true + a warning).
  • Some CFF shapes — CID-keyed (Type0) CFF/Type1C is supported; simple-font CFF, CFF2, name-keyed CFF, multi-FD CID, and composite donors refuse honestly (font_extension_failed).
  • unitsPerEm mismatch between embedded and system font — out of scope; refuses rather than distort.
  • Image editing / table semantics — text-only.
  • Right-to-left / complex-script shaping — bidi reordering is not handled; CJK line-breaking is supported (engine E.7).
  • Multi-codepoint emoji not in your system fonts — recorded as glyphs_missing.

Errors

Engine failures surface as MCP tool errors (isError) carrying a classified message and a recovery hint — for example:

  • OperatorError"TextMatch is stale — re-run pdf_find_text and retry."
  • EncodingError"…run pdf_analyze_subset to check coverage."
  • ReflowError"Replacement may be too wide — try shorter text or a different bbox."
  • FontNotFoundError"Run pdf_get_fonts, or install the required font / accept a fallback."

Raw pikepdf exceptions (e.g. on an encrypted PDF opened without a password) are never leaked — you get a clean "password-protected" message instead.

Migrating from 0.1.x (npm)

The 0.1.x npm package @aryanbv/pdf-edit-mcp is deprecated. Replace the npm/npx launch config with the uvx config above. The tool names, inputs, and outputs are unchanged, so prompts and integrations keep working; you no longer need Node.js, and the PDF_EDIT_PYTHON env var is gone (the engine runs in-process).

Development

git clone https://github.com/AryanBV/pdf-edit-mcp.git
cd pdf-edit-mcp
python -m venv .venv && . .venv/bin/activate    # Windows: .venv\Scripts\activate
pip install -e ".[dev]"
ruff check src/ tests/        # lint
mypy src/pdf_edit_mcp         # type-check (strict)
pytest tests/ -q              # tests (fixtures auto-generated via reportlab)

License

MIT

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选