Back to Browse

Pdfnative MCP Server

by Nizoka
Developer ToolsModerate7.1MCP RegistryLocal
Free

Server data from the Official MCP Registry

PDF MCP server: PDF/A, PDF/X-4, PAdES (LTV), forms, 32 scripts, JPEG 2000, spot colours. 28 tools

About

PDF MCP server: PDF/A, PDF/X-4, PAdES (LTV), forms, 32 scripts, JPEG 2000, spot colours. 28 tools

Security Report

7.1
Moderate7.1Low Risk

pdfnative-mcp is a PDF generation and manipulation MCP server that runs locally over stdio, with an optional loopback-only HTTP mode protected by an opt-in bearer token. The visible code shows deliberate security hardening (output sandboxing, zip-bomb caps, refusal to cache encrypted or password-bearing outputs, weak-token rejection) and no exfiltration, shell execution, or hardcoded secrets in the excerpts reviewed. Remaining concerns are minor: the HTTP mode is unauthenticated by default and the excerpt is truncated so not every tool implementation was inspected. Supply chain analysis found 2 known vulnerabilities in dependencies (0 critical, 1 high severity). Package verification found 1 issue.

6 files analyzed · 6 issues found

Security scores are indicators to help you make informed decisions, not guarantees. Always review permissions before connecting any MCP server.

Permissions Required

This plugin requests these system permissions. Most are normal for its category.

File System Read

Reads files on your machine. Normal for tools that analyze or process local data.

File System Write

Writes or modifies files on your machine. Check that this is expected for the tool.

env_vars

Check that this permission is expected for this type of plugin.

process_spawn

Check that this permission is expected for this type of plugin.

HTTP Network Access

Connects to external APIs or services over the internet.

What You'll Need

Set these up before or after installing:

Absolute path of a sandboxed directory where outputMode='file' may write PDFs. Unset: every tool returns base64 only (file output disabled).Optional

Environment variable: PDFNATIVE_MCP_OUTPUT_DIR

Optional public base URL of PDFNATIVE_MCP_OUTPUT_DIR when the operator serves it over HTTP (e.g. https://files.example.com/pdf/). File-mode results then carry url (base + sandbox-relative path, percent-encoded) and name it instead of the host path. Absolute http(s) URL, no credentials, query or fragment; requires PDFNATIVE_MCP_OUTPUT_DIR; invalid value refuses to start. Never requested by the server.Optional

Environment variable: PDFNATIVE_MCP_OUTPUT_BASE_URL

Opt-in content-addressed response cache directory (SHA-256 keyed, 1h TTL, 256 MiB LRU, plaintext at rest). Never caches encrypt/decrypt, sign, timestamp, add_ltv, update_metadata, encrypted builds or file output.Optional

Environment variable: PDFNATIVE_MCP_CACHE_DIR

Optional operator font sandbox: absolute path of a directory of .ttf / .otf files (at most 64, 16 MiB each), each parsed by the engine and registered at boot under the slug of its file name; tools name one with the font input (FONT_NOT_FOUND otherwise). An invalid directory or file refuses to start. Never a path from a tool argument.Optional

Environment variable: PDFNATIVE_MCP_FONT_DIR

Serve Streamable HTTP on this loopback port instead of stdio (MCP 2026-07-28, stateless). Unauthenticated unless PDFNATIVE_MCP_HTTP_TOKEN is set.Optional

Environment variable: PDFNATIVE_MCP_PORT

Opt-in bearer token for the HTTP transport (>= 16 chars, no whitespace). When set, /mcp requires 'Authorization: Bearer <token>' or answers 401. Never logged.Required

Environment variable: PDFNATIVE_MCP_HTTP_TOKEN

Per-stream FlateDecode decompression cap in bytes (zip-bomb mitigation; default 104857600 = 100 MiB). Integer >= 1024; an invalid value refuses to start the server.Optional

Environment variable: PDFNATIVE_MCP_MAX_INFLATE_BYTES

ISO 8601 instant with a time zone (e.g. 2026-01-01T00:00:00Z) pinned as the creation date of every generated document: reproducible bytes on any host. A call's own creationDate still wins. An invalid value refuses to start the server.Optional

Environment variable: PDFNATIVE_MCP_CREATION_DATE

reproducible-builds.org convention: integer seconds since the Unix epoch, used as the pinned creation date when PDFNATIVE_MCP_CREATION_DATE is unset. An invalid value refuses to start the server.Optional

Environment variable: SOURCE_DATE_EPOCH

http(s) URL of the RFC 3161 timestamp authority used by sign_pdf timestamp=true and timestamp_pdf (PAdES B-T / B-LTA). Unset: those calls fail with TSA_NOT_CONFIGURED and no network request is made. Tool arguments can never supply a URL.Optional

Environment variable: PDFNATIVE_MCP_TSA_URL

Optional Authorization header value sent to the TSA (e.g. 'Basic ...' or 'Bearer ...'). Never logged or echoed.Required

Environment variable: PDFNATIVE_MCP_TSA_AUTH

'ocsp', 'crl' or 'ocsp,crl': enables online revocation collection for add_ltv mode='online' (PAdES B-LT). Unset: that mode fails with REVOCATION_NOT_CONFIGURED; mode='offline' stays fully offline. Requires PDFNATIVE_MCP_NETWORK_ALLOWED_HOSTS.Optional

Environment variable: PDFNATIVE_MCP_REVOCATION

Comma-separated allow-list of OCSP / CRL responder hosts ('host', 'host:port' or '*.suffix'). Mandatory when PDFNATIVE_MCP_REVOCATION is set: responder URLs found in certificates are fetched only if the host matches (http(s) only, no credentials, no redirects, internal addresses rejected unless listed verbatim).Optional

Environment variable: PDFNATIVE_MCP_NETWORK_ALLOWED_HOSTS

Per-request timeout for TSA / OCSP / CRL calls in milliseconds, 1000-120000 (default 10000).Optional

Environment variable: PDFNATIVE_MCP_NETWORK_TIMEOUT_MS

How to Install

Add this to your MCP configuration file:

{
  "mcpServers": {
    "io-github-nizoka-pdfnative-mcp": {
      "env": {
        "SOURCE_DATE_EPOCH": "your-source-date-epoch-here",
        "PDFNATIVE_MCP_PORT": "your-pdfnative-mcp-port-here",
        "PDFNATIVE_MCP_TSA_URL": "your-pdfnative-mcp-tsa-url-here",
        "PDFNATIVE_MCP_FONT_DIR": "your-pdfnative-mcp-font-dir-here",
        "PDFNATIVE_MCP_TSA_AUTH": "your-pdfnative-mcp-tsa-auth-here",
        "PDFNATIVE_MCP_CACHE_DIR": "your-pdfnative-mcp-cache-dir-here",
        "PDFNATIVE_MCP_HTTP_TOKEN": "your-pdfnative-mcp-http-token-here",
        "PDFNATIVE_MCP_OUTPUT_DIR": "your-pdfnative-mcp-output-dir-here",
        "PDFNATIVE_MCP_REVOCATION": "your-pdfnative-mcp-revocation-here",
        "PDFNATIVE_MCP_CREATION_DATE": "your-pdfnative-mcp-creation-date-here",
        "PDFNATIVE_MCP_OUTPUT_BASE_URL": "your-pdfnative-mcp-output-base-url-here",
        "PDFNATIVE_MCP_MAX_INFLATE_BYTES": "your-pdfnative-mcp-max-inflate-bytes-here",
        "PDFNATIVE_MCP_NETWORK_TIMEOUT_MS": "your-pdfnative-mcp-network-timeout-ms-here",
        "PDFNATIVE_MCP_NETWORK_ALLOWED_HOSTS": "your-pdfnative-mcp-network-allowed-hosts-here"
      },
      "args": [
        "-y",
        "pdfnative-mcp"
      ],
      "command": "npx"
    }
  }
}

Documentation

View on GitHub

From the project's GitHub README.

pdfnative-mcp

MCP server for PDF generation, PDF/A archival, PDF/X-4 print exchange, spot colours, right-to-left and 32-script text, JPEG 2000, fine typography, PAdES signing with long-term validation, AcroForms, merge/split, encryption and layout preview — 28 tools and 7 prompts on the pdfnative engine (zero-dependency, ISO 32000-1 compliant), for Claude Desktop, Cursor, ChatGPT and any Model Context Protocol client.

npm version npm downloads Node version License: MIT CI MCP pdfnative TypeScript OpenSSF Scorecard CodeQL Fuzz MCP Registry


✨ Features

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

ToolPurpose
generate_basic_pdfMulti-page documents from 13 block kinds — heading, paragraph, list, table, image (JPEG/PNG/JPEG 2000), link, toc (printed table of contents), barcode, svg, formField, chart, pageBreak, spacer — every DocumentBlock the engine offers. Embedded newlines auto-split into paragraphs. Optional pdfA, pdfx (new in v1.7.0), print, metadata, embedFonts, watermark, outline, layout options (pageSize, margins, headerTemplate / footerTemplate, compress, debug, encrypt), typography (new in v1.7.0) and CMYK colours (new in v1.7.0).
inspect_layout (new in v1.6.0)Read-only pagination dry run of the same blocks (+ title, footerText, pdfA, normalize, embedFonts, font, pageSize, margins, headerTemplate, footerTemplate, typography): page count and where every block lands, no PDF produced.
add_barcodeQR Code, Code 128, EAN-13, Data Matrix, PDF417 — embedded in a single-page PDF.
add_international_text32 Unicode scripts — Gujarati, Gurmukhi, Kannada, Malayalam and Odia (new in v1.8.0), Lao, Tai Tham, New Tai Lue, Tai Le and Cham (v1.7.0) — plus Latin, math and COLRv1 colour emoji (flag / ZWJ sequences, skin-tone modifiers), with BiDi & OpenType shaping; multi-lang per document.
add_tableTabular reports with smart fields (wrap, repeatHeader, zebra, caption, minRowHeight, cellPadding).
add_formCreate a new interactive AcroForm PDF with text fields, text areas, checkboxes, radio buttons, dropdowns, list boxes (+ placeholder hint text).
read_form_fieldsRead-only enumeration of an existing AcroForm's field tree (names, types, values, widgets).
fill_formFill and/or flatten an existing AcroForm (non-destructive incremental update).
add_chartNative vector charts v2 — bar / barH / stackedBar / stackedBarH / line / area / scatter / pie / donut, secondary axis, log & time scales, data labels, per-value bar colours and optional series labels (new in v1.8.0) (pure PDF path operators, PDF/A-safe).
embed_imageEmbed a JPEG, PNG or JPEG 2000 image (image/jp2, new in v1.8.0) (base64) into a titled PDF document (align, alt text for tagged output).
prepare_signature_placeholderOptional step 1 of the sign workflow — create a PDF with a /Sig placeholder (signer metadata, subFilter, reserveTimestamp baked in).
sign_pdfPAdES B-B / B-T CMS signature (RSA-SHA256/384/512, ECDSA-SHA256 P-256; profile: 'pades', timestamp, certChainDerBase64, multiple signatures, pinnable signingTime). Auto-injects a placeholder when needed.
add_ltv (new in v1.6.0)PAdES B-LT — embed a /DSS with certificates + OCSP/CRL material (operator-configured provider, or caller-supplied offline material composed by the engine — `match: 'all'
timestamp_pdf (new in v1.6.0)PAdES B-LTA — append an RFC 3161 /DocTimeStamp from the operator-configured TSA; re-run to extend the archival chain.
verify_pdfVerify every PAdES signature and document timestamp (integrity + signature value + optional chain trust; a /DocTimeStamp counts in allValid like any signature); ltv: true reports the B-B…B-LTA level.
validate_pdfValidate a Tagged PDF for PDF/UA (ISO 14289-1) structural conformance, or with standard: 'pdf-x-4' (new in v1.7.0) the structural prerequisites of PDF/X-4 (ISO 15930-7) — read-only, not a certified preflight.
add_attachmentGenerate a PDF/A-3 document with embedded files (Factur-X / ZUGFeRD invoices).
extract_attachmentsRead-only extraction of embedded files (Factur-X / ZUGFeRD XML round-trip) with byte-for-byte payloads.
extract_textUnicode text extraction (resolves /ToUnicode; logical order for right-to-left and Indic text, tagged or not) with optional positioned runs; onStreamError (new in v1.8.0); opens encrypted PDFs via password.
inspect_pdfRead-only inspection: PDF version, page count, encryption (+ precise encryptionInfo), PDF/A claim, PDF/X claim (pdfX, new in v1.7.0), signatures (+ inventory, /DSS, document timestamps), page boxes, /Trapped, attachments, placeholder state, annotations: true inventory of existing page annotations.
update_metadata (new in v1.6.0)Rewrite /Info title / author / subject / keywords (+ XMP, dates included) of an existing PDF as an incremental update; pin modDate for reproducible bytes.
encrypt_pdfRe-secure a PDF with AES-128 / AES-256 (owner/user passwords, permissions, password rotation).
decrypt_pdfEmit an unencrypted copy of an RC4 / AES-128 / AES-256 document.
merge_pdfsConcatenate 2–50 PDFs into one via pdfnative's page-tree API (page boxes preserved).
split_pdfSplit one PDF into one document per page range (multi-output).
extract_pagesPull an arbitrary page subset into a single PDF.
annotate_pdfAdd markup annotations (highlight, note, square/circle, line, freetext) and link annotations (new in v1.8.0) as a visual overlay — not a redaction.
draft_governance_issueDraft a governance-compliant GitHub issue locally for human review; never submits, no network.

New in v1.8.0:

  • 🎨 Spot colours — print.spotColours declares inks with a process alternate; { spot, tint } (a /Separation plate) and { inks: { … } } (a /DeviceN mix) are accepted wherever a colour is — table borders, templates, watermarks, charts, SVG, annotations. An undeclared ink is refused by name.
  • ↔️ Right-to-left documents — direction: 'auto' | 'ltr' | 'rtl' on the nine document tools, inspect_layout and each paragraph; untagged output carries /ActualText on right-to-left and reordered shaped runs (actualText: false to opt out), so extract_text returns reading order with or without a PDF/A claim.
  • 🌏 32 Unicode scripts — add_international_text gains gu (Gujarati), pa (Gurmukhi), kn (Kannada), ml (Malayalam) and or (Odia); every shaper names its glyphs in ToUnicode, so Tai Tham passes PDF/A-2u too.
  • 🖼️ JPEG 2000 — mimeType: 'image/jp2' (a JP2 file or a raw codestream) on embed_image, the image block and image watermarks, embedded as /JPXDecode without re-encoding; PDFA1_JPX_IMAGE under PDF/A-1, PDFA_JPX_IMAGE for an opacity channel.
  • 🖨️ PDF/X-4 + PDF/A-2 dual claim — pdfx: 'pdfx4' combines with pdfA: 'pdfa2b' | 'pdfa2u' in one file; pdfa1b and pdfa3b are refused with the engine's own message.
  • 🔗 Link annotations — annotate_pdf type: 'link' adds a /URI link to an existing page (http: / https: / mailto:).
  • 🔤 Operator fonts — PDFNATIVE_MCP_FONT_DIR registers the operator's .ttf / .otf files at boot (parsed by the engine, ≤ 64 files); font: '<slug>' on generate_basic_pdf, inspect_layout and add_international_text draws that face first — FONT_NOT_FOUND lists the slugs. See docs/guides/FONTS.md.
  • 🌐 File mode behind a reverse proxy — PDFNATIVE_MCP_OUTPUT_BASE_URL maps the sandbox to a public base URL: file-mode results carry url and name it instead of the host's path (issue #66); pure string formatting, never requested.
  • 📊 Charts — series[].colors (one colour per bar) and an optional series label ("Series N" otherwise).
  • 🔏 LTV, ECDSA — add_ltv mode: 'offline' composes /DSS + /VRI through the engine (match: 'all' | 'chain'); verify_pdf verifies ECDSA through the engine's ecdsaVerifyHash (the local P-256 code is gone).
  • 📖 extract_text — a content stream over the decompression cap is now PDF_PARSE_FAILED naming the remedy (onStreamError: 'skip' restores the 1.7.0 empty page); inspect_pdf decodes /Info text strings (UTF-16BE titles read back as text).
  • 🤝 Governance as resources — pdfnative://governance/policy and pdfnative://governance/rules serve the AI-governance contract byte-identical to the repository (always listed); 13 engine diagnostics (4 new), 48 error codes (FONT_NOT_FOUND), prepare_signature_placeholder.blocks takes 5000 items like generate_basic_pdf (llama.cpp grammar, issue #65); calls carrying password are never cached.
  • 🧪 Hardening — the pdfnative 1.9 release pipeline (guard → build → publish → attest → registry: Trusted Publishing, SHA-512-pinned npm client, registry bytes attested with three SBOMs, server.json published to the MCP registry with the workflow's OIDC identity), ClusterFuzzLite over five boundary targets, workflow-lint (zizmor + actionlint) as a required check, block-mode egress on the Linux jobs whose hosts are baselined (audit mode with a dated reason elsewhere), CodeQL on the workflows, Node 26 advisory, a pack-manifest gate step, every Dependabot and code-scanning alert of the 1.7.0 line closed. Catalogue: tools/list ≈ 357 kB under a 384 KiB budget.
  • ⬆ Engine upgrade — pdfnative v1.9.0. No breaking change to the tool API; the bytes that change (lean compact subsets, /ActualText spans, one text object per line) are declared in the release note and the sample baseline is re-anchored once.

New in v1.7.0:

  • 🔤 Fine typography — an opt-in typography object on the nine document tools and on inspect_layout: splitParagraphs with orphans / widows, keepHeadingsWithNext, unitBinding, bindShortWords, punctuationSpacing ('fr', 'fr-CA' or explicit rules), opticalMargins, metrics: 'exact', fontFeatures (11 OpenType tags), kerning, hyphenationLanguage. Paragraph blocks gain align (left / right / center / justify), keepWithNext and splittable; heading blocks gain keepWithNext. Honest limits: kerning, fontFeatures and the 'fr' narrow no-break space need embedFonts: true (base-14 Helvetica degrades 'fr' to 'fr-CA'); tnum / lnum change nothing on the bundled Noto Sans (diagnostic TYPOGRAPHY_FEATURE_INEFFECTIVE); no hyphenation dictionary is installed, so hyphenationLanguage has no effect here — soft hyphens (U+00AD) are honoured. See docs/guides/TYPOGRAPHY.md.
  • 🎨 CMYK everywhere a colour is accepted — 'c m y k' operand strings (0–1) and [c, m, y, k] percent tuples (0–100) beside the existing hex / RGB forms: watermarks, header / footer templates, table cell borders, outline entries, charts, link and svg blocks, annotate_pdf. Every 1.6.0 colour form still validates.
  • 🖨️ PDF/X-4 — pdfx: 'pdfx4' on six generation tools (generate_basic_pdf, add_table, add_chart, add_barcode, embed_image, add_international_text), CMYK or Gray outputIntent profiles beside RGB, print.marks.colourBars, and validate_pdf { standard: 'pdf-x-4' } to check the result; inspect_pdf reports the claim (pdfX, check 'pdfx'). It requires the printer's ICC profile (device class prtr — none is bundled), needs embedFonts: true for a conformant file (PDFX_NO_FONT_ENTRIES otherwise; strict: true refuses), and combines with pdfA: 'pdfa2b' | 'pdfa2u' since v1.8.0 (pdfa1b / pdfa3b and encrypt refused). The validation is structural — not a certified preflight; the result says so itself in caveats[]. See docs/guides/PRINT.md.
  • 🌏 27 Unicode scripts — add_international_text accepts lo (Lao), nod (Tai Tham), khb (New Tai Lue), tdd (Tai Le) and cjm (Cham); ha, yo, ig, sw are aliases of latin (tone marks attach); emoji skin-tone modifiers render. Tai Tham under PDF/A must use pdfa2b, not pdfa2u (one glyph lacks a ToUnicode entry upstream).
  • 🔁 Reproducible on every host — every date is written in UTC, {date} in a header or footer follows the pinned instant, and the operator can pin the whole process with PDFNATIVE_MCP_CREATION_DATE or SOURCE_DATE_EPOCH (see Environment variables). Not covered, by design: signingTime, modDate, RFC 3161 tokens and revocation data, encryption, ECDSA signatures. See docs/guides/REPRODUCIBLE.md.
  • 🚦 strict escalates by diagnostic code — PDFA_* → PDF_A_COMPLIANCE_VIOLATION, PDFX_* → PDF_X_COMPLIANCE_VIOLATION (new), anything else → DIAGNOSTIC_ESCALATED (new). Both new codes can only be returned by a call that sets strict: true.
  • 🧩 A seventh MCP prompt, typography — and print_ready, reproducible_output, pdfa_valid rewritten for CMYK, PDF/X-4, colour bars and the UTC / operator pin.
  • 🐛 Fixes — a 0–1 RGB triple (watermark.color, the annotate_pdf colours) now renders the colour it names ([1, 0, 0] used to render almost black); any unexpected failure of a tool that takes PDF input is classified PDF_PARSE_FAILED instead of surfacing uncoded.
  • ✅ Closed upstream — a PDF/A form built with embedFonts: true now validates under veraPDF (the AcroForm font is embedded), and inspect_layout measures a toc block exactly as the build lays it out.
  • 🧪 One gate, hardened CI, verified docs — npm run gate is the single definition of green (the built server is driven over stdio and stdout must carry JSON-RPC frames only); veraPDF is blocking over a 41-file conformance corpus; a 96-sample byte baseline guards the output; npm run verify:docs holds every count, version, tool, error code and operator variable quoted in the docs to docs/assets/ecosystem.json and the source tree.
  • 🧾 Catalogue — tools/list grows to ≈ 306 kB in 1.7.0 (the typography fragment and the widened colour schemas are inlined in every tool that carries them; npx tsx scripts/tool-shape.ts --check held it under 320 KiB and the instructions under 8 KiB); _meta.apiVersion is 1.7.0.
  • ⬆ Engine upgrade — pdfnative v1.8.0. No breaking change to the tool API; the bytes that do change (embedded TrueType subsets, print.marks, shaped text with mark positioning, UTC dates) are listed under Upgrade in release-notes/v1.7.0.md.

New in v1.6.0:

  • 🧱 Full engine coverage — 13 block kinds — generate_basic_pdf accepts every DocumentBlock pdfnative offers: the new table, image, link, toc, barcode, svg and formField blocks share their body with the dedicated tools (add_table, embed_image, add_barcode, add_form) so a standalone artefact and an inline block validate and render identically. Rules: link accepts http: / https: / mailto: only (control characters rejected); image blocks are bounded (12 M base64 characters each, 24 MiB decoded per call; PNG must be 8-bit, non-interlaced, without alpha or palette — rejected with a remedy); svg covers paths, basic shapes and <text> (no transform, <g>, gradients or CSS — silently ignored; nothing is ever fetched); toc pairs with outline: 'auto'; formField under a PDF/A claim reports PDFA_UNEMBEDDED_FORM_FONT; barcode has no alt (engine limitation).
  • 📐 Layout options on the nine document tools — pageSize (A4 default, Letter, Legal, A3, Tabloid), margins (all four, 0–200 pt), headerTemplate / footerTemplate with {page} {pages} {title} {date} (a footerTemplate replaces the default footer, so footerText is then ignored; {date} was the build-day wall clock in 1.6.0 — since v1.7.0 it follows the pinned instant), compress (FlateDecode streams — smaller file, different bytes; XMP stays plain under PDF/A) and debug (guide rectangles, unmarked content — not for PDF/UA). Absent by default, so default output stays byte-identical.
  • 🔐 Encryption at build time — encrypt on seven document tools (generate_basic_pdf, add_table, add_form, add_international_text, embed_image, add_barcode, add_chart): Standard Security Handler, AES-128 default / AES-256, keeps the AcroForm (unlike encrypt_pdf, which rebuilds the page tree). Exclusive with pdfA (VALIDATION_ERROR), never cached; not offered on prepare_signature_placeholder (must stay signable) or add_attachment (PDF/A-3).
  • 📏 inspect_layout — the 28th tool: a read-only pagination dry run over the same blocks and layout inputs, reporting totalPages and each block's page / x / top / width / height without rendering a PDF. Known engine gap in 1.6.0 (closed in v1.7.0): a toc block was measured as 0 pt, so documents with a printed contents could paginate one page later than previewed.
  • 🔎 inspect_pdf annotations: true — lists every page annotation (subtype, 0-based page, rect, contents truncated to 200 chars, title, colour, quadPoints, link URL) plus annotationCount; new check: 'annotations'.
  • 🖼️ Image watermarks — watermark.image (JPEG/PNG, default opacity 0.10, own 8 MiB cap) on generate_basic_pdf and add_table, alone or combined with text (default opacity 0.15); position: 'background' | 'foreground' for both. Either opacity below 1.0 is rejected under pdfa1b.
  • 🧯 PDFNATIVE_MCP_MAX_INFLATE_BYTES — operator override of the engine's 100 MiB per-stream decompression cap (integer ≥ 1024; an invalid value refuses to start). A capped attachment stream fails extract_attachments includeData: true with PDF_PARSE_FAILED; extract_text degrades to empty page text (the engine swallows per-page decode failures).
  • 📝 Forms — add_form and formField blocks gain listbox and placeholder; fieldType: 'textarea' now reaches the engine as multilineText (it was passed through unmapped before and rendered as a single-line field — a bug fix that changes bytes for that input). embed_image gains align and alt.
  • 🔏 PAdES long-term validation ladder — sign_pdf gains profile: 'pades' (ETSI EN 319 142-1 baseline, ESS signing-certificate-v2, ETSI.CAdES.detached), timestamp: true (B-T, RFC 3161), RSA-SHA384/512, certChainDerBase64, fieldName / allowMultiple for several signatures; new add_ltv embeds a /DSS (B-LT, mode: 'online' through the operator provider or mode: 'offline' with caller-supplied DER material); new timestamp_pdf appends a /DocTimeStamp (B-LTA). verify_pdf ltv: true reports profile, timestamp, revocation status and ltvLevel. See docs/guides/LTV.md.
  • 🌐 Network charter — no outbound request by default. The only egress the server can ever perform goes to the RFC 3161 / OCSP / CRL endpoints the operator configured (PDFNATIVE_MCP_TSA_URL, PDFNATIVE_MCP_REVOCATION, PDFNATIVE_MCP_NETWORK_ALLOWED_HOSTS), behind an SSRF guard; tool arguments can never supply a URL.
  • 🖨️ Print production — every document tool accepts print (TrimBox / BleedBox / ArtBox / CropBox or the bleed shorthand, crop + registration marks, /UserUnit), metadata (/Author, /Subject, /Keywords, /Trapped) and outputIntent (custom RGB ICC for PDF/A); viewerPreferences gains duplex, pickTrayByPDFSize, printPageRange, numCopies. inspect_pdf pages: true reports the boxes; merge / split / extract preserve them. See docs/guides/PRINT.md.
  • ✍️ update_metadata — rewrite /Info + XMP of an existing PDF as an incremental update (earlier revisions and signatures preserved verbatim).
  • 📊 Charts v2 — stackedBar / stackedBarH / area / scatter, secondary right axis (axis2), axis.scale: 'log', xAxis.type: 'linear' | 'time', dataLabels, labelStride / labelRotation; overlapping category labels are thinned automatically.
  • 📜 Honest PDF/A — embedFonts: true embeds Noto Sans Latin (base-14 Helvetica is not embedded, so a PDF/A claim on plain Latin text is rejected by veraPDF), strict: true fails instead of producing a non-conformant file, includeDiagnostics: true echoes engine diagnostics. Local veraPDF script (npm run validate:pdfa) over a 26-file corpus (24 validated, 3 of them negative canaries; 2 page-tree outputs skipped) and a fail-closed VERAPDF_REQUIRED=1 mode; the CI workflow pins the installer by SHA-256 and stays non-blocking in 1.6.0 (blocking since v1.7.0, where --require-all on the gate replaces VERAPDF_REQUIRED=1). Known engine gaps in 1.6.0: add_form output fails PDF/A-2b even with embedFonts (unembedded /DR /Helv — closed in v1.7.0), and a prepare_signature_placeholder output is conformant only once signed.
  • 🧰 inspect_pdf — signatures: true inventory, dss / docTimestampCount / trapped (presence-gated), new check values dss, docTimestamp, trapped; checks lists only the keys you requested, and signed is structural (a signed field exists — validity is verify_pdf's job).
  • 🔁 Reproducible output — opt-in creationDate on all nine document tools pins /CreationDate, the XMP dates and the trailer /ID; signingTime on prepare_signature_placeholder (and on sign_pdf, now with time-zone offsets) pins /Sig /M. Identical bytes on the same host time zone in 1.6.0 (on every host since v1.7.0: dates are written in UTC). Backed by the reproducible_output prompt.
  • 🛡️ Hardened boundary — strict input schemas (unknown or misspelt keys → VALIDATION_ERROR instead of being silently ignored); data:…;base64, prefixes tolerated, PEM-where-DER and double-encoded payloads rejected with the exact remedy; page-index mistakes on the page-tree tools are VALIDATION_ERROR with a 0-based hint; an unknown tool name is a JSON-RPC protocol error (-32602, [UNKNOWN_TOOL]).
  • 🔑 HTTP bearer token — opt-in PDFNATIVE_MCP_HTTP_TOKEN gates the Streamable HTTP endpoint (401 + WWW-Authenticate otherwise). Without it the loopback endpoint has no authentication — see SECURITY.md.
  • 🧾 Catalogue — tools/list is ≈ 245 kB (1.5.0: ≈ 108 kB) because every block kind, layout option and encrypt fragment is now advertised inline — no $ref / $defs by policy, so hosts that forward inputSchema to function-calling APIs never meet a reference; the server instructions are ≈ 6.7 kB (from 12.9 kB). Structure is guarded by scripts/tool-shape.mjs (scripts/tool-shape.ts since v1.7.0) + tests/catalogue-parity.test.ts, and tests/catalogue-superset.test.ts proves the live catalogue is a superset of the published 1.5.0 one; at most two executable _meta.examples per tool, the rest under examples/. Four new recipe prompts: pades_ladder, print_ready, reproducible_output, pdfa_valid.
  • 🐛 Fixes — signer metadata (signerName / reason / location / contactInfo) never reached the /Sig dictionary on pdfnative < 1.7; it is now baked at placeholder time. verify_pdf no longer reports allValid: false on B-LTA documents (a /DocTimeStamp was parsed as a CMS signature).
  • 🔌 MCP 2026-07-28 on the MCP TypeScript SDK v2 (@modelcontextprotocol/server) with automatic fallback to the 2025-era initialize handshake — existing hosts keep working unchanged. See MCP protocol compliance.
  • ⬆ Engine upgrade — pdfnative v1.7.0 (LTV, print production, charts v2, digest agility, flag / ZWJ emoji sequences, UAX #9 fixes).

New in v1.5.0:

  • 📊 Native vector charts — add_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 forms — read_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-trip — encrypt_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 extraction — extract_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 upgrade — pdfnative 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-loop — draft_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, since v1.6.0, no outbound call other than to operator-configured TSA / OCSP / CRL endpoints). Backed by the governance_contract and draft_issue_workflow MCP prompts.
  • ✏️ Markup annotations — annotate_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 script — add_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 tools — merge_pdfs, split_pdf, extract_pages (built on pdfnative v1.4.0's page-tree API; encrypted sources were rejected until v1.5.0 added password).

  • 🔖 Bookmarks, page labels & nested lists — generate_basic_pdf gains outline ('auto' or explicit tree), pageLabels, multi-level list items, and viewerPreferences.

  • 📐 Table cell borders & alignment — add_table gains cellBorders, cellVAlign, and viewerPreferences; add_international_text gains viewerPreferences.

  • 🔐 Constant-time signing — sign_pdf signs RSA and EC-DER keys through a node:crypto provider with a transparent pure-JS fallback (raw P-256 scalars stay pure JS, and verification is pure JS); 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.

  • 💧 Watermarks — generate_basic_pdf and add_table accept an optional watermark (text, opacity, angle, colour, position; image since v1.6.0) 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; read_form_fields since v1.5.0) 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 fix — mcpName 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 upgrade — pdfnative 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 agent contract, docs/AGENT_CONTRACT.md (catalogue, decision tree, recipes, error table); contributors and coding agents start at AGENTS.md.
  • 🆕 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), 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), and add_ltv / timestamp_pdf / update_metadata plus print production and charts v2 (v1.6.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 } (plus diagnostics[] when includeDiagnostics: true, and a summary for add_ltv).
  • 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:

- 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 seven read-only tools (inspect_pdf, verify_pdf, validate_pdf, extract_text, extract_attachments, read_form_fields, inspect_layout) 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 } (+ ltvLevel with ltv: true); inspect_pdf keeps docTimestampCount / trapped / checksPassed when present.
  • fields: ['a', 'b.c'] — projects the structured result to named dot-paths; composes after verbosity. Unmatched paths are omitted and reported in _meta.unmatchedFields (with _meta.availableFields).

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 in the engine — pure JavaScript, no native bindings (this server adds only the MCP SDK and zod: three runtime dependencies in total).
  • ISO 32000-1 (PDF 1.7) compliant output.
  • PDF/A-1b/2b/2u/3b, AES-128/256 encryption, AcroForm, digital signatures.
  • 32 Unicode scripts (39 lang codes incl. latin, emoji, math and the four latin aliases) with built-in BiDi reordering, Arabic positional shaping, Indic / Thai OpenType shaping and, since v1.8.0, a base text direction (auto / ltr / rtl) for right-to-left documents.
  • PDF/X-4 print exchange, DeviceCMYK colour and fine typography (orphan / widow control, justification, French punctuation spacing, OpenType features).
  • 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 or Streamable HTTP.

Community-verified compatibility includes:

🔌 MCP protocol compliance

Since v1.6.0 the server is built on the MCP TypeScript SDK v2 (@modelcontextprotocol/server) and speaks MCP 2026-07-28:

Documentation truncated — see the full README on GitHub.

Reviews

No reviews yet

Be the first to review this server!