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 分