Featured

Deploy OpenClaw in 60 seconds — 20% off logoDeploy OpenClaw in 60 seconds — 20% off

Launch OpenClaw on Hostinger in about 60 seconds and keep your agent live 24/7. Our referral link gives you 20% off, no coupon code needed.

Launch on Hostinger
Run your Hermes agent on Hostinger, fully managed logoRun your Hermes agent on Hostinger, fully managed

Launch Hermes on Hostinger in one click, fully managed, no VPS knowledge needed. Use code ZACAARON10 for 10% off.

Launch on Hostinger
Crawl and scrape any site into clean data, 10% off logoCrawl and scrape any site into clean data, 10% off

Firecrawl crawls and scrapes any site into clean markdown for your agent. Get 1,000 free credits, and new users get 10% off their first purchase.

Try Firecrawl free
6,000+ web scrapers for your AI agent, start free logo6,000+ web scrapers for your AI agent, start free

Apify gives your agent live web data: 6,000+ prebuilt scrapers and actors, MCP-ready. Sign up free with $5 in usage credits.

Try Apify free
One API to scrape, enrich, and extract the internet. logoOne API to scrape, enrich, and extract the internet.

Context.dev gives your agents a single API to scrape, enrich, and extract live web data — no proxies, no parsers, no maintenance.

Start building free
SetupClaw: done-for-you OpenClaw for founders & exec teams logoSetupClaw: done-for-you OpenClaw for founders & exec teams

White-glove OpenClaw for founders and exec teams (4–50+ employees): we install, harden, integrate your tools, and maintain it — secured from day one.

Get it set up for you
SEO data APIs for your agent, $1 free credit logoSEO data APIs for your agent, $1 free credit

DataForSEO gives your agent live access to SERP results, keyword data, backlinks, and on-page SEO data through one API. New accounts get a $1 credit, good for up to 20,000 keyword or backlink lookups.

Try DataForSEO free
Reach 48,000+ AI builders

A flat monthly placement in front of developers actively installing AI tools. No lock-in, cancel anytime.

Advertise here

Works with

Claude CodeClaude DesktopCursorVS CodeClineCodex CLIOpenClaw+ any MCP client

Install to Claude Code

This server doesn't publish a one-line install command. Follow the setup in the source repository.

Summary

PDF native MCP server: generate, validate, sign PAdES, embed, extract. AI-powered.

README.md

pdfnative-mcp

Model Context Protocol (MCP) server that bridges the pdfnative library — a zero-dependency, ISO 32000-1 compliant PDF engine — to any MCP-compatible AI client (Claude Desktop, Cursor, Continue, ChatGPT, Zed, …).

![npm version](https://www.npmjs.com/package/pdfnative-mcp) ![npm downloads](https://www.npmjs.com/package/pdfnative-mcp) ![Node version](https://nodejs.org) ![License: MIT](LICENSE) ![CI](https://github.com/Nizoka/pdfnative-mcp/actions/workflows/ci.yml) ![MCP](https://modelcontextprotocol.io) ![TypeScript](https://www.typescriptlang.org/) ![OpenSSF Scorecard](https://scorecard.dev/viewer/?uri=github.com/Nizoka/pdfnative-mcp) ![CodeQL](https://github.com/Nizoka/pdfnative-mcp/actions/workflows/codeql.yml)

---

✨ Features

pdfnative-mcp exposes 24 production-grade tools to any MCP host:

| Tool | Purpose | | ---------------------------------- | ------------------------------------------------------------------------------------------------ | | generate_basic_pdf | Multi-page A4 documents from structured blocks (headings, paragraphs, lists, page breaks). Embedded newlines auto-split into paragraphs. Optional pdfA. | | add_barcode | QR Code, Code 128, EAN-13, Data Matrix, PDF417 — embedded in a single-page PDF. | | add_international_text | 24 scripts (incl. Latin & COLRv1 colour emoji) with BiDi & OpenType shaping; multi-lang per document. | | add_table | Tabular reports with smart fields (wrap, repeatHeader, zebra, caption, minRowHeight, cellPadding). | | add_form | Create a new interactive AcroForm PDF with text fields, checkboxes, radio buttons, dropdowns. | | read_form_fields (new in v1.5.0) | Read-only enumeration of an existing AcroForm's field tree (names, types, values, widgets). | | fill_form (new in v1.5.0) | Fill and/or flatten an existing AcroForm (non-destructive incremental update). | | add_chart (new in v1.5.0) | Native vector charts — bar / horizontal-bar / line / pie / donut (pure PDF path operators, PDF/A-safe). | | embed_image | Embed a JPEG or PNG image (base64) into a titled PDF document. | | prepare_signature_placeholder | Step 1 of the two-step sign workflow — create a PDF with a /Sig AcroForm placeholder. | | sign_pdf | Apply a PAdES-compatible CMS signature (RSA-SHA256 / ECDSA-SHA256 P-256). Auto-injects a placeholder when needed. | | verify_pdf | Verify every PAdES signature in a PDF (integrity + signature value + optional chain trust). | | validate_pdf (new in v1.1.0) | Validate a Tagged PDF for PDF/UA (ISO 14289-1) structural conformance (read-only). | | add_attachment | Generate a PDF/A-3 document with embedded files (Factur-X / ZUGFeRD invoices). | | extract_attachments | Read-only extraction of embedded files (Factur-X / ZUGFeRD XML round-trip) with byte-for-byte payloads. | | extract_text | Unicode text extraction (resolves /ToUnicode) with optional positioned runs; opens encrypted PDFs via password. | | inspect_pdf | Read-only inspection: PDF version, page count, encryption (+ precise encryptionInfo), PDF/A claim, signatures, attachments, placeholder state. | | encrypt_pdf (new in v1.5.0) | Re-secure a PDF with AES-128 / AES-256 (owner/user passwords, permissions, password rotation). | | decrypt_pdf (new in v1.5.0) | Emit an unencrypted copy of an RC4 / AES-128 / AES-256 document. | | merge_pdfs (new in v1.3.0) | Concatenate 2–50 PDFs into one via pdfnative's page-tree API. | | split_pdf (new in v1.3.0) | Split one PDF into one document per page range (multi-output). | | extract_pages (new in v1.3.0) | Pull an arbitrary page subset into a single PDF. | | annotate_pdf (new in v1.4.0) | Add markup annotations (highlight, note, square/circle, line, freetext) as a visual overlay — not a redaction. | | draft_governance_issue (new in v1.4.0) | Draft a governance-compliant GitHub issue locally for human review; never submits, no network. |

New in v1.5.0:

  • 📊 Native vector chartsadd_chart renders bar / horizontal-bar / line / pie / donut charts as pure PDF path operators (zero rasterisation, PDF/A-safe with auto alt text). generate_basic_pdf also accepts a chart block for composition with text and tables.
  • 📝 Fill & flatten formsread_form_fields lists an existing AcroForm's fields; fill_form fills and/or flattens it via a non-destructive incremental update (the counterpart to add_form).
  • 🔐 Encryption round-tripencrypt_pdf re-secures with AES-128 / AES-256 (RC4 never emitted), decrypt_pdf recovers an unencrypted copy, a password input opens encrypted sources on the read-only tools, and merge_pdfs / split_pdf / extract_pages gain password + encrypt.
  • 🔤 Real text extractionextract_text now resolves each font's /ToUnicode CMap (no more glyph-index output) and can return positioned runs.
  • 🔗 Native MCP resources — sandboxed generated PDFs become pdfnative://output/… resources (resources/list + resources/read), with a resource_link in file-mode results for cross-call re-reference.
  • 🏷️ Tool annotations — every tool advertises readOnlyHint / destructiveHint / idempotentHint / openWorldHint.
  • Engine upgradepdfnative v1.6.0 (decrypt/re-encrypt, extractText, fill/flatten, charts; colour-emoji subset 221 → 1167 glyphs).

New in v1.4.0:

  • 🤝 AI governance + human-in-the-loopdraft_governance_issue lets an agent draft a fully compliant GitHub issue locally (draft .md + machine-readable compliance report). The agent is a draftsman, never an autonomous submitter: a human is the only gate, and the server makes zero GitHub writes and no outbound network calls. Backed by the governance_contract and draft_issue_workflow MCP prompts.
  • ✏️ Markup annotationsannotate_pdf overlays highlight, sticky-note, underline, strikeout, squiggly, square, circle, line, and freetext annotations on an existing PDF via incremental update. It is a visual review layer, not a redaction — underlying bytes remain.
  • 🔢 Page labels in inspect_pdf — read-only surfacing of /PageLabels ranges (roman, decimal, prefixed).
  • Math / scientific scriptadd_international_text accepts lang: 'math' (explicit, like emoji) to embed the Noto Sans Math face on demand.
  • 🧩 MCP prompts — the server now advertises the prompts capability with governance_contract and draft_issue_workflow.
  • Engine upgrade — pdfnative v1.5.0.

New in v1.3.0:

  • 🆕 Three page-tree toolsmerge_pdfs, split_pdf, extract_pages (built on pdfnative v1.4.0's page-tree API; encrypted sources are rejected).
  • 🔖 Bookmarks, page labels & nested listsgenerate_basic_pdf gains outline ('auto' or explicit tree), pageLabels, multi-level list items, and viewerPreferences.
  • 📐 Table cell borders & alignmentadd_table gains cellBorders, cellVAlign, and viewerPreferences; add_international_text gains viewerPreferences.
  • 🔐 Constant-time signingsign_pdf signs RSA and EC-DER keys through a node:crypto provider with a transparent pure-JS fallback; signatures stay interoperable.
  • Engine upgrade — pdfnative v1.4.0.
  • 🆕 Tool extract_attachments — read embedded files back out of a PDF (completes the Factur-X / ZUGFeRD round-trip) with byte-for-byte payloads, a filename filter, and an includeData: false metadata-only probe.
  • 💧 Watermarksgenerate_basic_pdf and add_table accept an optional watermark (text, opacity, angle, colour, position) rendered on every page.
  • 🌐 Unicode normalize — opt-in NFC/NFD/NFKC/NFKD on generate_basic_pdf and add_international_text.
  • 🪙 Token-frugal reads — the read-only tools (inspect_pdf, verify_pdf, validate_pdf, extract_text, extract_attachments) accept optional verbosity: 'summary' and fields: […] inputs for ~90% smaller responses on large results, with no loss of the fields agents branch on. Defaults are unchanged.
  • 🪙 No base64 duplication — generated PDFs (base64 mode) are returned once as an embedded resource content block instead of also being copied into structuredContent.
  • 🔧 MCP registry publish fixmcpName now uses the canonical GitHub login casing (io.github.Nizoka/pdfnative-mcp) so the registry's case-sensitive validation accepts the npm package.
  • Dependency — upgraded to zod 4.

New in v1.1.0:

  • 🆕 Tool validate_pdf — read-only PDF/UA (ISO 14289-1) structural conformance check.
  • 🆕 Six new scripts — Telugu, Sinhala, Tibetan, Khmer, Myanmar, Ethiopic (24 scripts total).
  • 🆕 COLRv1 colour emoji — native colour emoji with monochrome fallback.
  • 🆕 Newline sanitizer — embedded \n in paragraphs auto-splits into separate paragraphs (Safe PDF/A).
  • 🆕 Automatic NFC normalisation for add_international_text.
  • 🛠 Engine upgradepdfnative v1.3.0: the Euro sign / CP-1252 symbols now extract correctly, and wrapped table cells get unique per-line MCIDs (PDF/UA-safe).

New in v1.0.0:

  • 🆕 Three new tools: verify_pdf, add_attachment (Factur-X / ZUGFeRD), extract_text.
  • 🆕 Smart-table fields: wrap, repeatHeader, zebra, caption, minRowHeight, cellPadding.
  • 🆕 inspect_pdf now reports hasSignaturePlaceholder and per-attachment summary; new check values 'placeholder' and 'attachments'.
  • 🆕 Signing ergonomics: sign_pdf accepts ECDSA SEC1 / PKCS#8 DER keys and auto-injects a /Sig placeholder when missing (one-call signing of any PDF).
  • 🆕 Opt-in cache (PDFNATIVE_MCP_CACHE_DIR): SHA-256 keyed, 1 h TTL, 256 MiB LRU.
  • 🆕 _meta.apiVersion and per-tool _meta.examples for AI-agent discovery — see docs/API_STABILITY.md.
  • 🆕 AI agent guide: docs/AI_GUIDE.md — decision tree + common pitfalls. See also the root AGENTS.md operations manual.
  • 🆕 PDF/A authoring guide: docs/guides/PDFA.md.
  • 🛠 Env-var rename: PDFNATIVE_MCP_OUTPUT_DIR (was PDFNATIVE_MPC_OUTPUT_DIR; old name still works with a one-shot deprecation warning).
  • Now shipped: merge_pdfs, split_pdf, extract_pages (v1.3.0), annotate_pdf (v1.4.0), and the add_chart / read_form_fields / fill_form / encrypt_pdf / decrypt_pdf tools plus the encrypted round-trip and native MCP resources (v1.5.0). redact_pdf stays deferred — pdfnative can overlay/flatten but not remove page content, and an overlay-only "redaction" would create false security, so it is intentionally not shipped (tracked as an upstream content-removal request).

All tools support two output modes:

  • base64 (default) — the generated PDF is returned once as an embedded resource content block (a data:application/pdf;base64,… URI); structuredContent carries only { mode, sizeBytes }.
  • file — the PDF is written to a sandboxed directory configured via PDFNATIVE_MCP_OUTPUT_DIR. File output is disabled unless this variable is set; absolute paths, path traversal, non-.pdf extensions, and NUL bytes are all rejected.

Upgrading from v1.1.0: the only behaviour change is that base64-mode bytes are no longer duplicated into structuredContent.base64. Read them from the embedded resource block instead: ``diff - const base64 = response.structuredContent.base64; // v1.1.0 + const block = response.content.find((c) => c.type === 'resource'); + const base64 = block.resource.blob; // v1.2.0 ``

Token-frugal reads (v1.2.0). The four read-only tools accept two optional inputs:

  • verbosity: 'summary' — returns a compact scalar-only verdict (drops the heavy arrays / full text). E.g. verify_pdf{ signatureCount, allValid, invalid, summary }.
  • fields: ['a', 'b.c'] — projects the structured result to named dot-paths; composes after verbosity. Unknown paths are omitted leniently.

Smallest “is this PDF signed and valid?” probe: { "pdfBase64": "…", "verbosity": "summary", "fields": ["allValid"] }.

Why pdfnative?

pdfnative-mcp inherits every guarantee of the underlying engine:

  • Zero runtime dependencies — pure JavaScript, no native bindings.
  • ISO 32000-1 (PDF 1.7) compliant output.
  • PDF/A-1b/2b/3b, AES-128/256 encryption, AcroForm, digital signatures.
  • 16 Unicode scripts with built-in BiDi reordering, Arabic positional shaping, Thai/Devanagari/Bengali/Tamil OpenType shaping.
  • Tree-shakeable ESM build.

---

🚀 Installation

# Run directly with npx (recommended for MCP clients)
npx -y pdfnative-mcp

# Or install globally
npm install -g pdfnative-mcp
pdfnative-mcp

Requirements: Node.js ≥ 22.

---

⚙️ Configuration

Claude Desktop

Edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):

{
  "mcpServers": {
    "pdfnative": {
      "command": "npx",
      "args": ["-y", "pdfnative-mcp"],
      "env": {
        "PDFNATIVE_MCP_OUTPUT_DIR": "/Users/you/Documents/mcp-pdfs"
      }
    }
  }
}

Cursor / Continue / Zed / Windsurf / Cline / Roo Code

Any MCP-compatible client that supports stdio servers will work. Use the same command + args + env triple. Example for Cursor (~/.cursor/mcp.json):

{
  "mcpServers": {
    "pdfnative": {
      "command": "npx",
      "args": ["-y", "pdfnative-mcp"],
      "env": { "PDFNATIVE_MCP_OUTPUT_DIR": "/Users/you/Documents/mcp-pdfs" }
    }
  }
}

Windsurf / Cline / Roo Code use the same shape inside their respective MCP config files.

🌐 Supported AI Ecosystem & Clients

pdfnative-mcp is designed for MCP-native environments and works with clients that support MCP over stdio.

Community-verified compatibility includes:

Environment variables

| Variable | Purpose | | ----------------------------- | ---------------------------------------------------------------------------------- | | PDFNATIVE_MCP_OUTPUT_DIR | Absolute path to the sandbox directory. Required to enable outputMode: 'file'. | | PDFNATIVE_MCP_CACHE_DIR | Absolute path to enable the persistent SHA-256-keyed result cache (1 h TTL, 256 MiB LRU). When unset, the cache is disabled. | | PDFNATIVE_MCP_PORT | When set to a valid port (1–65535), starts an HTTP server on http://127.0.0.1:<port>/mcp instead of stdio. Binds loopback only and enables DNS-rebinding protection (foreign Host/Origin403). |

---

🛠 Tool reference

generate_basic_pdf

{
  "title": "Q1 2026 Report",
  "blocks": [
    { "type": "heading", "text": "Executive summary", "level": 1 },
    { "type": "paragraph", "text": "Revenue grew 24% year over year." },
    { "type": "list", "style": "bullet", "items": ["Strong APAC", "Stable EU", "Soft NA"] },
    { "type": "pageBreak" },
    { "type": "heading", "text": "Details", "level": 2 }
  ],
  "footerText": "Confidential — Internal use only",
  "outputMode": "base64"
}

add_barcode

{
  "format": "qr",
  "data": "https://pdfnative.dev",
  "caption": "Scan to learn more",
  "ecLevel": "H",
  "outputMode": "file",
  "outputPath": "tickets/event-42.pdf"
}

Supported formats: qr, code128, ean13, datamatrix, pdf417.

add_international_text

{
  "title": "مرحبا بالعالم",
  "lang": "ar",
  "paragraphs": [
    "هذا اختبار للنص العربي مع تشكيل OpenType ومحارف ثنائية الاتجاه.",
    "Mixed content: العربية + English ✓"
  ]
}

Supported lang codes: ar, he, th, ja, zh, ko, el, hi, bn, ta, ru, ka, hy, tr, vi, pl, latin, emoji, math.

Multi-script documents — pass an array or comma-separated list:

{
  "title": "Mixed Script",
  "lang": ["ar", "emoji"],
  "paragraphs": ["العربية مع رموز 🎉🚀"],
  "pdfA": "pdfa2u"
}

sign_pdf

As of v1.0.0, sign_pdf auto-injects a /Sig placeholder when missing — you can sign any PDF in one call:

{
  "pdfBase64": "<any base64 PDF>",
  "algorithm": "rsa-sha256",
  "certDerBase64": "<base64 X.509 cert in DER>",
  "rsaKeyPkcs1DerBase64": "<base64 PKCS#1 RSAPrivateKey DER>",
  "signerName": "Alice",
  "reason": "Approval",
  "location": "Paris, FR",
  "signingTime": "2026-01-15T10:30:00Z"
}

For ECDSA P-256: use algorithm: "ecdsa-sha256" and supply either ecPrivateKeyDerBase64 (SEC1 or PKCS#8 DER) or ecPrivateScalarHex (64 hex chars).

PEM → DER conversion:

openssl x509 -in cert.pem -outform DER | base64 -w0                 # cert
openssl rsa  -in key.pem  -outform DER -traditional | base64 -w0    # RSA PKCS#1
openssl pkey -in key.pem  -outform DER | base64 -w0                 # ECDSA

Use prepare_signature_placeholder only when you need to customize the placeholder (e.g. larger placeholderBytes for >4096-bit RSA keys). Otherwise call sign_pdf directly.

---

add_table

{
  "title": "Monthly Sales",
  "headers": ["Region", "Units", "Revenue"],
  "rows": [
    ["APAC", "1200", "$240,000"],
    ["EMEA", "800", "$160,000"]
  ],
  "infoItems": [{ "label": "Period", "value": "January 2025" }],
  "footerText": "Internal use only",
  "outputMode": "base64"
}

add_form

{
  "title": "Employee Onboarding",
  "fields": [
    { "fieldType": "text", "name": "fullName", "label": "Full Name", "required": true },
    { "fieldType": "dropdown", "name": "dept", "label": "Department", "options": ["Engineering", "Sales", "HR"] },
    { "fieldType": "checkbox", "name": "agree", "label": "I agree to the terms", "checked": false }
  ],
  "outputMode": "base64"
}

embed_image

{
  "title": "Product Photo",
  "imageBase64": "<base64-encoded JPEG bytes>",
  "mimeType": "image/jpeg",
  "caption": "Front view of Model X",
  "width": 400,
  "outputMode": "base64"
}

Note: pdfnative does not support alpha-channel PNGs (color type 6). Pre-process such images to remove the alpha channel before embedding.

prepare_signature_placeholder

{
  "title": "Service Agreement",
  "signerName": "Alice Dupont",
  "reason": "Approved",
  "location": "Paris, FR",
  "blocks": [
    { "type": "paragraph", "text": "By signing below, I accept the terms and conditions." }
  ],
  "outputMode": "base64"
}

Pass the returned PDF bytes to sign_pdf to complete the signing workflow.

inspect_pdf

Read-only structural and security inspection — useful for downstream verification, CI assertions, and AI agents that need to reason about a PDF before acting on it.

{
  "pdfBase64": "<base64 PDF>",
  "pages": true,
  "check": ["pdfa", "signed", "attachments"]
}

Returns:

{
  "version": "1.7",
  "pageCount": 3,
  "encryption": "none",          // 'none' | 'aes-128' | 'aes-256' | 'rc4' | 'unknown'
  "pdfA": "3B",                  // null when no PDF/A claim is present
  "signatureCount": 1,
  "hasSignaturePlaceholder": false,
  "attachments": [{ "filename": "factur-x.xml", "mimeType": "application/xml", "sizeBytes": 1234, "relationship": "Source" }],
  "info": { "Producer": "pdfnative", "Title": "Invoice INV-2025-001" },
  "perPage": [{ "index": 0, "width": 595, "height": 842 }],
  "checks": { "pdfa": true, "signed": true, "attachments": true },
  "checksPassed": true
}

check[] accepts any of 'pdfa', 'signed', 'encrypted', 'placeholder', 'attachments'. checksPassed is the AND of all requested checks.

validate_pdf

Read-only PDF/UA (ISO 14289-1) structural conformance check for a Tagged PDF. Generate an accessible document with any tool using pdfA (e.g. pdfA: 'pdfa2u'), then validate the result:

{ "pdfBase64": "<tagged-pdf-base64>" }

Returns:

{
  "standard": "pdf-ua-1",
  "valid": true,
  "errors": [],          // blocking structural violations (empty when valid)
  "warnings": [],        // non-blocking best-practice recommendations
  "summary": "PDF/UA structural prerequisites hold."
}

It verifies catalog /MarkInfo /Marked true, /StructTreeRoot (+ /ParentTree), /Metadata (XMP), /Lang, and per-page MCID uniqueness. This is a fast developer-time gate — not a substitute for a full reference validator (veraPDF), which additionally checks fonts, colour, and rendering.

annotate_pdf

Overlay markup annotations on an existing PDF via incremental update. This is a visual review layer, not a redaction — the underlying content is untouched.

{
  "pdfBase64": "<base64 PDF>",
  "annotations": [
    { "type": "highlight", "page": 0, "rect": [72, 700, 520, 715], "color": [1, 1, 0], "contents": "Check this figure" },
    { "type": "text", "page": 0, "rect": [540, 700, 560, 720], "contents": "Reviewer note" }
  ]
}

Types: text, highlight, underline, strikeout, squiggly, square, circle, line, freetext. Encrypted sources are rejected (ENCRYPTED_SOURCE).

draft_governance_issue

Draft a governance-compliant GitHub issue locally for a human to review and submit. The server never contacts GitHub and makes no outbound network calls; it returns the draft Markdown plus a machine-readable compliance report.

{
  "title": "add_table drops the caption on the second page",
  "issueType": "bug",
  "summary": "The table caption is only rendered on page 1 when repeatHeader is true.",
  "reproduction": { "command": "node examples/run.mjs add-table-caption.json", "result": "Page 2 has no caption row." },
  "expectedBehavior": "The caption repeats with the header on every page.",
  "duplicateSearchPerformed": true
}

A draft that proposes a runtime dependency, omits a reproduction, or sets duplicateSearchPerformed: false is rejected with GOVERNANCE_VIOLATION. See docs/guides/AI_GOVERNANCE.md for the full human-in-the-loop contract.

verify_pdf, add_attachment, extract_text

See the dedicated sections in docs/AI_GUIDE.md and the reference in docs/KNOWLEDGE_BASE.md. Ready-to-run examples live under examples/.

---

🔐 Security model

pdfnative-mcp runs inside the host process and exposes a stdio MCP server. It does not open network sockets and does not perform any I/O outside the configured sandbox.

  • File writes are gated by PDFNATIVE_MCP_OUTPUT_DIR. When unset, the file output mode is rejected with a SecurityError.
  • Path resolution rejects absolute paths, traversal sequences (..), NUL bytes, and any extension other than .pdf.
  • Output size is capped at 50 MB per call.
  • Inputs are validated against strict JSON Schemas + Zod runtime checks at the boundary of every tool.

See SECURITY.md for the responsible disclosure process.

---

🧪 Local development

git clone https://github.com/Nizoka/pdfnative-mcp.git
cd pdfnative-mcp
npm install
npm run typecheck
npm run lint
npm test
npm run build

Smoke-test the server over stdio:

node dist/cli.js
# In another terminal, send a JSON-RPC initialize request via stdin (e.g. with mcp-inspector).

Contributors: see docs/guides/LOCAL_TESTING.md for the full local-verification workflow — the quality gate, examples-as-tests, validating that generated PDFs are structurally correct (assertValidPdf, inspect_pdf, validate_pdf, verify_pdf), opening output in a viewer, external PDF/A checking with veraPDF, and the MCP Inspector.

📣 Release process

pdfnative-mcp follows the same release formalism as pdfnative:

  • One release note file per tag in release-notes/vX.Y.Z.md
  • CHANGELOG.md mirrors each release bullet list
  • GitHub Release body is copied from release-notes/vX.Y.Z.md
  • npm publication is handled by GitHub Actions Trusted Publishing (OIDC), without NPM_TOKEN

See release-notes/TEMPLATE.md for the canonical structure and publication checklist.

---

📚 Project structure

src/
├── cli.ts                      # stdio entrypoint (#!/usr/bin/env node)
├── index.ts                    # public library exports
├── server.ts                   # McpServer factory + tool registry
├── output.ts                   # sandboxed file writer / base64 emitter (single + multi)
├── text.ts                     # newline sanitizer (Safe PDF/A)
├── doc-features.ts             # nested lists, outline, page labels, viewer prefs
├── pagetree.ts                 # page-tree error mapping (merge/split/extract)
├── crypto-provider.ts          # node:crypto constant-time signature provider
├── errors.ts                   # ToolError, SecurityError
└── tools/
    ├── generate-basic-pdf.ts
    ├── add-barcode.ts
    ├── sign-pdf.ts
    ├── add-international-text.ts
    ├── add-table.ts
    ├── add-form.ts
    ├── embed-image.ts
    ├── inspect-pdf.ts
    ├── verify-pdf.ts
    ├── validate-pdf.ts
    ├── add-attachment.ts
    ├── extract-attachments.ts
    ├── extract-text.ts
    ├── merge-pdfs.ts
    ├── split-pdf.ts
    ├── extract-pages.ts
    └── prepare-signature-placeholder.ts
tests/                          # vitest suites

---

🗺 Roadmap

v1.3.0 is shipped. The full plan — released milestones, in-progress work, and long-term direction — lives in ROADMAP.md.

Blocked upstream (page-tree manipulation):

  • redact_pdf and an encrypted-PDF round-trip — pdfnative does not yet export the content-redaction / decryption primitives required to build these safely. They remain on the roadmap, blocked on an upstream API. (merge_pdfs, split_pdf and extract_pages shipped in v1.3.0.)

Have a feature idea? Open an issue or PR.

---

⭐ Star the project

If pdfnative-mcp is useful to you, please ⭐ this repository — and consider also starring the underlying engine Nizoka/pdfnative. Stars help others discover the project and motivate continued development.

---

🤝 Contributing

Contributions are very welcome. Please read CONTRIBUTING.md, check the open issues, and follow the code of conduct.

---

📄 License

MIT © 2026 Nizoka

pdfnative-mcp is built on top of pdfnative and the Model Context Protocol TypeScript SDK.

See related servers & alternatives →

Related MCP servers

Browse all →

Related guides

Hand-picked reading to help you choose and use Files & Docs servers.