Pdfedit Mcp

io.github.zp130221由 GitHub 账号 zp130221 发布v0.1.10更新于 Oct 24, 2026

Edit text inside existing PDFs: replace, delete, redact, insert, fill forms; original fonts kept.

已验证Streamable HTTP可网页运行效率与工作流文件与存储

概览

AI 生成的概览

在已有 PDF 中修改文字——替换、删除、涂黑、插入、填写表单,保留原字体与版式,并返回修改前后预览。

可以做什么
  • 在已有 PDF 中替换、删除、涂黑、插入文字或填写表单字段,保留版式与字体,并返回最多三张前后对比预览
  • 对同一模板 PDF 按每条记录重复执行相同修改(邮件合并),并通过任务 id 获取结果
  • 读取 PDF 的文字片段及其页码、位置、字体和片段 id,可按查询词与页码过滤并分页
  • 将某一页或某个区域渲染为 PNG,可叠加高亮框,用于修改前后核对
  • 查询异步编辑与批量任务的结果和进度
适用场景
适合需要修改已有 PDF 中的措辞、涂黑敏感字符串或填写表单,同时保持原文件外观的场景;也适合用同一模板为多条记录批量生成个性化文档。
运行要求
可通过 npx(Node.js)在本地运行,或使用托管的 Streamable-HTTP 端点。可选 PDFEDIT_API_KEY 以获得更高额度,不填则使用无密钥免费额度。PDFEDIT_BASE_URL 默认指向托管 API。本地路径仅本地包支持,托管端点只接受 PDF 网址。
安装前请注意
编辑会在输入文件旁写出新文件,属于对文档的写入操作。PDF 会上传到托管 API;无密钥免费额度会在输出上加水印 TEST 并按 IP 限制用量。加密 PDF 需要打开密码。扫描像素上的涂黑和从右到左文字会被拒绝;部分编辑会因判定为附带损伤而回滚。

安装

在 SourceWeft 中

  1. 打开 控制台中的 Pdfedit Mcp,将其添加到工作区。
  2. 为需要使用其工具的对话启用该服务。

Web executable,通过 Streamable HTTP。 远程服务在工作区中配置后即可从网页运行时运行。

交给智能体安装

把这段提示词粘贴到 Claude Code、Codex、Cursor 等智能体,或 SourceWeft 对话中。智能体会读取该服务器的安装指南,先向你展示发布者、端点和登录方式,经你同意后再把它添加到你的客户端。密钥不会写进任何命令。

阅读 https://sourceweft.com/mcp/io.github.zp130221%2Fpdfedit-mcp/install.md,并按其中说明把这个 MCP 服务器接入我的客户端。修改任何配置之前,先告诉我它的发布者、端点和登录方式,等我确认。不要把 API 密钥写进命令或我会提交的文件;问我密钥应从哪里获取。

查看智能体所依据的安装指南

其他 MCP 客户端

把它添加到你客户端的 mcpServers 配置中。

{
  "mcpServers": {
    "pdfedit": {
      "type": "http",
      "url": "https://pdfedit-mcp-remote.niubai-pdfedit-remote-worker.workers.dev/mcp"
    }
  }
}

README

@niubai/pdfedit-mcp — edit existing PDFs from your agent

Five MCP tools over the PDF Edit API: replace, delete, redact, insert, form-fill, stamp or remove an image inside a PDF that already exists, keeping the original font, the original layout and everything you did not point at. Not "generate a new PDF that looks similar" — the same file, with the words you named changed, and a before/after picture of every change.

[Install in Cursor] [Install in VS Code] [npm] [MIT]

With PDFEDIT_BASE_URL unset the server talks to the hosted API at https://api.niubai.vip; set it to point at another deployment.

Try it in 30 seconds, no key

Without PDFEDIT_API_KEY the server runs on the keyless free tier: 20 pages a day per IP, outputs watermarked TEST, local files included.

Claude Code

bash
claude mcp add pdfedit -- npx -y @niubai/pdfedit-mcp

Cursor / VS Code / Claude Desktop — this server entry (or the buttons on the repository page):

json
{ "pdfedit": { "command": "npx", "args": ["-y", "@niubai/pdfedit-mcp"] } }

Then ask your agent: "In ./contract.pdf replace 'Acme Ltd' with 'Acme GmbH' and redact the IBAN." The edited PDF is written next to the original and a before/after picture of every change comes back. A free API key (200 pages a month, no watermark on ordinary documents) takes one email at https://api.niubai.vip.

Install

Claude Code — one line:

bash
claude mcp add pdfedit -e PDFEDIT_API_KEY=sk_live_your_key -- npx -y @niubai/pdfedit-mcp

Cursor — the deeplink (Settings → MCP also takes the same JSON):

cursor://anysphere.cursor-deeplink/mcp/install?name=pdfedit&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBuaXViYWkvcGRmZWRpdC1tY3AiXSwiZW52Ijp7IlBERkVESVRfQVBJX0tFWSI6InNrX2xpdmVfeW91cl9rZXkifX0=

Claude Desktop — claude_desktop_config.json:

json
{  "mcpServers": {    "pdfedit": {      "command": "npx",      "args": ["-y", "@niubai/pdfedit-mcp"],      "env": {        "PDFEDIT_API_KEY": "sk_live_your_key"      }    }  }}

No key? Leave env out: the keyless free tier is 20 pages/day per IP, outputs watermarked TEST. Web clients that cannot run a local server (claude.ai) can add the hosted endpoint instead; it takes PDF URLs only.

Local files versus URLs

This package runs on your machine, so every tool's file argument takes an absolute (or ~) local path — it uploads the file for you and writes the edited PDF back next to the input as <name>.edited.pdf — or an https:// URL, or an f_… file id from an earlier call. The hosted Streamable-HTTP endpoint cannot read your disk and says so (remote server cannot read local paths; pass a URL). PDFs never travel as MCP content blobs either way; only up to three preview PNGs of the changed pages come back inline.

Tools

ToolWhat it does
pdf_editReplace / delete / redact / insert / fill, one call, with previews.
pdf_batchThe same edits once per record over one template. Returns a job id.
pdf_findEvery span with page, bbox, font and span id; filter with the four match modes.
pdf_previewRender a page (or a region) as a PNG, with optional highlight boxes.
pdf_jobThe result of an async edit or a batch.

Every schema is generated from the gateway's OpenAPI document, so an edits[] entry here is exactly the one POST /v1/edit and the SDKs take — see src/tools.ts.

What it will refuse, and why

The engine would rather hand back "no" with a reason than a file that looks edited and is not. Two kinds of refusal.

Verification gates — the edit was attempted and rolled back

Every change is written, then checked, then kept or undone. A group that fails any gate is rolled back and reported in failed[]:

ReasonWhat happened
collateral_damagePixels changed outside the rewrite's own area — something else on the page moved. The page is restored byte-for-byte.
readback_failedRe-reading the edited rectangle did not return the text that was supposed to be there.
does_not_fitThe replacement does not fit the space, and fit was not allowed to make it worse (fit: "strict"), or an insert would have landed on text that is already there.
font_unavailableoptions.font.policy: "exact_only" (or "metric_only") and neither the system nor the document has an acceptable face.
redact_residualAfter a redaction the string was still readable in the rect — the removal is refused rather than reported as done.
no_target, field_not_editable, field_value_invalid, field_value_mismatchThe form field does not exist, is read-only, rejects the value, or did not read back as written.

With options.atomic (the default) any single failure fails the whole request and no file is produced; options.strict does the same for an edit that simply did not match. An unmatched edit comes back with fuzzy suggestions ("did you mean Acme, Inc.?") rather than a silent no-op.

Known-unsupported — rejected up front as invalid_request

What the API refuses before touching the document:

  • Right-to-left text (Arabic, Hebrew) in find. Everything after the matcher is left-to-right: lines are assembled left edge first and replacements are laid out rightwards, so RTL would be matched against a visually reversed line and written in the wrong direction with nothing downstream able to notice.
  • redact on text that only exists as scanned pixels. The word is the image; covering it leaves it in the file, so the op's promise cannot be kept.
  • style together with fit: "reflow". A reflow re-sets the whole paragraph in the document's own face, so the matched phrase no longer has a run of its own to style.
  • fit: "reflow" on redact or form.
  • options.preview: "pages" (whole-page previews); "changes" and "none" work.
  • Unknown ops.

Known limits — supported, with a caveat worth knowing

  • A raster OCR write produces an image, not text. Where a scanned line has no underlying text to clone, the new words are drawn as pixels: correct on the page, verified by re-rendering, but not selectable or searchable afterwards.
  • A redaction on a scan is verified by the text layer and the pixel scrub, not by recognising the output again.
  • Text positioned relatively — matplotlib writes each tick relative to the previous one — can make an unrelated element move hundreds of points away. The engine sees that as collateral damage and rolls the change back; the page stays correct, the edit does not happen. One corpus file does this on purpose as a regression.
  • Fonts. A replacement is set in the document's own font where the file embeds enough of it (any page's subset of that font counts), in a metric-compatible twin where it does not (Arial, Helvetica, Times New Roman, Courier New, Calibri, Cambria, Georgia, Segoe UI, Palatino, Book Antiqua, Bookman, Century Gothic, Avant Garde, New Century Schoolbook and Arial Narrow all have one: same widths, so the line ends where it did), and in a look-alike of the same class as a last resort. The result always says which (font_source, font_used), the summary spells out approx_font_used when the last resort was taken, and options.font.policy: "metric_only" refuses it outright, so "it looks slightly different" is a value you can read rather than a surprise.
  • flatten on radio groups and comboboxes depends on the appearance the file carries; where it declines, the field is left live and flatten_skipped is warned instead of failing.
  • Encrypted documents need the open password (password); edits are not attempted without it.

More

  • Quick start — install per client, what to say to the agent, what comes back. The canonical usage doc; this README stays short on purpose.
  • API reference — every field of edits[], options and the response.
  • Examples — ten before/after pairs, each with the request that produced it.
  • Repository — this server, the SDKs and the hosted endpoint's source.

MIT -- this server, the SDKs, the agent skill and the OpenAPI document. The hosted API itself is a proprietary service.

来源:mcp/pdfedit-mcp/README.md,提交 5daf8d6

工具

5

pdf_edit

Edit a PDF

Edit the text of an existing PDF in place: replace, delete, redact, insert, or fill form fields, keeping the original layout, fonts and everything you did not point at. `edits[]` is taken exactly as the API takes it (`op`, `scope`, `match`, `fit`), and the result carries up to 3 before/after previews of the pages that changed. To change text on one page only, set `scope.pages`; to pick one of several identical matches, use `scope.after` with nearby text or `scope.occurrence`. Use `op: 'redact'` when the text must be unrecoverable.

输入参数file必填edits必填optionspasswordoutput_path

pdf_batch

Batch-edit a PDF template

Apply the same edits to one template PDF once per record, producing one output document per record — a mail merge over an existing PDF. Returns a `job_id`: call `pdf_job` with it for the per-record results. To change text on one page only, set `scope.pages`; to pick one of several identical matches, use `scope.after` with nearby text or `scope.occurrence`. Use `op: 'redact'` when the text must be unrecoverable.

输入参数file必填edits必填optionsrecordspasswordrecords_url

pdf_find

Read the text of a PDF

Read the text of a PDF: every span with its page, position, font and span id, optionally filtered by `query` (the same four `match` modes an edit uses) and `pages`, over the `content`, `forms` and `annotations` layers. Paginated: pass the returned `next_cursor` back as `cursor` for the next page. Use it before `pdf_edit` to check what a document actually says and to pick the `scope` that selects the match you mean.

输入参数file必填limitmatchpagesquerycursorlayerspassword

pdf_preview

Render a PDF page

Render one page of a PDF as a PNG image block, optionally cropped to `region` and with rectangles drawn over `highlight`. Use it to see a page before editing it, or to check the result afterwards.

输入参数file必填pagescaleregionpasswordhighlight

pdf_job

Job result

The result of an async edit or a batch, by `job_id`: the same body `pdf_edit` returns once the job is done, plus `progress` while it is still queued or running, and `records` for a batch.

输入参数job_id必填output_path

版本历史

6
  1. v0.1.10最新Oct 20, 2026
  2. v0.1.9Oct 19, 2026
  3. v0.1.7Oct 18, 2026
  4. v0.1.5Oct 17, 2026
  5. v0.1.4Oct 16, 2026
  6. v0.1.3Oct 16, 2026

评分

已满足适用检查项的 100%

该评分衡量此收录条目的完整程度,依据注册中心条目、端点与公开来源计算得出。它不是对服务器本身的评价,也不表示服务器安全或当前可用:可连通性是带日期的检查结果,评分也不包含安装量或用户评价。

  • 近 30 天内可连通必需25 分
  • 已声明认证方式必需10 分
  • 已列出工具必需15 分
  • 描述必需15 分
  • 图标10 分
  • 文档15 分
  • 许可证10 分