pdfnative-mcp
The pdfnative-mcp server is a full-featured PDF engine exposed via the Model Context Protocol, enabling AI clients to create, manipulate, sign, inspect, and extract data from PDF documents. It provides 14 production-grade tools:
PDF Generation
generate_basic_pdf: Create multi-page A4 PDFs from structured blocks (headings, paragraphs, lists, page breaks, spacers) with optional PDF/A conformance, watermarks, and footers.add_barcode: Embed QR Code, Code 128, EAN-13, Data Matrix, or PDF417 barcodes into a single-page PDF.add_international_text: Render text in 24 scripts (Arabic, Hebrew, CJK, Devanagari, Cyrillic, emoji, etc.) with full BiDi and OpenType shaping support.add_table: Build tabular reports with cell wrapping, zebra striping, repeated headers, captions, and adjustable cell padding.add_form: Create interactive AcroForm PDFs with text fields, checkboxes, radio buttons, and dropdowns.embed_image: Insert JPEG or PNG images (base64) into a PDF with optional captions and custom dimensions.add_attachment: Generate PDF/A-3 documents with embedded files (e.g., Factur-X/ZUGFeRD invoices).
Signing & Verification
prepare_signature_placeholder: Create a PDF with an unsigned/SigAcroForm placeholder as step 1 of a signing workflow.sign_pdf: Apply PAdES-compatible CMS digital signatures (RSA-SHA256 or ECDSA-SHA256), with automatic placeholder injection if needed.verify_pdf: Verify all PAdES signatures in a PDF for integrity, signature value, and optional chain trust.
Inspection & Extraction (Read-only)
inspect_pdf: Structural inspection covering PDF version, page count, encryption, PDF/A claim, signatures, attachments, and document info.validate_pdf: Check Tagged PDFs for PDF/UA (ISO 14289-1) structural conformance (accessibility).extract_attachments: Read embedded files from a PDF, with optional filename filtering and metadata-only mode.extract_text: Best-effort plain-text extraction from non-encrypted PDFs, page by page.
Key features: zero runtime dependencies, base64 or sandboxed file output modes, token-frugal verbosity options, and configuration via environment variables.
pdfnative-mcp
MCP server for PDF generation, PDF/A archival, PAdES signing with long-term validation, AcroForms, merge/split, encryption and layout preview — 28 tools on the pdfnative engine (zero-dependency, ISO 32000-1 compliant), for Claude Desktop, Cursor, ChatGPT and any Model Context Protocol client.
✨ Features
pdfnative-mcp exposes 28 production-grade tools to any MCP host:
Tool | Purpose |
| Multi-page documents from 13 block kinds — |
| Read-only pagination dry run of the same |
| QR Code, Code 128, EAN-13, Data Matrix, PDF417 — embedded in a single-page PDF. |
| 24 scripts (incl. Latin & COLRv1 colour emoji with flag / ZWJ sequences) with BiDi & OpenType shaping; multi-lang per document. |
| Tabular reports with smart fields (wrap, repeatHeader, zebra, caption, minRowHeight, cellPadding). |
| Create a new interactive AcroForm PDF with text fields, text areas, checkboxes, radio buttons, dropdowns, list boxes (+ |
| Read-only enumeration of an existing AcroForm's field tree (names, types, values, widgets). |
| Fill and/or flatten an existing AcroForm (non-destructive incremental update). |
| Native vector charts v2 — bar / barH / stackedBar / stackedBarH / line / area / scatter / pie / donut, secondary axis, log & time scales, data labels (pure PDF path operators, PDF/A-safe). |
| Embed a JPEG or PNG image (base64) into a titled PDF document ( |
| Optional step 1 of the sign workflow — create a PDF with a |
| PAdES B-B / B-T CMS signature (RSA-SHA256/384/512, ECDSA-SHA256 P-256; |
| PAdES B-LT — embed a |
| PAdES B-LTA — append an RFC 3161 |
| Verify every PAdES signature and document timestamp (integrity + signature value + optional chain trust; a |
| Validate a Tagged PDF for PDF/UA (ISO 14289-1) structural conformance (read-only). |
| Generate a PDF/A-3 document with embedded files (Factur-X / ZUGFeRD invoices). |
| Read-only extraction of embedded files (Factur-X / ZUGFeRD XML round-trip) with byte-for-byte payloads. |
| Unicode text extraction (resolves |
| Read-only inspection: PDF version, page count, encryption (+ precise |
| Rewrite |
| Re-secure a PDF with AES-128 / AES-256 (owner/user passwords, permissions, password rotation). |
| Emit an unencrypted copy of an RC4 / AES-128 / AES-256 document. |
| Concatenate 2–50 PDFs into one via pdfnative's page-tree API (page boxes preserved). |
| Split one PDF into one document per page range (multi-output). |
| Pull an arbitrary page subset into a single PDF. |
| Add markup annotations (highlight, note, square/circle, line, freetext) as a visual overlay — not a redaction. |
| Draft a governance-compliant GitHub issue locally for human review; never submits, no network. |
New in v1.6.0:
🧱 Full engine coverage — 13 block kinds —
generate_basic_pdfaccepts everyDocumentBlockpdfnative offers: the newtable,image,link,toc,barcode,svgandformFieldblocks 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:linkacceptshttp:/https:/mailto:only (control characters rejected);imageblocks 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);svgcovers paths, basic shapes and<text>(notransform,<g>, gradients or CSS — silently ignored; nothing is ever fetched);tocpairs withoutline: 'auto';formFieldunder a PDF/A claim reportsPDFA_UNEMBEDDED_FORM_FONT;barcodehas noalt(engine limitation).📐 Layout options on the nine document tools —
pageSize(A4default,Letter,Legal,A3,Tabloid),margins(all four, 0–200 pt),headerTemplate/footerTemplatewith{page}{pages}{title}{date}(afooterTemplatereplaces the default footer, sofooterTextis then ignored;{date}is the build-day wall clock, notcreationDate),compress(FlateDecode streams — smaller file, different bytes; XMP stays plain under PDF/A) anddebug(guide rectangles, unmarked content — not for PDF/UA). Absent by default, so default output stays byte-identical.🔐 Encryption at build time —
encrypton 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 (unlikeencrypt_pdf, which rebuilds the page tree). Exclusive withpdfA(VALIDATION_ERROR), never cached; not offered onprepare_signature_placeholder(must stay signable) oradd_attachment(PDF/A-3).📏
inspect_layout— the 28th tool: a read-only pagination dry run over the sameblocksand layout inputs, reportingtotalPagesand each block's page / x / top / width / height without rendering a PDF. Known engine gap: atocblock is measured as 0 pt, so documents with a printed contents may 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) plusannotationCount; newcheck: 'annotations'.🖼️ Image watermarks —
watermark.image(JPEG/PNG, default opacity 0.10, own 8 MiB cap) ongenerate_basic_pdfandadd_table, alone or combined withtext(default opacity 0.15);position: 'background' | 'foreground'for both. Either opacity below 1.0 is rejected underpdfa1b.🧯
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 failsextract_attachments includeData: truewithPDF_PARSE_FAILED;extract_textdegrades to empty page text (the engine swallows per-page decode failures).📝 Forms —
add_formandformFieldblocks gainlistboxandplaceholder;fieldType: 'textarea'now reaches the engine asmultilineText(it was passed through unmapped before and rendered as a single-line field — a bug fix that changes bytes for that input).embed_imagegainsalignandalt.🔏 PAdES long-term validation ladder —
sign_pdfgainsprofile: '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/allowMultiplefor several signatures; newadd_ltvembeds a/DSS(B-LT,mode: 'online'through the operator provider ormode: 'offline'with caller-supplied DER material); newtimestamp_pdfappends a/DocTimeStamp(B-LTA).verify_pdf ltv: truereports profile, timestamp, revocation status andltvLevel. Seedocs/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 thebleedshorthand, crop + registrationmarks,/UserUnit),metadata(/Author,/Subject,/Keywords,/Trapped) andoutputIntent(custom RGB ICC for PDF/A);viewerPreferencesgainsduplex,pickTrayByPDFSize,printPageRange,numCopies.inspect_pdf pages: truereports the boxes; merge / split / extract preserve them. Seedocs/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: trueembeds Noto Sans Latin (base-14 Helvetica is not embedded, so a PDF/A claim on plain Latin text is rejected by veraPDF),strict: truefails instead of producing a non-conformant file,includeDiagnostics: trueechoes 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-closedVERAPDF_REQUIRED=1mode; the CI workflow pins the installer by SHA-256 and stays non-blocking in 1.6.0. Known engine gaps:add_formoutput fails PDF/A-2b even withembedFonts(unembedded/DR /Helv), and aprepare_signature_placeholderoutput is conformant only once signed.🧰
inspect_pdf—signatures: trueinventory,dss/docTimestampCount/trapped(presence-gated), newcheckvaluesdss,docTimestamp,trapped;checkslists only the keys you requested, andsignedis structural (a signed field exists — validity isverify_pdf's job).🔁 Reproducible output — opt-in
creationDateon all nine document tools pins/CreationDate, the XMP dates and the trailer/ID;signingTimeonprepare_signature_placeholder(and onsign_pdf, now with time-zone offsets) pins/Sig /M. Identical bytes on the same host time zone. Backed by thereproducible_outputprompt.🛡️ Hardened boundary — strict input schemas (unknown or misspelt keys →
VALIDATION_ERRORinstead 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 areVALIDATION_ERRORwith 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_TOKENgates the Streamable HTTP endpoint (401+WWW-Authenticateotherwise). Without it the loopback endpoint has no authentication — seeSECURITY.md.🧾 Catalogue —
tools/listis ≈ 245 kB (1.5.0: ≈ 108 kB) because every block kind, layout option andencryptfragment is now advertised inline — no$ref/$defsby policy, so hosts that forwardinputSchemato function-calling APIs never meet a reference; the server instructions are ≈ 6.7 kB (from 12.9 kB). Structure is guarded byscripts/tool-shape.mjs+tests/catalogue-parity.test.ts, andtests/catalogue-superset.test.tsproves the live catalogue is a superset of the published 1.5.0 one; at most two executable_meta.examplesper tool, the rest underexamples/. Four new recipe prompts:pades_ladder,print_ready,reproducible_output,pdfa_valid.🐛 Fixes — signer metadata (
signerName/reason/location/contactInfo) never reached the/Sigdictionary on pdfnative < 1.7; it is now baked at placeholder time.verify_pdfno longer reportsallValid: falseon B-LTA documents (a/DocTimeStampwas parsed as a CMS signature).🔌 MCP 2026-07-28 on the MCP TypeScript SDK v2 (
@modelcontextprotocol/server) with automatic fallback to the 2025-erainitializehandshake — 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_chartrenders bar / horizontal-bar / line / pie / donut charts as pure PDF path operators (zero rasterisation, PDF/A-safe with auto alt text).generate_basic_pdfalso accepts achartblock for composition with text and tables.📝 Fill & flatten forms —
read_form_fieldslists an existing AcroForm's fields;fill_formfills and/or flattens it via a non-destructive incremental update (the counterpart toadd_form).🔐 Encryption round-trip —
encrypt_pdfre-secures with AES-128 / AES-256 (RC4 never emitted),decrypt_pdfrecovers an unencrypted copy, apasswordinput opens encrypted sources on the read-only tools, andmerge_pdfs/split_pdf/extract_pagesgainpassword+encrypt.🔤 Real text extraction —
extract_textnow resolves each font's/ToUnicodeCMap (no more glyph-index output) and can return positionedruns.🔗 Native MCP resources — sandboxed generated PDFs become
pdfnative://output/…resources (resources/list+resources/read), with aresource_linkin 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_issuelets 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 thegovernance_contractanddraft_issue_workflowMCP prompts.✏️ Markup annotations —
annotate_pdfoverlays 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/PageLabelsranges (roman, decimal, prefixed).∑ Math / scientific script —
add_international_textacceptslang: 'math'(explicit, likeemoji) to embed the Noto Sans Math face on demand.🧩 MCP prompts — the server now advertises the
promptscapability withgovernance_contractanddraft_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 addedpassword).🔖 Bookmarks, page labels & nested lists —
generate_basic_pdfgainsoutline('auto'or explicit tree),pageLabels, multi-levellistitems, andviewerPreferences.📐 Table cell borders & alignment —
add_tablegainscellBorders,cellVAlign, andviewerPreferences;add_international_textgainsviewerPreferences.🔐 Constant-time signing —
sign_pdfsigns RSA and EC-DER keys through anode:cryptoprovider 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, afilenamefilter, and anincludeData: falsemetadata-only probe.💧 Watermarks —
generate_basic_pdfandadd_tableaccept an optionalwatermark(text, opacity, angle, colour, position;imagesince v1.6.0) rendered on every page.🌐 Unicode
normalize— opt-inNFC/NFD/NFKC/NFKDongenerate_basic_pdfandadd_international_text.🪙 Token-frugal reads — the read-only tools (
inspect_pdf,verify_pdf,validate_pdf,extract_text,extract_attachments;read_form_fieldssince v1.5.0) accept optionalverbosity: 'summary'andfields: […]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
resourcecontent block instead of also being copied intostructuredContent.🔧 MCP registry publish fix —
mcpNamenow 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
\nin 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_pdfnow reportshasSignaturePlaceholderand per-attachment summary; newcheckvalues'placeholder'and'attachments'.🆕 Signing ergonomics:
sign_pdfaccepts ECDSA SEC1 / PKCS#8 DER keys and auto-injects a/Sigplaceholder 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.apiVersionand per-tool_meta.examplesfor AI-agent discovery — seedocs/API_STABILITY.md.🆕 AI agent guide:
docs/AI_GUIDE.md— decision tree + common pitfalls. See also the rootAGENTS.mdoperations manual.🆕 PDF/A authoring guide:
docs/guides/PDFA.md.🛠 Env-var rename:
PDFNATIVE_MCP_OUTPUT_DIR(wasPDFNATIVE_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), theadd_chart/read_form_fields/fill_form/encrypt_pdf/decrypt_pdftools plus the encrypted round-trip and native MCP resources (v1.5.0), andadd_ltv/timestamp_pdf/update_metadataplus print production and charts v2 (v1.6.0).redact_pdfstays 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 embeddedresourcecontent block (adata:application/pdf;base64,…URI);structuredContentcarries only{ mode, sizeBytes }(plusdiagnostics[]whenincludeDiagnostics: true, and asummaryforadd_ltv).file— the PDF is written to a sandboxed directory configured viaPDFNATIVE_MCP_OUTPUT_DIR. File output is disabled unless this variable is set; absolute paths, path traversal, non-.pdfextensions, 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 embeddedresourceblock 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 }(+ltvLevelwithltv: true);inspect_pdfkeepsdocTimestampCount/trapped/checksPassedwhen present.fields: ['a', 'b.c']— projects the structured result to named dot-paths; composes afterverbosity. 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.
24 scripts (25
langcodes incl.emojiandmath) with built-in BiDi reordering, Arabic positional shaping, Thai/Devanagari/Bengali/Tamil OpenType shaping.Tree-shakeable ESM build.
Related MCP server: document-intelligence-mcp
🚀 Installation
# Run directly with npx (recommended for MCP clients)
npx -y pdfnative-mcp
# Or install globally
npm install -g pdfnative-mcp
pdfnative-mcpRequirements: 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:
Ontheia — a self-hosted, open-source AI agent platform (privacy-first). Reported as working out of the box in issue #41 and listed on Ontheia's compatible MCP servers page.
🔌 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:
Stateless serving —
server/discoverreplaces the session handshake; every result carriesresultTypeand the_metaserverInfoenvelope. Over HTTP, 2026-07-28 clients sendMcp-Method/Mcp-Nameheaders with eachPOST /mcp.Cache hints —
tools/listandprompts/listarepublicwith a 24 httlMs,server/discoverispublicfor 1 h, andresources/list/resources/templates/list/resources/readareprivatewithttlMs: 0(generated PDFs are per-host user data).Resource errors — an unknown resource URI is reported as JSON-RPC
-32602(Invalid params), as the 2026-07-28 specification requires.Automatic legacy fallback — a client that opens with
initialize(2025-11-25, 2025-06-18 or 2025-03-26) is served through the SDK's legacy path on both stdio and HTTP. Nothing changes for existing hosts.HTTP —
GET/DELETE /mcpanswer 405 (no SSE resumability; the server is stateless). The loopback bind and theHost/Originguard are unchanged, and theOriginport must now equal the server port (the SDK check alone is port-agnostic);PDFNATIVE_MCP_HTTP_TOKENadds an opt-in bearer-token gate (401+WWW-Authenticatewithout it). JSON-RPC batch arrays (2025-03-26) are accepted over HTTP. Keep-alive connections no longer accumulate socket listeners.stdio — as in every SDK release to date, a request sent before
initializeis dropped without a reply and JSON-RPC batch arrays are not accepted on stdio (unchanged from 1.5.0; no major host batches).Protocol errors —
tools/callwith an unknown tool name is a JSON-RPC error (-32602,[UNKNOWN_TOOL] Unknown tool: …) rather than anisErrorresult, as the specification classifies it;isError: trueis reserved for execution failures.Output schemas — every
structuredContentvalidates against the tool'soutputSchema(a 2026-07-28 MUST), includingverbosity: 'summary'andfieldsprojections: the seven read tools declare projectable schemas (all properties optional,additionalProperties: falsekept). Input schemas carry no$schemakeyword by policy (MCP ≥ 2025-11-25 defaults to JSON Schema 2020-12; some hosts forwardinputSchemato function-calling APIs that reject unknown keywords).serverInfocarrieswebsiteUrl; the resource template ispdfnative://output/{+path}.
The tools/call payload (content, structuredContent, isError) is identical between the 2026-07-28 path and the legacy path; tests/http-modern.test.ts asserts it, and tests/schema-conformance.test.ts validates structuredContent with the SDK's JSON Schema 2020-12 validator.
Client | Transport | Protocol negotiated |
Claude Desktop, Cursor, Continue, Zed, Windsurf, Cline | stdio | legacy |
ChatGPT and other Streamable HTTP hosts | HTTP | legacy stateless streamable HTTP — unchanged |
MCP 2026-07-28 clients (SDK v2 | stdio / HTTP |
|
Ontheia | stdio | legacy |
Environment variables
Variable | Purpose |
| Absolute path to the sandbox directory. Required to enable |
| Absolute path to enable the persistent SHA-256-keyed result cache (1 h TTL, 256 MiB LRU; key namespaced by tool API + package version). When unset, the cache is disabled. Never caches |
| When set to a valid port (1–65535), starts an HTTP server on |
| (v1.6.0, secret) Opt-in bearer token for the HTTP transport (≥ 16 characters, no whitespace — a weaker value aborts startup). When set, every |
| (v1.6.0) Overrides the engine's 100 MiB per-stream decompression cap (zip-bomb guard): a positive integer number of bytes ≥ 1024, read once at startup — an invalid value refuses to start. Lower it on a shared host, raise it for trusted archives of large scans. A capped attachment stream fails |
| (v1.6.0) Absolute |
| (v1.6.0, secret) Optional |
| (v1.6.0) |
| (v1.6.0) Comma-separated allow-list ( |
| (v1.6.0) Per-request timeout for TSA / OCSP / CRL calls, 1000–120000 ms (default 10000). |
🛠 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"
}The 13 block kinds: heading, paragraph, list, table, image, link, toc, barcode, svg, formField, chart, pageBreak, spacer. A composite report:
{
"title": "Quarterly report",
"blocks": [
{ "type": "toc" },
{ "type": "heading", "text": "Sales", "level": 1 },
{ "type": "table", "headers": ["Region", "Revenue"], "rows": [["EMEA", "1.2 M"], ["APAC", "0.9 M"]], "zebra": true },
{ "type": "image", "imageBase64": "<base64 JPEG>", "mimeType": "image/jpeg", "width": 300, "alt": "Revenue chart" },
{ "type": "svg", "data": "M10 10 H 90 V 90 H 10 Z", "viewBox": [0, 0, 100, 100], "fill": "#0a7e8c" },
{ "type": "barcode", "format": "qr", "data": "https://example.com/q1", "align": "center" },
{ "type": "link", "text": "Full dataset", "url": "https://example.com/data" },
{ "type": "formField", "fieldType": "text", "name": "reviewer", "label": "Reviewed by" }
],
"outline": "auto",
"pageSize": "Letter",
"headerTemplate": { "right": "{title} — page {page}/{pages}" },
"embedFonts": true
}Block rules: table, barcode, formField and chart take the same body as add_table / add_barcode / add_form / add_chart; link URLs must be http:, https: or mailto:; image blocks are capped at 12 M base64 characters each and 24 MiB decoded per call (PNG: 8-bit greyscale/RGB, non-interlaced, no alpha, no palette — otherwise VALIDATION_ERROR with a remedy); svg supports <path>, <rect>, <circle>, <ellipse>, <line>, <polyline>, <polygon>, <text>/<tspan> and silently ignores transform, <g>, <use>, <image>, gradients, opacity and CSS (no external reference is ever fetched); toc is built from the heading blocks and pairs with outline: 'auto'; formField under pdfA reports PDFA_UNEMBEDDED_FORM_FONT (strict: true fails); barcode has no alt. Use inspect_layout with the same inputs to preview the pagination before rendering.
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 (25): ar, he, th, ja, zh, ko, el, hi, bn, ta, ru, ka, hy, tr, pl, vi, latin, te, si, bo, km, my, am, emoji, math. Fonts are always embedded (no embedFonts input); pin creationDate for byte-identical output.
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 # ECDSAUse
prepare_signature_placeholderonly when you need to customize the placeholder (e.g. largerplaceholderBytesfor >4096-bit RSA keys,subFilter: 'ETSI.CAdES.detached',reserveTimestamp: true). Otherwise callsign_pdfdirectly.
PAdES ladder (v1.6.0). sign_pdf with profile: "pades" produces a B-B signature; add timestamp: true for B-T (needs PDFNATIVE_MCP_TSA_URL), then add_ltv (B-LT) and timestamp_pdf (B-LTA):
// 1. sign_pdf { ..., "profile": "pades", "timestamp": true, "certChainDerBase64": ["<intermediate DER>"] }
// 2. add_ltv { "pdfBase64": "<signed>", "mode": "online" } // or "offline" + certificatesDerBase64 / ocspResponsesDerBase64 / crlsDerBase64
// 3. timestamp_pdf { "pdfBase64": "<ltv>" } // re-run before the TSA certificate expires
// 4. verify_pdf { "pdfBase64": "<final>", "ltv": true } // -> ltvLevel: "B-LTA"Signer metadata (signerName, reason, location, contactInfo) is baked into the placeholder; fieldName selects one of several unsigned placeholders (PLACEHOLDER_AMBIGUOUS otherwise) and allowMultiple: true adds a further signature. See docs/guides/LTV.md.
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 },
{ "fieldType": "listbox", "name": "skills", "label": "Skills", "options": ["TypeScript", "PDF", "MCP"] },
{ "fieldType": "textarea", "name": "notes", "label": "Notes", "placeholder": "Anything we should know?" }
],
"outputMode": "base64"
}Field types: text, textarea (multi-line, /Ff 4096), checkbox, radio, dropdown, listbox; placeholder shows hint text while a field is empty. Add encrypt to produce a password-protected form that keeps its AcroForm. Under a PDF/A claim the widget appearance font is not embedded (PDFA_UNEMBEDDED_FORM_FONT).
embed_image
{
"title": "Product Photo",
"imageBase64": "<base64-encoded JPEG bytes>",
"mimeType": "image/jpeg",
"caption": "Front view of Model X",
"width": 400,
"align": "center",
"alt": "Front view of the Model X chassis",
"outputMode": "base64"
}Note: the engine's PNG decoder accepts 8-bit, non-interlaced greyscale / RGB images only. Alpha-channel (colour type 4 / 6), palette (type 3), 16-bit and interlaced PNGs are rejected at the boundary with
VALIDATION_ERRORand a remedy (flatten or re-export) — the same rule applies toimageblocks and image watermarks.embed_image.imageBase64keeps its 1.5.0 contract with no length bound; the 12 M-character cap applies to inlineimageblocks and watermark images only.
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', 'dss', 'docTimestamp', 'trapped', 'annotations' (the last four since v1.6.0). checksPassed is the AND of all requested checks. signatures: true adds a per-field inventory (subFilter, isDocTimestamp, isPlaceholder, byteRange, vriKey); annotations: true adds annotations[] (every /Annots entry: 0-based page, subtype, rect, and when present contents truncated to 200 chars, title, color, quadPoints, link url) plus annotationCount; dss, docTimestampCount and trapped appear only when present; with pages: true each perPage entry also carries trimBox / bleedBox / artBox / cropBox / userUnit when set.
inspect_layout
Read-only pagination dry run — the same blocks as generate_basic_pdf plus every input that moves a block (title, footerText, pdfA, normalize, embedFonts, pageSize, margins, headerTemplate, footerTemplate). No PDF is produced; pass exactly what you will give generate_basic_pdf and totalPages matches.
{ "title": "Memo", "blocks": [{ "type": "paragraph", "text": "Short note." }], "pageSize": "Letter", "verbosity": "summary", "fields": ["totalPages"] }The full result carries pageWidth, pageHeight, margins, totalPages and pages[].blocks[] (type, page, x, top, width, height in points, rounded to two decimals). Known engine gap: a toc block is measured as 0 pt here, so a document with a printed contents may paginate one page later than previewed.
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. Page indices are 0-based. Encrypted sources are rejected (ENCRYPTED_SOURCE) — run decrypt_pdf first (drops signatures / AcroForm), annotate, then encrypt_pdf again.
draft_governance_issue
Draft a governance-compliant GitHub issue locally for a human to review and submit. The server never contacts GitHub (its only possible egress is the operator-configured TSA / OCSP / CRL endpoints — see Network & egress); 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": "add_table with caption + repeatHeader over 2 pages (examples/bordered-table.json, then inspect_pdf)", "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 (or a loopback-only HTTP endpoint). It does not perform any I/O outside the configured sandbox.
File writes are gated by
PDFNATIVE_MCP_OUTPUT_DIR. When unset, thefileoutput mode is rejected with aSecurityError.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 — unknown or misspelt keys (top-level or nested) are rejected with
VALIDATION_ERROR, and base64 / DER payloads are sanity-checked (data:prefix tolerated, PEM or double-encoded input rejected with the remedy) before any parser runs.HTTP transport (
PDFNATIVE_MCP_PORT) binds loopback only; it has no authentication unlessPDFNATIVE_MCP_HTTP_TOKENis set (then401without a valid bearer token).
Network & egress
The server makes no outbound network call by default. The only egress it can ever perform goes to the RFC 3161 / OCSP / CRL endpoints the operator configured in the environment for PAdES long-term validation (PDFNATIVE_MCP_TSA_URL, PDFNATIVE_MCP_REVOCATION, PDFNATIVE_MCP_NETWORK_ALLOWED_HOSTS) — never to a URL supplied by a tool argument, never to GitHub, never for telemetry. Without that configuration sign_pdf timestamp: true, timestamp_pdf and add_ltv mode: 'online' fail fast with TSA_NOT_CONFIGURED / REVOCATION_NOT_CONFIGURED before touching the document; add_ltv mode: 'offline' embeds caller-supplied material with zero network access.
OCSP / CRL URLs come from the AIA / CRL-distribution-point extensions of untrusted certificates inside the PDF, so every fetch passes an SSRF guard:
host must match the operator allow-list (
host,host:portor*.suffix; bare wildcards are rejected). Entries are hostnames, not URLs: ahost:portentry only matches URLs carrying an explicit port (the URL parser drops default:80/:443— list the bare host for those); wildcard entries cannot carry a port; IDN hostnames must be listed in punycode (xn--…); IPv6 literals in brackets ([2001:db8::1]);http:/https:only, no embedded credentials, redirects are never followed;loopback, link-local, private, unique-local, CGNAT, unspecified and multicast address literals (including decimal / octal / hex spellings and IPv4-mapped IPv6) are rejected unless that literal is allow-listed verbatim. The guard checks literals only — a listed hostname that resolves to an internal address (DNS rebinding) is not detected, since there is no resolver without adding a dependency; allow-list only hosts you control;
per-request timeout (
PDFNATIVE_MCP_NETWORK_TIMEOUT_MS) and response caps (256 KiB TSA, 1 MiB OCSP, 16 MiB CRL) enforced while streaming, so an oversized response is cut off rather than buffered;OCSP responses and CRLs returned by responders are parse-validated before
add_ltvembeds them;the TSA URL is operator-trusted (scheme + credential checks only); the
PDFNATIVE_MCP_TSA_AUTHsecret is never logged or echoed in error messages.
Providers are built per call and passed through pdfnative's per-call options — the process-wide provider setters are never used, so concurrent requests share nothing. The server/discover instructions report the current egress policy (endpoint kinds only, never secrets).
See SECURITY.md for the responsible disclosure process and docs/guides/LTV.md for the operator setup.
🧪 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
npm run validate:pdfa # advisory: veraPDF over the 26-file PDF/A corpus (24 validated; skips when veraPDF is absent; VERAPDF_REQUIRED=1 fails closed)
node scripts/tool-shape.mjs --write # only after a deliberate tools/list schema change (catalogue parity fixture)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.mdCHANGELOG.mdmirrors each release bullet listGitHub Release body is copied from
release-notes/vX.Y.Z.mdnpm 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 # entrypoint: stdio (default) or Streamable HTTP (PDFNATIVE_MCP_PORT)
├── http.ts # Node http <-> Web Request/Response bridge + Host/Origin loopback guard
├── auth.ts # opt-in HTTP bearer token (PDFNATIVE_MCP_HTTP_TOKEN)
├── base64.ts # base64 / DER boundary decoding with agent-facing diagnostics
├── index.ts # public library exports
├── server.ts # Server factory, tool registry, cache hints, SERVER_INSTRUCTIONS
├── network.ts # operator-configured TSA / OCSP / CRL egress + SSRF guard
├── print.ts # print-production schema (boxes, bleed, marks, userUnit, outputIntent, metadata, creationDate)
├── diagnostics.ts # PDF/A diagnostics sink, strict / includeDiagnostics / embedFonts
├── chart.ts # charts v2 schema + ChartBlock mapper
├── blocks.ts # the 7 extended document blocks (table, image, link, toc, barcode, svg, formField)
├── layout.ts # pageSize / margins / header & footer templates / compress / debug / encrypt (PdfLayoutOptions)
├── table.ts, barcode.ts, form.ts, image.ts # bodies shared by a dedicated tool and its inline block
├── watermark.ts # text and/or image watermark + position, PDF/A-1b transparency guard
├── encryption.ts # password + encrypt schema (Standard Security Handler), decrypt error mapping
├── inflate-cap.ts # PDFNATIVE_MCP_MAX_INFLATE_BYTES (engine decompression cap) + PDF_PARSE_FAILED mapping
├── 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 (+ print-dialog defaults)
├── pagetree.ts # page-tree error mapping (merge/split/extract)
├── crypto-provider.ts # node:crypto signing provider for DER keys (SHA-256/384/512); verification stays pure JS
├── projection.ts # verbosity / fields projection for the seven read tools
├── errors.ts # ToolError, SecurityError, GovernanceError
└── tools/
├── generate-basic-pdf.ts
├── inspect-layout.ts
├── add-barcode.ts
├── sign-pdf.ts
├── add-ltv.ts
├── timestamp-pdf.ts
├── update-metadata.ts
├── add-international-text.ts
├── add-table.ts
├── add-form.ts
├── read-form-fields.ts
├── fill-form.ts
├── add-chart.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
├── annotate-pdf.ts
├── encrypt-pdf.ts
├── decrypt-pdf.ts
├── draft-governance-issue.ts
└── prepare-signature-placeholder.ts
scripts/
├── verify-issue.mjs # governance draft checker (npm run verify:issue)
├── validate-pdfa.mjs # veraPDF run (npm run validate:pdfa; PASS/FAIL/XFAIL/XPASS/INFRA/SKIP)
├── generate-pdfa-corpus.mjs # builds the 26-file PDF/A corpus (24 validated incl. 3 negative canaries, 2 page-tree outputs)
└── tool-shape.mjs # structural tools/list fingerprint (--write refreshes tests/_fixtures/tool-shape.json)
.github/workflows/ci.yml # Linux (Node 22 / 24) + Windows quality gate
.github/workflows/verapdf.yml # non-blocking veraPDF CI job (SHA-256-pinned installer, VERAPDF_REQUIRED=1)
tests/ # vitest suites (one per tool / module; document-blocks, layout-options, inspect-layout,
# watermark, inflate-cap, catalogue-parity + catalogue-superset vs the 1.5.0 fixture)🗺 Roadmap
v1.6.0 is shipped (full engine coverage — 13 block kinds, layout options, inspect_layout — PAdES LTV ladder, print production, charts v2, update_metadata, MCP 2026-07-28). The full plan — released milestones, in-progress work, and long-term direction — lives in ROADMAP.md.
Still deferred:
redact_pdf— pdfnative has no content-removal API; an overlay-only "redaction" would create false security.Native ECDSA verification — pdfnative does not export
ecdsaVerifyHash;verify_pdfkeeps its pure-JS path for P-256.HTTP page streaming — MCP 2026-07-28 still has no partial
structuredContent, so large results stay single-shot.
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.
Available Tools
28 toolsadd_attachmentAdd embedded file attachment (PDF/A-3, Factur-X)AIdempotent
PDF/A-3b document with embedded files — the tool for Factur-X / ZUGFeRD e-invoices (one XML attachment, relationship 'Source', mimeType application/xml) or any PDF carrying machine-readable side-files (≤ 8 MiB each). Body via blocks (same schema as generate_basic_pdf). Pair with embedFonts:true for a valid PDF/A-3 claim (strict:true fails otherwise). Read them back with extract_attachments. Print, metadata and creationDate options as on every document tool.
| Name | Required | Description | Default |
|---|---|---|---|
| debug | No | Draw margin / block / cell guide rectangles (unmarked content — not for PDF/UA output). Geometry unchanged. Default false. | |
| No | Print production (ISO 32000-1 §14.11): page boxes, `bleed` shorthand (TrimBox = MediaBox inset), crop/registration marks outside the TrimBox, /UserUnit for large formats (PDF 1.7; not under pdfa1b). See docs/guides/PRINT.md. | ||
| title | Yes | Document title (also written to the /Info dictionary). | |
| blocks | No | Optional human-readable document body (same block schema as generate_basic_pdf). When omitted, a minimal cover paragraph is emitted so the PDF is not empty. | |
| strict | No | Fail with PDF_A_COMPLIANCE_VIOLATION instead of producing a non-conformant PDF/A file (e.g. PDFA_NO_FONT_ENTRIES without embedFonts). Pair with embedFonts=true. | |
| margins | No | Margins in points, all four required (0–200). Default 45 / 36 / 35 / 36. | |
| compress | No | FlateDecode the streams (smaller file, different bytes; PDF/A unaffected, XMP stays plain). Default false. | |
| metadata | No | /Info (+ XMP under PDF/A): author, subject, keywords, /Trapped. | |
| pageSize | No | Portrait page preset (points): A4 595.28×841.89 (default), Letter 612×792, Legal 612×1008, A3 841.89×1190.55, Tabloid 792×1224. print.* boxes must fit it. | |
| embedFonts | No | Embed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A claim (ISO 19005 §6.2.11.4.1) and for strict=true; adds ~0.3 MiB. | |
| footerText | No | Optional footer text rendered on every page. | |
| outputMode | No | 'base64' (default) returns the PDF inline; 'file' writes it inside the PDFNATIVE_MCP_OUTPUT_DIR sandbox (SECURITY_VIOLATION when the sandbox is not configured). | base64 |
| outputPath | No | Required when outputMode='file'. Relative path inside the sandbox; must end with .pdf (no absolute paths, no '..'). | |
| attachments | Yes | One or more files to embed. Auto-enables PDF/A-3 (ISO 19005-3). Factur-X invoices use a single attachment with relationship=Source and mimeType=application/xml. | |
| creationDate | No | ISO-8601 instant for /CreationDate (+ XMP). Pin it for byte-identical output across calls (same host TZ); omitted = wall clock, so every call differs. | |
| outputIntent | No | Custom PDF/A OutputIntent: an RGB ICC profile + condition strings replacing the built-in sRGB intent (CMYK rejected). | |
| footerTemplate | No | Running footer on every page. Replaces the default footer: footerText is then ignored and page numbers appear only via {page}/{pages}. | |
| headerTemplate | No | Running header on every page (left / center / right zones); reserves 15 pt. | |
| includeDiagnostics | No | Return the PDF/A diagnostics raised while building as `diagnostics[]` (possibly empty). |
Output Schema
| Name | Required | Description |
|---|---|---|
| mode | Yes | |
| summary | No | Tool-specific summary, when produced. |
| filePath | No | Sandboxed absolute path (file mode). |
| sizeBytes | Yes | |
| diagnostics | No | PDF/A diagnostics (when includeDiagnostics=true). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover safety (idempotent=true, destructive=false, readOnly=false), so the bar is lower. The description adds genuinely useful behavioral detail beyond the annotations: PDF/A-3 auto-enable via attachment, the strict:true cold fail if embedFonts is not paired, the ≤8 MiB per-file cap, and a read-back pointer to extract_attachments. No contradiction with annotations; this is meaningful supplementary behavior disclosure, though it stops short of explaining exact failure or concurrency behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Five sentences, mostly one clause each, front-loaded with the tool's core identity. Every sentence earns its place: the Factur-X use case, the size constraint, the blocks reference, the embedFonts/strict pairing, the read-back pointer, and the note that print/metadata options mirror other document tools. No filler and no restatement of schema details.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity — 19 parameters, nested objects, an output schema, 2 enums — the description plus the fully-described schema leave no critical gap for an agent to call this correctly. The description covers the core semantic decisions (when to use it, how to compose the body, how to get a valid PDF/A claim, where to find the result). Everything else is accurately land cheaply documented in the rich schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 100% schema description coverage, the baseline is 3, but the description adds inter-parameter meaning that the schema prose lacks: it explains the coupling between embedFonts and strict (strict:true fails otherwise), delegating blocks to generate_basic_pdf's schema (saving the agent from guessing the block shape), and it restates the Factur-X attachment convention in the narrative. This is more than the schema alone provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description leads with a specific verb and resource: producing a PDF/A-3 document with embedded file attachments, and pins the canonical use case (Factur-X/ZUGFeRD e-invoices) plus the general case (any machine-readable side-files). It names exact characteristics (one XML attachment, relationship 'Source', mimeType application/xml) that clearly differentiate this tool from the 26 siblings, especially from generate_basic_pdf and extract_attachments. This goes well beyond a restatement of the name or title.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives concrete when-to-use context: 'the tool for Factur-X / ZUGFeRD e-invoices' or any PDF with side-files, and routes the agent to read results back with extract_attachments. It also signals where to find the body schema (generate_basic_pdf). The only gap is the absence of an explicit when-NOT-to-use statement with an alternative (e.g., use generate_basic_pdf when no attachments are needed), which keeps this just shy of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
add_barcodeAdd barcode / QR codeAIdempotent
Single-page PDF with a barcode: qr (URLs, vCards, UTF-8 ≤ 4296 chars; ecLevel 'H' for print, 'M' default), code128 (ASCII SKUs), ean13 (12–13 digits, checksum auto), datamatrix (dense industrial marks), pdf417 (ID cards, boarding passes). data is the raw payload — never pre-encode. Typical: { format:'qr', data:'https://example.com', caption:'Scan me' }. PDF/A, print, metadata and creationDate options as on every document tool.
| Name | Required | Description | Default |
|---|---|---|---|
| data | Yes | Raw payload to encode — do NOT URL-encode. For QR/URL pass e.g. "https://example.com" verbatim. EAN-13 must be 12 or 13 digits (13th is auto-computed). Code 128 accepts ASCII alphanumerics. | |
| pdfA | No | PDF/A level: pdfa1b (simple text+images), pdfa2b/pdfa2u (richer; 2u = Unicode mapping), pdfa3b (attachments / Factur-X). Pair with embedFonts=true for a valid claim. Exclusive with encryption. See docs/guides/PDFA.md. | |
| debug | No | Draw margin / block / cell guide rectangles (unmarked content — not for PDF/UA output). Geometry unchanged. Default false. | |
| No | Print production (ISO 32000-1 §14.11): page boxes, `bleed` shorthand (TrimBox = MediaBox inset), crop/registration marks outside the TrimBox, /UserUnit for large formats (PDF 1.7; not under pdfa1b). See docs/guides/PRINT.md. | ||
| title | No | PDF document title (also rendered as page heading). | Barcode |
| width | No | Barcode width in PDF points. | |
| format | Yes | Barcode symbology to render. | |
| height | No | Barcode height in PDF points (ignored for square symbologies like QR/Data Matrix). | |
| strict | No | Fail with PDF_A_COMPLIANCE_VIOLATION instead of producing a non-conformant PDF/A file (e.g. PDFA_NO_FONT_ENTRIES without embedFonts). Pair with embedFonts=true. | |
| caption | No | Optional caption rendered above the barcode. | |
| ecLevel | No | QR ONLY. Error correction level (L=7%, M=15%, Q=25%, H=30%). Ignored for code128/ean13/datamatrix/pdf417. Use H for printed media that may get smudged or partially covered (e.g. logo overlay). | M |
| encrypt | No | Encrypt at build time (AES-128 default / AES-256) and KEEP the AcroForm — unlike encrypt_pdf, which rebuilds the page tree. Exclusive with pdfA. Randomised output, never cached. | |
| margins | No | Margins in points, all four required (0–200). Default 45 / 36 / 35 / 36. | |
| compress | No | FlateDecode the streams (smaller file, different bytes; PDF/A unaffected, XMP stays plain). Default false. | |
| metadata | No | /Info (+ XMP under PDF/A): author, subject, keywords, /Trapped. | |
| pageSize | No | Portrait page preset (points): A4 595.28×841.89 (default), Letter 612×792, Legal 612×1008, A3 841.89×1190.55, Tabloid 792×1224. print.* boxes must fit it. | |
| embedFonts | No | Embed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A claim (ISO 19005 §6.2.11.4.1) and for strict=true; adds ~0.3 MiB. | |
| outputMode | No | 'base64' (default) returns the PDF inline; 'file' writes it inside the PDFNATIVE_MCP_OUTPUT_DIR sandbox (SECURITY_VIOLATION when the sandbox is not configured). | base64 |
| outputPath | No | Required when outputMode='file'. Relative path inside the sandbox; must end with .pdf (no absolute paths, no '..'). | |
| creationDate | No | ISO-8601 instant for /CreationDate (+ XMP). Pin it for byte-identical output across calls (same host TZ); omitted = wall clock, so every call differs. | |
| outputIntent | No | Custom PDF/A OutputIntent: an RGB ICC profile + condition strings replacing the built-in sRGB intent (CMYK rejected). | |
| footerTemplate | No | Running footer on every page. Replaces the default footer: footerText is then ignored and page numbers appear only via {page}/{pages}. | |
| headerTemplate | No | Running header on every page (left / center / right zones); reserves 15 pt. | |
| includeDiagnostics | No | Return the PDF/A diagnostics raised while building as `diagnostics[]` (possibly empty). |
Output Schema
| Name | Required | Description |
|---|---|---|
| mode | Yes | |
| summary | No | Tool-specific summary, when produced. |
| filePath | No | Sandboxed absolute path (file mode). |
| sizeBytes | Yes | |
| diagnostics | No | PDF/A diagnostics (when includeDiagnostics=true). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds useful behavioral context beyond annotations: the result is a single-page PDF, data must be raw ('never pre-encode'), and ecLevel should be 'H' for print. It also flags 'PDF/A, print, metadata and creationDate general options'. It does not contradict the annotations, and annotations already covers failed/crucy/safety characteristics.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two dense sentences plus an example: no filler, useful constraints are front-loaded, and the common typic invocation is given before wiring into extra options. Every sentence carries decision-relevant behavior.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 24-parameter tool, the description gives a strong entry point and relies on the very rich input schema for the long tail (encryption, outputMode, PDF/A, footers, etc.). That is acceptable given the schema coverage, but the description could be a bit more explicit about output modes and the full PDF/A family of common options.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents every parameter. The description still adds value by mapping formats to practical uses, highlighting 'raw payload, never pre-encode', and reading EAN-13 checksum auto-computation. This eases whether to the Correct parameter choices without repeating every schema field.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies what the tool does: it creates a single-page PDF containing a barcode, and it maps each supported symbology to a realistic content type. It is specific about the resource and output shape, though it does not explicitly compare against sibling add_* tools like add_image or add_table.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Includes per-format guidance, e.g. QR for URLs/vCards, code128 for ASCII SKUs, pdf417 for ID cards, plus a concrete 'typically' example. It says when to use each barcode format but does not mention when not to use the tool or reroute to a sibling tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
add_chartAdd native vector chartAIdempotent
Single-page PDF with a native vector chart (pure path operators, no raster): bar, barH, stackedBar, stackedBarH, line (markers), area, scatter, pie, donut. Multi-series, legends, 'nice' ticks, gridlines, negatives; per-series xValues with xAxis.type 'linear' | 'time' (ISO-8601), secondary right axis (axis2 + yAxis:'right'), axis.scale 'log', dataLabels, labelStride / labelRotation. Pie/donut take exactly one series. Colours are hex ('#3366cc'). Tagged /Figure + /Alt (auto when altText is omitted). Engine cross-field rules surface as CHART_ERROR with the remedy. Inside a longer document use a 'chart' block in generate_basic_pdf. PDF/A (pdfA + embedFonts:true), print, metadata and creationDate as on every document tool.
| Name | Required | Description | Default |
|---|---|---|---|
| axis | No | Value-axis options (bar/line only). | |
| pdfA | No | PDF/A level: pdfa1b (simple text+images), pdfa2b/pdfa2u (richer; 2u = Unicode mapping), pdfa3b (attachments / Factur-X). Pair with embedFonts=true for a valid claim. Exclusive with encryption. See docs/guides/PDFA.md. | |
| align | No | Horizontal alignment within the content width. Default 'left'. | |
| axis2 | No | Secondary RIGHT value axis (drawn only when a series sets yAxis:'right'). | |
| debug | No | Draw margin / block / cell guide rectangles (unmarked content — not for PDF/UA output). Geometry unchanged. Default false. | |
| intro | No | Optional introductory paragraph rendered above the chart. The chart `title` (if any) is also used as the PDF metadata title. | |
| No | Print production (ISO 32000-1 §14.11): page boxes, `bleed` shorthand (TrimBox = MediaBox inset), crop/registration marks outside the TrimBox, /UserUnit for large formats (PDF 1.7; not under pdfa1b). See docs/guides/PRINT.md. | ||
| title | No | Chart title rendered above the plot. | |
| width | No | Plot width in points (clamped to content width). Default 460. | |
| xAxis | No | Horizontal axis. 'category' (default) positions points by index; 'linear' / 'time' position them by series xValues (line/area/scatter only). Time ticks are UTC-deterministic. | |
| colors | No | Palette override (per-series for bar/line, per-slice for pie/donut). | |
| height | No | Plot-area height in points. Default 240. | |
| legend | No | Legend placement. Defaults to 'bottom' for multi-series/pie, else 'none'. | |
| series | Yes | Data series. Pie/donut charts use exactly one series (each value becomes a slice). | |
| strict | No | Fail with PDF_A_COMPLIANCE_VIOLATION instead of producing a non-conformant PDF/A file (e.g. PDFA_NO_FONT_ENTRIES without embedFonts). Pair with embedFonts=true. | |
| altText | No | Alt text for the tagged-PDF /Figure /Alt. Auto-generated when omitted. | |
| encrypt | No | Encrypt at build time (AES-128 default / AES-256) and KEEP the AcroForm — unlike encrypt_pdf, which rebuilds the page tree. Exclusive with pdfA. Randomised output, never cached. | |
| margins | No | Margins in points, all four required (0–200). Default 45 / 36 / 35 / 36. | |
| markers | No | Draw point markers on line series. Default false. | |
| compress | No | FlateDecode the streams (smaller file, different bytes; PDF/A unaffected, XMP stays plain). Default false. | |
| metadata | No | /Info (+ XMP under PDF/A): author, subject, keywords, /Trapped. | |
| pageSize | No | Portrait page preset (points): A4 595.28×841.89 (default), Letter 612×792, Legal 612×1008, A3 841.89×1190.55, Tabloid 792×1224. print.* boxes must fit it. | |
| chartType | Yes | Chart kind. 'pie'/'donut' use exactly one series; 'bar'/'barH'/'stackedBar'/'stackedBarH'/'line'/'area'/'scatter' support multiple series. 'scatter' requires xValues on every series and a positional xAxis.type ('linear' or 'time'). | |
| categories | No | Category / slice labels (x-axis). Defaults to 1-based indices when omitted. | |
| dataLabels | No | Per-point value labels: true for defaults, or an object to format them. | |
| embedFonts | No | Embed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A claim (ISO 19005 §6.2.11.4.1) and for strict=true; adds ~0.3 MiB. | |
| outputMode | No | Either 'base64' (returns the PDF inline) or 'file' (writes into the PDFNATIVE_MCP_OUTPUT_DIR sandbox). | base64 |
| outputPath | No | Required when outputMode='file'. Relative path inside the sandbox; must end with .pdf. | |
| labelStride | No | Draw every Nth category label. Default: automatic (measured non-overlap); 1 draws every label. | |
| creationDate | No | ISO-8601 instant for /CreationDate (+ XMP). Pin it for byte-identical output across calls (same host TZ); omitted = wall clock, so every call differs. | |
| outputIntent | No | Custom PDF/A OutputIntent: an RGB ICC profile + condition strings replacing the built-in sRGB intent (CMYK rejected). | |
| labelRotation | No | Rotate category labels counter-clockwise by this many degrees (disables the automatic stride). | |
| footerTemplate | No | Running footer on every page. Replaces the default footer: footerText is then ignored and page numbers appear only via {page}/{pages}. | |
| headerTemplate | No | Running header on every page (left / center / right zones); reserves 15 pt. | |
| includeDiagnostics | No | Return the PDF/A diagnostics raised while building as `diagnostics[]` (possibly empty). |
Output Schema
| Name | Required | Description |
|---|---|---|
| mode | Yes | |
| summary | No | Tool-specific summary, when produced. |
| filePath | No | Sandboxed absolute path (file mode). |
| sizeBytes | Yes | |
| diagnostics | No | PDF/A diagnostics (when includeDiagnostics=true). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare idempotentHint=true and destructiveHint=false, so safety is covered. The description adds valuable behavioral context beyond that: output is a single-page PDF with pure vector paths, pie/donut require exactly one series, errors surface as CHART_ERROR, and PDF/A compliance requires embedFonts. This is strong but not exhaustive; e.g., it doesn't mention default random output unless creationDate is pinned, though the schema does.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single compact paragraph that packs a lot of feature detail without fluff. It front-loads the core value proposition (native vector chart) and then lists constraints and notable behaviors. It earns 4, not 5, because the dense wall of text could be structured more clearly for an agent scanning for supported chart types or key restrictions.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 35 parameters, the description is nearly complete: it covers chart types, vector guarantee, multi-series, axes, pie/donut constraint, error code, routing to generate_basic_pdf, and PDF/A pairing. The output schema exists, so describing return values isn't necessary. It slightly lacks a quick statement about expected output format (base64 vs file) or the default one-page document, but the schema covers the outputMode parameter, so this is a minor gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description does add some high-level semantics like 'per-series xValues with xAxis.type linear|time' and 'Pie/donut take exactly one series', but these are also repeated in the schema. No significant meaning is added beyond what the schema already documents, so 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Add') and resource ('native vector chart') and enumerates the supported chart types and features. It is clearly distinct from siblings like add_table or embed_image, but it does not explicitly name a sibling tool it is not, so it stops short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives a clear routing rule: 'Inside a longer document use a "chart" block in generate_basic_pdf.' This tells the agent when not to use add_chart. However, it doesn't explicitly state when to prefer this tool over other chart-capable paths or give a fuller when-to-use/when-not-to-use comparison, so it doesn't reach 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
add_formAdd interactive formAIdempotent
New PDF with an interactive AcroForm: text fields, text areas, checkboxes, radio buttons, dropdowns (data capture, surveys, fillable templates). To fill or flatten an EXISTING form use read_form_fields + fill_form. PDF/A, print, metadata and creationDate options as on every document tool.
| Name | Required | Description | Default |
|---|---|---|---|
| pdfA | No | PDF/A level: pdfa1b (simple text+images), pdfa2b/pdfa2u (richer; 2u = Unicode mapping), pdfa3b (attachments / Factur-X). Pair with embedFonts=true for a valid claim. Exclusive with encryption. See docs/guides/PDFA.md. | |
| debug | No | Draw margin / block / cell guide rectangles (unmarked content — not for PDF/UA output). Geometry unchanged. Default false. | |
| No | Print production (ISO 32000-1 §14.11): page boxes, `bleed` shorthand (TrimBox = MediaBox inset), crop/registration marks outside the TrimBox, /UserUnit for large formats (PDF 1.7; not under pdfa1b). See docs/guides/PRINT.md. | ||
| title | Yes | Form title rendered at the top of the document. | |
| fields | Yes | Ordered list of form field definitions. | |
| strict | No | Fail with PDF_A_COMPLIANCE_VIOLATION instead of producing a non-conformant PDF/A file (e.g. PDFA_NO_FONT_ENTRIES without embedFonts). Pair with embedFonts=true. | |
| encrypt | No | Encrypt at build time (AES-128 default / AES-256) and KEEP the AcroForm — unlike encrypt_pdf, which rebuilds the page tree. Exclusive with pdfA. Randomised output, never cached. | |
| margins | No | Margins in points, all four required (0–200). Default 45 / 36 / 35 / 36. | |
| compress | No | FlateDecode the streams (smaller file, different bytes; PDF/A unaffected, XMP stays plain). Default false. | |
| metadata | No | /Info (+ XMP under PDF/A): author, subject, keywords, /Trapped. | |
| pageSize | No | Portrait page preset (points): A4 595.28×841.89 (default), Letter 612×792, Legal 612×1008, A3 841.89×1190.55, Tabloid 792×1224. print.* boxes must fit it. | |
| embedFonts | No | Embed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A claim (ISO 19005 §6.2.11.4.1) and for strict=true; adds ~0.3 MiB. | |
| footerText | No | Optional footer text rendered at the bottom of every page. | |
| outputMode | No | Either 'base64' (returns the PDF inline) or 'file' (writes to a sandboxed path inside PDFNATIVE_MCP_OUTPUT_DIR). | base64 |
| outputPath | No | Required when outputMode='file'. Relative path inside the sandbox; must end with .pdf. | |
| creationDate | No | ISO-8601 instant for /CreationDate (+ XMP). Pin it for byte-identical output across calls (same host TZ); omitted = wall clock, so every call differs. | |
| outputIntent | No | Custom PDF/A OutputIntent: an RGB ICC profile + condition strings replacing the built-in sRGB intent (CMYK rejected). | |
| footerTemplate | No | Running footer on every page. Replaces the default footer: footerText is then ignored and page numbers appear only via {page}/{pages}. | |
| headerTemplate | No | Running header on every page (left / center / right zones); reserves 15 pt. | |
| includeDiagnostics | No | Return the PDF/A diagnostics raised while building as `diagnostics[]` (possibly empty). |
Output Schema
| Name | Required | Description |
|---|---|---|
| mode | Yes | |
| summary | No | Tool-specific summary, when produced. |
| filePath | No | Sandboxed absolute path (file mode). |
| sizeBytes | Yes | |
| diagnostics | No | PDF/A diagnostics (when includeDiagnostics=true). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the safety profile (readOnly=false for a document-creation mutation, idempotent=true, destructive=false), and the description adds modest context beyond that — noting this tool creates a new PDF rather than touching existing content and that common options mirror the other document tools. It does not dive into side effects, output format, or state changes for file-mode output, but with the schema carrying those details, a mid-score is fair.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, each earning its place: the first states what the tool does and lists the field types; the second gives the exclusion rroute; the third signals family-wide option consistency. It is front-loaded and contains no filler—just a minor tightening opportunity in the redundant 'as on every document tool' phrase.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 20-parametee complex nested tool, the combination of a 100%-covered schema, an output schema, and safety annotations gives the complete picture — required and output modes (base64/file), return to return, exclusive modes, defaults all live in the structure. The only region left to the agent to discover is the return-up artifact structure, which the output schema holds, so nothing critical is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so each of the 20 parameters is already documented (units, defaults, exclusivities, groupings). The description merely hints at the field vocabulary without repeating parameter-level detail; no compensation needed, but also no added value above the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Starts with a specific verb+resource — 'New PDF with an interactive AcroForm' — and enumerates the concrete control types (text fields, text areas, checkboxes, radio buttons, dropdowns). It further sharpens the scope by naming the sibling path it is NOT ('To fill or flatten an EXISTING form...'), so an agent can distinguish create-from-fill at a glance.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes the agent away from this tool for existing forms: 'To fill or flatten an EXISTING form use read_form_fields + fill_form.' The use cases (data capture, surveys, fillable templates) imply when to call it. It does not, however, contrast with other creation tools like generate_basic_pdf, so the boundary for 'when a plain PDF suffices' is left implicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
add_international_textAdd international textAIdempotent
PDF rendering text in 24 scripts (Arabic, Hebrew, Thai, CJK, Devanagari, Bengali, Tamil, Telugu, Sinhala, Tibetan, Khmer, Myanmar, Ethiopic, Cyrillic, Greek, Georgian, Armenian, Vietnamese, …), COLRv1 colour emoji and mathematical symbols ('math': ∀ ∃ √ ∑ ∫ ∞). BiDi (UAX #9), Arabic joining and complex-script shaping are automatic; input is NFC-normalised; newlines split paragraphs. lang is a code or an array for mixed runs (['ar','emoji'], ['latin','math']). Fonts are always embedded, so embedFonts does not exist here. PDF/A, print, metadata and creationDate options as on every document tool.
| Name | Required | Description | Default |
|---|---|---|---|
| lang | Yes | Language / script identifier. Either a single code (e.g. 'ar'), a comma-separated list ('ar,emoji'), or an array (['ar','emoji']). Multiple codes enable multi-font run splitting (script + emoji + Latin fallback). | |
| pdfA | No | PDF/A level (Tagged PDF + sRGB OutputIntent + XMP). Fonts are embedded here, so the claim is valid as-is. See docs/guides/PDFA.md. | |
| debug | No | Draw margin / block / cell guide rectangles (unmarked content — not for PDF/UA output). Geometry unchanged. Default false. | |
| No | Print production (ISO 32000-1 §14.11): page boxes, `bleed` shorthand (TrimBox = MediaBox inset), crop/registration marks outside the TrimBox, /UserUnit for large formats (PDF 1.7; not under pdfa1b). See docs/guides/PRINT.md. | ||
| title | Yes | PDF title (rendered as page heading and stored as document metadata). | |
| strict | No | Fail with PDF_A_COMPLIANCE_VIOLATION instead of producing a non-conformant PDF/A file (e.g. PDFA_NO_FONT_ENTRIES without embedFonts). Pair with embedFonts=true. | |
| encrypt | No | Encrypt at build time (AES-128 default / AES-256) and KEEP the AcroForm — unlike encrypt_pdf, which rebuilds the page tree. Exclusive with pdfA. Randomised output, never cached. | |
| margins | No | Margins in points, all four required (0–200). Default 45 / 36 / 35 / 36. | |
| compress | No | FlateDecode the streams (smaller file, different bytes; PDF/A unaffected, XMP stays plain). Default false. | |
| metadata | No | /Info (+ XMP under PDF/A): author, subject, keywords, /Trapped. | |
| pageSize | No | Portrait page preset (points): A4 595.28×841.89 (default), Letter 612×792, Legal 612×1008, A3 841.89×1190.55, Tabloid 792×1224. print.* boxes must fit it. | |
| normalize | No | Unicode normalization before shaping. Default 'NFC' (widest glyph coverage); NFD/NFKC/NFKD or false for special needs. | |
| outputMode | No | 'base64' (default) returns the PDF inline; 'file' writes it inside the PDFNATIVE_MCP_OUTPUT_DIR sandbox (SECURITY_VIOLATION when the sandbox is not configured). | base64 |
| outputPath | No | Required when outputMode='file'. Relative path inside the sandbox; must end with .pdf (no absolute paths, no '..'). | |
| paragraphs | Yes | Ordered list of paragraphs to render in the chosen script. | |
| creationDate | No | ISO-8601 instant for /CreationDate (+ XMP). Pin it for byte-identical output across calls (same host TZ); omitted = wall clock, so every call differs. | |
| outputIntent | No | Custom PDF/A OutputIntent: an RGB ICC profile + condition strings replacing the built-in sRGB intent (CMYK rejected). | |
| footerTemplate | No | Running footer on every page. Replaces the default footer: footerText is then ignored and page numbers appear only via {page}/{pages}. | |
| headerTemplate | No | Running header on every page (left / center / right zones); reserves 15 pt. | |
| viewerPreferences | No | Reader presentation hints (catalog /PageLayout, /PageMode, /ViewerPreferences). PDF/A-safe; all optional. | |
| includeDiagnostics | No | Return the PDF/A diagnostics raised while building as `diagnostics[]` (possibly empty). |
Output Schema
| Name | Required | Description |
|---|---|---|
| mode | Yes | |
| summary | No | Tool-specific summary, when produced. |
| filePath | No | Sandboxed absolute path (file mode). |
| sizeBytes | Yes | |
| diagnostics | No | PDF/A diagnostics (when includeDiagnostics=true). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations, the description discloses important behavioral facts: BiDi, Arabic joining, complex-script shaping, NFC normalization, newlines become paragraphs, and fonts are always embedded so embedFonts does not exist. This is exactly the kind of behavior an agent cannot infer from the schema alone, and it contradicts no annotation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three-to-five dense sentences deliver a lot of ground without filler. The heavy script list is pruned with ellipsis, behavioral facts are front-loaded, and shared document options are collapsed into one phrase. It could trim a little, but it commits no wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex tool with 21 parameters, an output schema, and nested objects, this description covers the critical behavioral and parameter concerns. It could still be improved by naming the typical alternative for plain-Latin text, but it is nearly complete as it stands for selecting and calling the tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so a baseline of 3 applies, but the description adds real semantics: lang can be either a single code or an array for mixed runs, newlines split paragraphs, and Unicode normalization behavior is explicitly described. This is genuinely useful beyond the schema, though not exhaustive.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the tool as rendering PDF text in 24 scripts plus emoji and math, which distinguishes it from siblings like add_table, add_barcode, and add_chart. It does not explicitly state that it creates a new PDF document or position itself against generate_basic_pdf, so it stops just short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives a strong capability profile: international scripts, automatic shaping, always-embedded fonts, and no embedFonts option. However, it never explicitly says when to use this tool instead of a sibling such as generate_basic_pdf or add_table, so the when-to-use guidance is implied rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
add_ltvEmbed LTV validation material (PAdES B-LT)A
PAdES B-LT: embed a Document Security Store (/DSS + per-signature /VRI) with the certificates and OCSP/CRL material future verifiers need ('LTV enabled' in Adobe Reader once the root is trusted). Ladder step 3: sign_pdf (profile:'pades', timestamp:true) → add_ltv → timestamp_pdf. mode 'online' (default) fetches through the OPERATOR revocation provider (PDFNATIVE_MCP_REVOCATION + PDFNATIVE_MCP_NETWORK_ALLOWED_HOSTS; REVOCATION_NOT_CONFIGURED otherwise — no network without it); mode 'offline' embeds caller-supplied DER certificates / OCSP responses / CRLs with zero network. Incremental (existing /DSS merged). Needs ≥ 1 signed signature; unencrypted PDFs only.
| Name | Required | Description | Default |
|---|---|---|---|
| mode | No | 'online': fetch OCSP/CRL through the operator provider (PDFNATIVE_MCP_REVOCATION + allow-list; REVOCATION_NOT_CONFIGURED otherwise). 'offline': embed the caller-supplied DER material, zero network. | online |
| pdfBase64 | Yes | Base64-encoded SIGNED PDF (unencrypted). Sign with sign_pdf (profile=pades recommended) first. | |
| outputMode | No | 'base64' (default) returns the PDF inline; 'file' writes it inside the PDFNATIVE_MCP_OUTPUT_DIR sandbox (SECURITY_VIOLATION when the sandbox is not configured). | base64 |
| outputPath | No | Relative path inside PDFNATIVE_MCP_OUTPUT_DIR (required when outputMode='file'). | |
| preferOcsp | No | online: try OCSP before CRL for each certificate (default true). | |
| crlsDerBase64 | No | offline: DER CertificateList (RFC 5280) blobs to embed in /DSS /CRLs. | |
| certificatesDerBase64 | No | offline: DER X.509 certificates to embed in /DSS /Certs. | |
| ocspResponsesDerBase64 | No | offline: DER OCSPResponse (RFC 6960) blobs to embed in /DSS /OCSPs. | |
| extraCertificatesDerBase64 | No | online: additional DER certificates (intermediates / roots) to complete chains the CMS does not carry. |
Output Schema
| Name | Required | Description |
|---|---|---|
| mode | Yes | |
| summary | No | Tool-specific summary, when produced. |
| filePath | No | Sandboxed absolute path (file mode). |
| sizeBytes | Yes | |
| diagnostics | No | PDF/A diagnostics (when includeDiagnostics=true). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses important behavioral traits beyond annotations: network behaviour via the OPERATOR revocation provider, zero network in offline mode, incremental merging of existing /DSS, and constraints on signed/unencrypted input. There is no contradiction with the annotations, which treat it as a mutating and world-open operation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but efficient: it front-loads the core purpose and PAdES context, then uses compact parentheticals for mode/error details. It avoids fluff while still packing workflow, security, and environmental constraints into a text that earns its length.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex, 9-parameter tool with external network side effects, this description is complete. It explains the PAdES level, the call sequence, the mode differences, the security configuration, the offline/online material sources, and the key input constraints. Combined with the full schema and present output schema, an agent has enough to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, and each parameter already has detailed inline descriptions. The description adds some contextual value about modes and prerequisites, but it largely restates information present in the input schema rather than contributing new parameter-level semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb-resource pair: 'embed a Document Security Store (/DSS + per-signature /VRI)' with validation material. It also situates the tool in a clear sequence (sign_pdf → add_ltv → timestamp_pdf), which disambiguates it from sign_pdf and timestamp_pdf without needing to inspect the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage context is explicit: it is ladder step 3, requires at least one signed signature, requires an unencrypted PDF, and differentiates online vs offline modes. It even names the error condition (REVOCATION_NOT_CONFIGURED) and the environment prerequisites, leaving no ambiguity about when this tool is appropriate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
add_tableAdd table / reportAIdempotent
Tabular PDF report from headers + rows (every row the same length). Smart-table options: wrap, repeatHeader (header on every page), zebra, caption (tagged for PDF/A), minRowHeight, cellPadding, cellBorders, cellVAlign, autoFitColumns, clipCells. Inside a longer document use a 'table' block of generate_basic_pdf instead. PDF/A (pdfA + embedFonts:true), print, metadata, watermark and creationDate options as on every document tool.
| Name | Required | Description | Default |
|---|---|---|---|
| pdfA | No | PDF/A level: pdfa1b (simple text+images), pdfa2b/pdfa2u (richer; 2u = Unicode mapping), pdfa3b (attachments / Factur-X). Pair with embedFonts=true for a valid claim. Exclusive with encryption. See docs/guides/PDFA.md. | |
| rows | Yes | Data rows. Each row is an array of cell strings with the same length as `headers`. | |
| wrap | No | Cell wrap policy: 'auto' (default) wraps only overflowing cells; 'always' wraps every cell; 'never' truncates. | |
| debug | No | Draw margin / block / cell guide rectangles (unmarked content — not for PDF/UA output). Geometry unchanged. Default false. | |
| No | Print production (ISO 32000-1 §14.11): page boxes, `bleed` shorthand (TrimBox = MediaBox inset), crop/registration marks outside the TrimBox, /UserUnit for large formats (PDF 1.7; not under pdfa1b). See docs/guides/PRINT.md. | ||
| title | Yes | Report title rendered at the top of the document and used as PDF metadata title. | |
| zebra | No | Alternate-row light tint (static fill, PDF/A-1b safe). | |
| strict | No | Fail with PDF_A_COMPLIANCE_VIOLATION instead of producing a non-conformant PDF/A file (e.g. PDFA_NO_FONT_ENTRIES without embedFonts). Pair with embedFonts=true. | |
| caption | No | Caption rendered above the table (tagged as /Caption under PDF/A). | |
| encrypt | No | Encrypt at build time (AES-128 default / AES-256) and KEEP the AcroForm — unlike encrypt_pdf, which rebuilds the page tree. Exclusive with pdfA. Randomised output, never cached. | |
| headers | Yes | Column header labels. Must have the same length as each row in `rows`. | |
| margins | No | Margins in points, all four required (0–200). Default 45 / 36 / 35 / 36. | |
| compress | No | FlateDecode the streams (smaller file, different bytes; PDF/A unaffected, XMP stays plain). Default false. | |
| metadata | No | /Info (+ XMP under PDF/A): author, subject, keywords, /Trapped. | |
| pageSize | No | Portrait page preset (points): A4 595.28×841.89 (default), Letter 612×792, Legal 612×1008, A3 841.89×1190.55, Tabloid 792×1224. print.* boxes must fit it. | |
| clipCells | No | Clip cell contents to the column bounds (PDF clip operators). Recommended for PDF/A and visual safety. | |
| infoItems | No | Optional key-value metadata rows rendered below the title (e.g. date, author). | |
| watermark | No | Optional semi-transparent watermark rendered centred on every page: `text` (e.g. 'DRAFT'), `image` (JPEG/PNG), or both combined. At least one of text / image is required. opacity < 1.0 (text or image, including the defaults) is rejected under pdfA='pdfa1b' (ISO 19005-1 forbids transparency). | |
| cellVAlign | No | Vertical alignment of cell content. | |
| embedFonts | No | Embed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A claim (ISO 19005 §6.2.11.4.1) and for strict=true; adds ~0.3 MiB. | |
| footerText | No | Optional text rendered at the bottom of every page. | |
| outputMode | No | Either 'base64' (returns the PDF inline) or 'file' (writes to a sandboxed path inside PDFNATIVE_MCP_OUTPUT_DIR). | base64 |
| outputPath | No | Required when outputMode='file'. Relative path inside the sandbox; must end with .pdf. | |
| cellBorders | No | Per-cell vector borders (pure strokes, PDF/A-safe). Choose individual sides or `all`. | |
| cellPadding | No | Horizontal cell padding in points (default 3). | |
| creationDate | No | ISO-8601 instant for /CreationDate (+ XMP). Pin it for byte-identical output across calls (same host TZ); omitted = wall clock, so every call differs. | |
| minRowHeight | No | Minimum row height in points (default 12). | |
| outputIntent | No | Custom PDF/A OutputIntent: an RGB ICC profile + condition strings replacing the built-in sRGB intent (CMYK rejected). | |
| repeatHeader | No | Repeat the header row on every continuation page (default true). | |
| autoFitColumns | No | Auto-fit column widths to content. Output bytes then depend on text metrics (not byte-deterministic across content changes). | |
| footerTemplate | No | Running footer on every page. Replaces the default footer: footerText is then ignored and page numbers appear only via {page}/{pages}. | |
| headerTemplate | No | Running header on every page (left / center / right zones); reserves 15 pt. | |
| viewerPreferences | No | Reader presentation hints (catalog /PageLayout, /PageMode, /ViewerPreferences). PDF/A-safe; all optional. | |
| includeDiagnostics | No | Return the PDF/A diagnostics raised while building as `diagnostics[]` (possibly empty). |
Output Schema
| Name | Required | Description |
|---|---|---|
| mode | Yes | |
| summary | No | Tool-specific summary, when produced. |
| filePath | No | Sandboxed absolute path (file mode). |
| sizeBytes | Yes | |
| diagnostics | No | PDF/A diagnostics (when includeDiagnostics=true). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare destructiveHint=false, readOnlyHint=false, idempotentHint=true. The description adds meaningful behavior: PDF/A interaction with embedFonts, strict failure mode (PDF_A_COMPLIANCE_VIOLATION), tagged caption implications, and encryption/caching notes. These details exceed what annotations cover, though with a 34-param schema, the focus stays on the table-specific aspects.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense and well-structured, front-loads the core concept (tabular PDF report from headers+rows), and packs the smart-table options into one efficient list. Every sentence adds value, with the routing to generate_basic_pdf placed last as a natural afterthought.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has a huge schema (34 params) and output schema, so the description does not need to explain every return value. It covers the key behavioral notes (PDF/A compliance, embedFonts), and the self-contained table nature is clear. It does not explicitly mention outputMode/outputPath, but the schema covers that, so the balance is appropriate.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3; the description does not need to restate every parameter. It adds a top-level framing ('Smart-table options: wrap, repeatHeader ...') that summarizes the parameter groups without duplicating schema detail. It directly compensates where the schema is otherwise terse, e.g., grouping the table-format options.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Tabular PDF report from `headers` + `rows` (every row the same length)', which names the specific verb (add/generate), the resource (table report), and the core inputs. It distinguishes this tool from generate_basic_pdf explicitly by mentioning the alternative for embedding a table inside a longer document.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says 'Inside a longer document use a \'table\' block of generate_basic_pdf instead,' providing an exclusion condition and the named alternative. It also notes the shared options ('as on every document tool'), which sets expectations for typical usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
annotate_pdfAnnotate PDF (markup / drawing)AIdempotent
Append markup annotations (ISO 32000-1 §12.5) to an existing PDF as a non-destructive incremental update (original bytes preserved). Types: text (sticky note), highlight | underline | strikeout | squiggly, square | circle, line (needs start/end), freetext. Each needs a 0-based page and rect [x1,y1,x2,y2]; optional contents, color, opacity, title and type-specific fields. VISUAL OVERLAY ONLY — nothing is removed or redacted (covered text stays extractable). Encrypted sources → ENCRYPTED_SOURCE (decrypt_pdf first).
| Name | Required | Description | Default |
|---|---|---|---|
| pdfBase64 | Yes | Base64-encoded source PDF to annotate. | |
| outputMode | No | 'base64' (default) returns the PDF inline; 'file' writes it inside the PDFNATIVE_MCP_OUTPUT_DIR sandbox (SECURITY_VIOLATION when the sandbox is not configured). | base64 |
| outputPath | No | Required when outputMode='file'. Relative path inside the sandbox; must end with .pdf (no absolute paths, no '..'). | |
| annotations | Yes | Markup / drawing annotations to add. Each is attached to a 0-based page index. |
Output Schema
| Name | Required | Description |
|---|---|---|
| mode | Yes | |
| summary | No | Tool-specific summary, when produced. |
| filePath | No | Sandboxed absolute path (file mode). |
| sizeBytes | Yes | |
| diagnostics | No | PDF/A diagnostics (when includeDiagnostics=true). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint: false, destructiveHint: false, and idempotentHint: true, but the description significantly adds behavior beyond these: the PDF is modified non-destructively as an incremental update, original bytes are preserved, and content is never removed or redacted. It also warns about encrypted sources and sandbox file output. This is much stronger than the annotations alone.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact yet information-dense, structured as a sentence listing current valid types, then a sentence covering required parameters, then a warning. Major constraints and warnings are uppercase and front-loaded within each sentence. No filler or repetition of the schema is present.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the rich input schema that already documents every parameter and an existing output schema, the prose description still covers all operational facts an agent needs: non-destructive behavior, required coordinate parameters, encrypted-source handling, and sandbox file writing. There are no missing behavioral warnings or usage caveats that an agent would need to know before making a safe call.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already documents every parameter with useful descriptions, so the schema itself carries most semantics. The description enriches understanding by explaining the coordinate system (PDF user-space points), showing which parameters go with which annotation types (e.g. start/end for line, icon/open for text, quadPoints for markup types), and by stating that type-specific fields are optional. The one weak area is that outputMode/outputPath semantics are mostly schema-covered, but the description does reinforce the sandbox requirement.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the resource (existing PDF) and the precise action (append markup annotations as a non-destructive incremental update), listing supported annotation types and the standard it follows. It distinguishes itself from sibling tools like sign_pdf, encrypt_pdf, and merge_pdfs without needing detailed inspection.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states what it is not for: 'VISUAL OVERLAY ONLY — nothing is removed or redacted (covered text stays extractable).' It explicitly advises that encrypted sources require decrypt_pdf first. This provides clear when-to-use and when-not-to-use guidance relative to sibling tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
decrypt_pdfDecrypt a PDFAIdempotent
Emit an UNENCRYPTED copy of an encrypted PDF (RC4 V1–V4, AES-128, AES-256) given password (user or owner; empty user password needs none). CAVEAT: the page tree is rebuilt — signatures and AcroForm are DROPPED. To merely READ an encrypted PDF pass password to inspect_pdf / extract_text / extract_attachments / read_form_fields instead. Never cached.
| Name | Required | Description | Default |
|---|---|---|---|
| password | No | Password to open the encrypted source (user or owner). Omit only for documents with an empty user password. | |
| pdfBase64 | Yes | Base64-encoded encrypted PDF to decrypt. NOTE: signatures and AcroForm are dropped (page-tree rebuild). | |
| outputMode | No | 'base64' (default) returns the PDF inline; 'file' writes it inside the PDFNATIVE_MCP_OUTPUT_DIR sandbox (SECURITY_VIOLATION when the sandbox is not configured). | base64 |
| outputPath | No | Required when outputMode='file'. Relative path inside the sandbox; must end with .pdf. |
Output Schema
| Name | Required | Description |
|---|---|---|
| mode | Yes | |
| summary | No | Tool-specific summary, when produced. |
| filePath | No | Sandboxed absolute path (file mode). |
| sizeBytes | Yes | |
| diagnostics | No | PDF/A diagnostics (when includeDiagnostics=true). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses important non-obvious behaviors: the page tree is rebuilt, signatures and AcroForm are dropped, and results are never cached. This adds substantial value beyond the annotations, and no contradiction exists with idempotentHint/readOnlyHint.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three compact sentences front-load the core purpose, then the critical caveat, then the alternative routes. Each sentence earns its place, and the formatting makes the warning noticeable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description, together with the fully documented schema, is sufficient for an agent to invoke the tool correctly: it covers supported algorithms, password requirements, the destructive caveat, alternate tools, and output modes are already in the schema. No critical operational context is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all parameters and constraints. The description reiterates the password semantics and caveat, matching the schema but adding no substantial new parameter-level detail.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Emit an UNENCRYPTED copy') and clearly identifies the resource (encrypted PDF) and supported encryption types. It also explicitly distinguishes itself from read-only PDF tools, so an agent can tell it apart from siblings like inspect_pdf and extract_text.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It states exactly when to use this tool versus alternatives: to decrypt by emitting a new copy, and when merely reading an encrypted PDF to pass the password to sibling read tools instead. This gives explicit routing guidance with named alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
draft_governance_issueDraft a governance-compliant GitHub issue (HITL)AIdempotent
Produce a LOCAL GitHub issue draft + compliance report for pdfnative / pdfnative-mcp and NEVER submit it — the agent drafts, a human reviews and files it under their own identity (Human-In-The-Loop contract, .github/AGENT_RULES.md). No GitHub write path exists. The draft is checked against the zero-dependency + reproduction policy; a violation (new runtime dependency, missing reproduction, duplicateSearchPerformed:false) throws GOVERNANCE_VIOLATION. Returns markdown inline (outputMode:'file' also writes a .md). Present the draft AND the report to the user, then STOP.
| Name | Required | Description | Default |
|---|---|---|---|
| title | Yes | Concise issue title (imperative, no trailing period). | |
| summary | Yes | One or two paragraphs describing the problem or proposal. | |
| issueType | Yes | Issue category: 'bug' | 'feature' | 'security' | 'docs' | 'performance'. | |
| outputMode | No | 'inline' (default) returns the draft markdown in the response. 'file' additionally writes it to the sandbox (requires PDFNATIVE_MCP_OUTPUT_DIR); outputPath must be a relative .md path. | inline |
| outputPath | No | Relative .md path inside the sandbox (only when outputMode='file'). | |
| targetRepo | No | Destination repository label for the draft (documentation only — the server never contacts it). Typically 'pdfnative-mcp' or 'pdfnative'. | pdfnative-mcp |
| reproduction | Yes | The minimal, locally-executed reproduction that justifies this issue. | |
| actualBehavior | No | What actually happened (defaults to the reproduction result when omitted). | |
| affectedPackages | No | Packages impacted by this issue (e.g. ["pdfnative-mcp"], ["pdfnative"]). | |
| expectedBehavior | Yes | What you expected to happen instead. | |
| duplicateSearchPerformed | Yes | MUST be true: confirms you searched open AND closed issues/PRs for duplicates before drafting. |
Output Schema
| Name | Required | Description |
|---|---|---|
| title | Yes | |
| filePath | No | Sandboxed absolute path (when outputMode='file'). |
| warnings | Yes | |
| issueType | Yes | |
| sizeBytes | Yes | |
| compliance | Yes | |
| outputMode | Yes | |
| targetRepo | Yes | |
| draftMarkdown | Yes | The full draft, ready for a human to review and submit. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes beyond the annotation set and provides crucial behavioral context: the draft is never submitted, a human files it, no GitHub write path exists, policy violations raise GOVERNANCE_VIOLATION, and the agent must present output and then STOP. This is exactly the kind of non-obvious behavior an autonomous agent needs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact yet information-dense. Critically, it front-loads the key constraints (LOCAL, NEVER submit, HITL) and includes the procedural end state ('present the draft AND the report to the user, then STOP') with no wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the 11 parameters, nested reproduction object, output schema, and annotations, this description still closes all important gaps: the governance policy, violation behavior, output modes, human review step, and stop condition. An agent has enough to invoke the tool and interpret its guidance correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Even though the input schema describes every parameter thoroughly, the description adds meaningful behavioral requirements: duplicateSearchPerformed:false triggers a GOVERNANCE_VIOLATION, and outputMode 'file' writes a .md file. These enrich the interpretation of the parameters beyond their simple schema definitions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('Produce a LOCAL GitHub issue draft + compliance report'), the resource ('for pdfnative / pdfnative-mcp'), and the critical boundary ('NEVER submit it'). It is fully differentiated from the PDF-manipulation siblings by the explicit issue-drafting scope.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It clearly establishes when to use the tool: when an issue draft is needed under the Human-In-The-Loop contract and must not be submitted. It also tells the agent it does not provide a GitHub write path, implying it should not be used for actual issue submission, though no explicit alternative tool is named.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
embed_imageEmbed image in PDFAIdempotent
PDF with one embedded JPEG or PNG (base64; PNG without alpha channel) plus optional caption and render width/height. Inside a longer document use an 'image' block of generate_basic_pdf instead. PDF/A, print, metadata and creationDate options as on every document tool.
| Name | Required | Description | Default |
|---|---|---|---|
| alt | No | Accessible description of the image (tagged /Figure /Alt). Provide it for non-decorative images under PDF/A or PDF/UA. | |
| pdfA | No | PDF/A level: pdfa1b (simple text+images), pdfa2b/pdfa2u (richer; 2u = Unicode mapping), pdfa3b (attachments / Factur-X). Pair with embedFonts=true for a valid claim. Exclusive with encryption. See docs/guides/PDFA.md. | |
| align | No | Horizontal placement of the image inside the content width. | left |
| debug | No | Draw margin / block / cell guide rectangles (unmarked content — not for PDF/UA output). Geometry unchanged. Default false. | |
| No | Print production (ISO 32000-1 §14.11): page boxes, `bleed` shorthand (TrimBox = MediaBox inset), crop/registration marks outside the TrimBox, /UserUnit for large formats (PDF 1.7; not under pdfa1b). See docs/guides/PRINT.md. | ||
| title | Yes | Document title rendered at the top and used as PDF metadata title. | |
| width | No | Render width in points. If omitted, the image is auto-sized to fit the page. | |
| height | No | Render height in points. If omitted, aspect ratio is preserved. | |
| strict | No | Fail with PDF_A_COMPLIANCE_VIOLATION instead of producing a non-conformant PDF/A file (e.g. PDFA_NO_FONT_ENTRIES without embedFonts). Pair with embedFonts=true. | |
| caption | No | Optional caption rendered below the image. | |
| encrypt | No | Encrypt at build time (AES-128 default / AES-256) and KEEP the AcroForm — unlike encrypt_pdf, which rebuilds the page tree. Exclusive with pdfA. Randomised output, never cached. | |
| margins | No | Margins in points, all four required (0–200). Default 45 / 36 / 35 / 36. | |
| compress | No | FlateDecode the streams (smaller file, different bytes; PDF/A unaffected, XMP stays plain). Default false. | |
| metadata | No | /Info (+ XMP under PDF/A): author, subject, keywords, /Trapped. | |
| mimeType | Yes | MIME type of the image. Must match the actual encoding of imageBase64 (magic bytes are checked). | |
| pageSize | No | Portrait page preset (points): A4 595.28×841.89 (default), Letter 612×792, Legal 612×1008, A3 841.89×1190.55, Tabloid 792×1224. print.* boxes must fit it. | |
| embedFonts | No | Embed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A claim (ISO 19005 §6.2.11.4.1) and for strict=true; adds ~0.3 MiB. | |
| outputMode | No | Either 'base64' (returns the PDF inline) or 'file' (writes to a sandboxed path inside PDFNATIVE_MCP_OUTPUT_DIR). | base64 |
| outputPath | No | Required when outputMode='file'. Relative path inside the sandbox; must end with .pdf. | |
| imageBase64 | Yes | Base64 image bytes. JPEG (baseline; 1, 3 or 4 components — CMYK raises PDFA_DEVICE_CMYK_IMAGE under PDF/A) or PNG (8-bit greyscale/RGB, non-interlaced; alpha-channel and palette PNGs are rejected with a remedy). No data: URI. | |
| creationDate | No | ISO-8601 instant for /CreationDate (+ XMP). Pin it for byte-identical output across calls (same host TZ); omitted = wall clock, so every call differs. | |
| outputIntent | No | Custom PDF/A OutputIntent: an RGB ICC profile + condition strings replacing the built-in sRGB intent (CMYK rejected). | |
| footerTemplate | No | Running footer on every page. Replaces the default footer: footerText is then ignored and page numbers appear only via {page}/{pages}. | |
| headerTemplate | No | Running header on every page (left / center / right zones); reserves 15 pt. | |
| includeDiagnostics | No | Return the PDF/A diagnostics raised while building as `diagnostics[]` (possibly empty). |
Output Schema
| Name | Required | Description |
|---|---|---|
| mode | Yes | |
| summary | No | Tool-specific summary, when produced. |
| filePath | No | Sandboxed absolute path (file mode). |
| sizeBytes | Yes | |
| diagnostics | No | PDF/A diagnostics (when includeDiagnostics=true). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide readOnlyHint=false, idempotentHint=true, and destructiveHint=false, covering the safety profile. The description adds the 'PNG without alpha channel' input constraint (already present in the schemas) and the cross-tool option pattern, but reveals no new behavioral traits beyond what annotations and schema already state. No contradiction exists.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences with each carrying a distinct role: scope definition, sibling alternative, and cross-tool option pattern. The final sentence is slightly abstract but avoids redundancy, and the description is front-loaded with the clarifying scope before routing guidance.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 25-parameter tool with an output schema and rich parameter descriptions, the description covers the essential invocation decision and defers the rest to the schema. The main omission is any high-level note about output behavior, but the output schema and idempotency annotation fill that gap adequately.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all 25 parameters. The description briefly names caption, render width/height, and the doc-wide options group, but provides no new semantic detail beyond what the parameter schemas already give.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States the scope precisely: one PDF with a single embedded base64 JPEG/PNG, optional caption, and render width/height. It explicitly names generate_basic_pdf's 'image' block for longer documents, which differentiates it from the most similar sibling tool without opening any schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit when-not-to-use rule with the alternative tool: 'Inside a longer document use an image block of generate_basic_pdf instead.' This directly routes the agent to the correct sibling, with the positive use case for this tool implied by contrast.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
encrypt_pdfEncrypt / re-secure a PDFA
Encrypt an existing PDF with the Standard Security Handler: AES-128 (default) or AES-256; RC4 is never emitted. ownerPassword required; optional userPassword (open password), permissions { print, copy, modify, extractText }. Rotate the password of an already-encrypted source by passing its current password. CAVEAT: the page tree is rebuilt — signatures and AcroForm are DROPPED, only URI links kept; encrypt BEFORE signing. Never cached.
| Name | Required | Description | Default |
|---|---|---|---|
| password | No | Current password of an already-encrypted source (enables password rotation). Omit for an unencrypted source. | |
| algorithm | No | aes128 (V4/R4, widest compatibility) or aes256 (V5/R6). | aes128 |
| pdfBase64 | Yes | Base64-encoded source PDF to encrypt. NOTE: existing signatures and AcroForm are dropped (page-tree rebuild). | |
| outputMode | No | 'base64' (default) returns the PDF inline; 'file' writes it inside the PDFNATIVE_MCP_OUTPUT_DIR sandbox (SECURITY_VIOLATION when the sandbox is not configured). | base64 |
| outputPath | No | Required when outputMode='file'. Relative path inside the sandbox; must end with .pdf. | |
| permissions | No | Permission flags; each defaults to allowed. | |
| userPassword | No | Open password; omitted/empty = opens without a prompt. | |
| ownerPassword | Yes | Owner password (full access). |
Output Schema
| Name | Required | Description |
|---|---|---|
| mode | Yes | |
| summary | No | Tool-specific summary, when produced. |
| filePath | No | Sandboxed absolute path (file mode). |
| sizeBytes | Yes | |
| diagnostics | No | PDF/A diagnostics (when includeDiagnostics=true). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotation declares `destructiveHint`: false, but the description honestly states that the page tree is rebuilt and signatures/AcroForm are DROPPED. This is an annotation contradiction; per rubric a direct contradiction requires a score of 1.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences and every one earns its place: algorithm/handler, password/permissions/rotation, then the destructive caveat. The security-relevant warnings are front-loaded and there is no fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 8 parameters, 100% schema coverage, and an output schema available, the description covers every decision axis: algorithm version, rotation, permissions, timing, outputMode implications, and the destructive caveat. Nothing an agent needs to select or invoke it safely is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so every parameter is already meaningfully described in the input schema. The description restates ownerPassword required, optional userPassword, permission flags, and rotation; this convenience is useful but adds little beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Says exactly what it does: 'Encrypt an existing PDF' with a named handler, algorithms, password modes, permissions, and rotation use-case. This cleanly separates `enrypt_pdf` from sibling tools like `decrypt_pdf` and `sign_pdf`.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear context: use it on unencrypted or already-encrypted via `password` for rotation, and explicitly says to run encryption BEFORE signing. It does not spell out a when-not-to-use alternative such as 'use decryption for removing security', but the workflow cy is strong.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
extract_attachmentsExtract embedded files from PDFARead-onlyIdempotent
Read-only extraction of embedded files (PDF/A-3, Factur-X, ZUGFeRD): name, mimeType, AFRelationship, description, sizeBytes and (by default) the payload as dataBase64. filename selects one file; includeData:false probes metadata only. Encrypted sources: pass password. Token-frugal: verbosity:'summary'.
| Name | Required | Description | Default |
|---|---|---|---|
| fields | No | Optional dot-path projection applied to the structured result (e.g. ['attachments.name']). Composes after verbosity. Unknown paths are omitted. | |
| filename | No | Optional exact attachment name to extract. When omitted, every embedded file is returned. | |
| password | No | Password (user or owner) of an encrypted source. Never logged or echoed. | |
| pdfBase64 | Yes | Base64-encoded PDF bytes to read embedded files from. | |
| verbosity | No | Response verbosity. 'full' (default) returns the attachments[] array; 'summary' returns a token-frugal { attachmentCount } and drops the array. | full |
| includeData | No | When true (default) each attachment carries its decoded payload as dataBase64. Set false for a metadata-only probe (names, sizes, relationships) with no payload bytes. |
Output Schema
| Name | Required | Description |
|---|---|---|
| attachments | No | |
| attachmentCount | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and idempotentHint, and the description reinforces this with 'Read-only extraction'. It adds valuable behavioral details beyond annotations: default payload inclusion, metadata-only probing, password handling, and token-frugal summary mode. These add meaningful context without contradicting the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three tightly-worded sentences with no fluff. The core action is front-loaded (read-only extraction), key formats are named in the first sentence, and the remaining sentences efficiently cover optional behaviors and parameter interactions.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has a high-quality output schema, rich parameter descriptions, and complete annotations, the description covers the necessary behavioral context: file selection, payload vs metadata probing, encrypted sources, and response verbosity. Nothing appears missing for an agent to correctly invoke this tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already provides 100% parameter coverage with detailed descriptions, so the baseline is 3. The description adds concise semantic layer by explaining the practical intent of includeData:false as metadata-only probing and verbosity:'summary' as token-frugal. It also hints at the relationship between filename and single-file selection, complementing the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies a specific verb-object pair ('Read-only extraction') targeting embedded files in PDFs, including recognizable formats like PDF/A-3 and ZUGFeRD. This distinguishes it from sibling tools such as add_attachment and extract_text without ambiguity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear usage context: extracting embedded files from a PDF, including how to select a single file, probe metadata only, handle encrypted sources, and save tokens. It stops short of explicitly naming alternative tools or stating when not to use this tool, but the context is strong enough for an agent to route correctly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
extract_pagesExtract pages into one PDFAIdempotent
Keep an arbitrary pages[] subset (0-based, in the given order) in ONE fresh PDF. Same page-tree caveats as merge_pdfs (signatures/AcroForm/XMP dropped; boxes kept; URI links unless dropAnnotations). Encrypted sources: password; output unencrypted unless encrypt. Need several documents? Use split_pdf.
| Name | Required | Description | Default |
|---|---|---|---|
| pages | Yes | 0-based page indices to keep, in output order. Duplicates and out-of-range indices are rejected. | |
| encrypt | No | Re-encrypt the output (Standard Security Handler; AES-128 default or AES-256; RC4 never emitted). | |
| password | No | Password (user or owner) of an encrypted source. Never logged or echoed. | |
| pdfBase64 | Yes | Base64-encoded source PDF. Pass `password` for an encrypted source. | |
| outputMode | No | 'base64' (default) returns the PDF inline; 'file' writes it inside the PDFNATIVE_MCP_OUTPUT_DIR sandbox (SECURITY_VIOLATION when the sandbox is not configured). | base64 |
| outputPath | No | Required when outputMode='file'. Relative path inside the sandbox; must end with .pdf (no absolute paths, no '..'). | |
| dropAnnotations | No | When true, drop ALL annotations. Default keeps self-contained URI link annotations. | |
| maxOutputSizeBytes | No | Maximum size, in bytes, of the produced PDF. Defaults to 268435456 (256 MiB). |
Output Schema
| Name | Required | Description |
|---|---|---|
| mode | Yes | |
| summary | No | Tool-specific summary, when produced. |
| filePath | No | Sandboxed absolute path (file mode). |
| sizeBytes | Yes | |
| diagnostics | No | PDF/A diagnostics (when includeDiagnostics=true). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses material side effects: signatures/AcroForm/XMP are dropped, boxes are kept, URI annotations persist unless dropAnnotations, and output is unencrypted unless encrypt is supplied. These go well beyond the annotations and give the agent the real behavior of the tool. There is no contradiction with the idempotentHint/destructiveHint annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact, front-loaded, and avoids duplicating the 8-parameter schema. It leverages the sibling merge_pdfs to inherit known caveats instead of repeating them, and every sentence contributes either a constraint, a behavior, or an alternative.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given a rich input schema with 100% coverage and a declared output schema, the description fills the remaining practical gaps: output freshness, encryption behavior, page-tree side effects, and the route to split_pdf. An agent has enough information to select and invoke this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, and the description adds useful semantics on top: pages are order-preserving and 0-based, an encrypted source requires password, and output encryption happens only when encrypt is given. It does not restate every parameter, but the schema already documents those clearly.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description leads with a concrete action: keep an arbitrary 0-based pages[] subset in exactly one fresh PDF. It clearly distinguishes extract_pages from split_pdf and merge_pdfs and states a finite output scope. There is no ambiguity about the tool's object or effect.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly routes to split_pdf when multiple output documents are needed, and it references merge_pdfs for shared behavior. It also gives the encrypted-source conditional: provide password, include encrypt if encrypted output is wanted. These are concrete when-to-use vs when-not-to-use signals.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
extract_textExtract plain text from PDFARead-onlyIdempotent
Plain-text extraction: decodes Tj/TJ operands through each font's /ToUnicode CMap, /Encoding /Differences or base encoding and returns pages[] + fullText (positioned runs with includeRuns:true; pages selects 0-based pages). extractable is false only when a page decoded ENTIRELY to U+FFFD (a font with no usable mapping — expected for some subset fonts, not an error; extractableReason explains). Encrypted sources: pass password (PASSWORD_REQUIRED / PASSWORD_INVALID otherwise). Token-frugal: verbosity:'summary', fields:[…].
| Name | Required | Description | Default |
|---|---|---|---|
| pages | No | Optional 0-based page indices to extract. When omitted, every page is extracted. | |
| fields | No | Optional dot-path projection applied to the structured result (e.g. ['fullText'] or ['extractable']). Composes after verbosity. Unknown paths are omitted. | |
| password | No | Password (user or owner) of an encrypted source. Never logged or echoed. | |
| pdfBase64 | Yes | Base64-encoded PDF bytes. | |
| verbosity | No | Response verbosity. 'full' (default) returns the per-page pages[] array and fullText; 'summary' returns a token-frugal { pageCount, extractedPageCount, extractable, charCount } and drops the text payloads. | full |
| includeRuns | No | When true, each page also carries `runs[]` — positioned text-showing operations `{ text, x, y, fontSize, fontName }` in device space (content-stream order). Useful for layout-aware extraction; larger responses. | |
| maxTextLength | No | Hard cap on total extracted characters across all pages (memory bound for adversarial input). Default 16000000. Exceeding it fails with OUTPUT_TOO_LARGE. |
Output Schema
| Name | Required | Description |
|---|---|---|
| pages | No | |
| fullText | No | |
| charCount | No | summary only: length of fullText. |
| pageCount | No | |
| extractable | No | False when one or more requested pages produced text that is entirely U+FFFD replacement characters — a font with no usable /ToUnicode CMap or base encoding. Blank pages are still considered extractable. |
| extractableReason | No | Present when extractable is false: why no text could be decoded. |
| extractedPageCount | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only and idempotent, but the description adds crucial behavioral detail: the meaning of `extractable=false` as a legitimate condition explained by `extractableReason` rather than an error, the PASSWORD_REQUIRED/PASSWORD_INVALID error states, and the security note that passwords are never logged. It also explains the verbosity and runs mechanics, which are not expressed by annotations alone. No contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense and front-loaded with the core purpose. Every sentence carries meaningful operational or error-handling information, but the heavy use of parentheticals and one very long sentence make it slightly harder to parse. In comparison to a two-sentence standard, it is longer but justified by the complexity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity, an output schema exists and the description covers supported input behaviors, edge cases (font mapping failure), encryption, security, and response verbosity tuning. The only minor gap is not enumerating all error codes (like OUTPUT_TOO_LARGE), but that appears in the schema parameter docs. Overall, an agent can select and invoke the tool correctly based on the description plus schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema covers all 7 parameters (100%), but the description enriches key ones: it explains that `pages` uses zero-based indices, that `fields` is a dot-path projection, that `verbosity:'summary'` produces a token-frugal response, and that `includeRuns` returns positioned runs. These are semantic overlaps that add value beyond the schema without repeating it fully.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The first line 'Plain-text extraction' plus the technical mechanism ('decodes Tj/TJ operands through each font's /ToUnicode CMap...') states the exact operation and resource. It is clearly distinguished from siblings like extract_attachments and inspect_pdf, which perform different extraction/inspection tasks. The specific mention of pages, fullText, and includeRuns output confirms it is a text extraction tool with unique purpose.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear operational context: it explains when to use `password` for encrypted sources, when `extractable` is false, and how `includeRuns` gives layout-aware extraction. It implies this is the tool for extracting text from PDFs, but it does not explicitly state 'use this instead of X' or list exclusions. The guidance is concrete and contextual but lacks direct sibling differentiation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fill_formFill / flatten an existing AcroFormAIdempotent
Fill and/or flatten the AcroForm of an EXISTING PDF (add_form creates one) as an incremental update — prior signatures stay valid for their revision. values: fully-qualified name → string (array for multi-select), boolean or export state for checkbox/radio. flatten:true stamps appearances and drops the interactive layer (with no values = pure flatten). Unknown names → FORM_FIELD_NOT_FOUND unless onUnknownField:'ignore'; signature fields cannot be filled (FORM_UNSUPPORTED). Encrypted sources: password.
| Name | Required | Description | Default |
|---|---|---|---|
| values | No | Map of fully-qualified field name → value. Text/choice: a string (array of strings for multi-select listboxes). Checkbox/radio: a boolean or the export-state string. Omit (or pass {}) with flatten:true for a pure flatten. | |
| flatten | No | When true, stamp appearances into page content and remove the interactive fields after filling. | |
| password | No | Password (user or owner) of an encrypted source. Never logged or echoed. | |
| pdfBase64 | Yes | Base64-encoded source PDF containing the AcroForm to fill. Use read_form_fields first to discover field names. | |
| nonWinAnsi | No | Behaviour when a value contains non-WinAnsi characters (appearance font is Helvetica/WinAnsi). 'throw' (default) rejects it; 'needAppearances' writes the value and sets /NeedAppearances so the viewer regenerates the appearance. | throw |
| outputMode | No | 'base64' (default) returns the PDF inline; 'file' writes it inside the PDFNATIVE_MCP_OUTPUT_DIR sandbox (SECURITY_VIOLATION when the sandbox is not configured). | base64 |
| outputPath | No | Required when outputMode='file'. Relative path inside the sandbox; must end with .pdf. | |
| onUnknownField | No | Behaviour for a value key that matches no field. 'throw' (default) → FORM_FIELD_NOT_FOUND; 'ignore' skips it. | throw |
Output Schema
| Name | Required | Description |
|---|---|---|
| mode | Yes | |
| summary | No | Tool-specific summary, when produced. |
| filePath | No | Sandboxed absolute path (file mode). |
| sizeBytes | Yes | |
| diagnostics | No | PDF/A diagnostics (when includeDiagnostics=true). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond what annotations state, the description discloses several non-obvious behaviors: the update is incremental and preserves prior signatures, flattening stamps appearances and removes the interactive layer, pure flattening works with no values, unknown field names produce FORM_FIELD_OT_FOUND unless ignored, and signature fields are unsupported. This is exactly the kind of behavioral context that annotations cannot cover.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact yet information-dense, roughly five sentences cover target, sibling distinction, value syntax, flatten behavior, error modes, fir signature constraints, and encryption. Every sentence adds a factual constraint needed for safe invocation, and the most important scoping information is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 8 parameters, 1 requirement, nested values, and an output schema, the description plus rich parameter descriptions are complete enough. It covers the main failure modes and non-obvision side effects, while the output schema handles return value explanations, so nothing necessary for correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and every parameter including `values`, `flatten`, `onUnknownField`, and `password` has a detailed description already. The tool description provides a high-level summary of value types and flatten semantics, but it does not add meaningful information beyond what the input schema already supplies, so baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and target: 'fill and/or flatten the AcroForm of an EXISTING PDF'. It immediately distinguishes this from add_form by parenthetically identifying that sibling as the creation tool, so an agent can identify the exact resource and action.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly says this operates on an existing AcroForm and points to add_form ('add_form creates one') as the alternative. The schema's pdfBase6 explanation further tells the agent to call `read_form_fields` first to discover names, and the description says signature fields cannot be filled, making misuse conditions explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
generate_basic_pdfGenerate basic PDFAIdempotent
Multi-page PDF composed from ordered blocks: heading, paragraph, list, table, image (JPEG/PNG), link, toc (printed table of contents), barcode, svg, formField, chart, pageBreak, spacer — every block kind the engine offers, each sharing its body with the dedicated tool (add_table, embed_image, add_barcode, add_form, add_chart). DEFAULT for any document; use the dedicated tools only for a standalone artefact, add_attachment for embedded files and add_international_text for non-Latin scripts. pdfA + embedFonts:true for a valid PDF/A-1b/2b/2u/3b claim; outline / pageLabels / viewerPreferences / watermark for navigation and presentation; print, metadata, outputIntent, creationDate as on every document tool. The 'chart' block takes the same body as add_chart.
| Name | Required | Description | Default |
|---|---|---|---|
| pdfA | No | PDF/A level: pdfa1b (simple text+images), pdfa2b/pdfa2u (richer; 2u = Unicode mapping), pdfa3b (attachments / Factur-X). Pair with embedFonts=true for a valid claim. Exclusive with encryption. See docs/guides/PDFA.md. | |
| debug | No | Draw margin / block / cell guide rectangles (unmarked content — not for PDF/UA output). Geometry unchanged. Default false. | |
| No | Print production (ISO 32000-1 §14.11): page boxes, `bleed` shorthand (TrimBox = MediaBox inset), crop/registration marks outside the TrimBox, /UserUnit for large formats (PDF 1.7; not under pdfa1b). See docs/guides/PRINT.md. | ||
| title | Yes | Document title (rendered at top of page 1 and used as PDF metadata title). | |
| blocks | Yes | Ordered list of content blocks composing the document body. | |
| strict | No | Fail with PDF_A_COMPLIANCE_VIOLATION instead of producing a non-conformant PDF/A file (e.g. PDFA_NO_FONT_ENTRIES without embedFonts). Pair with embedFonts=true. | |
| encrypt | No | Encrypt at build time (AES-128 default / AES-256) and KEEP the AcroForm — unlike encrypt_pdf, which rebuilds the page tree. Exclusive with pdfA. Randomised output, never cached. | |
| margins | No | Margins in points, all four required (0–200). Default 45 / 36 / 35 / 36. | |
| outline | No | Document outline (bookmarks panel). Either 'auto' (derive a flat outline from heading blocks) or an explicit nested bookmark tree. | |
| compress | No | FlateDecode the streams (smaller file, different bytes; PDF/A unaffected, XMP stays plain). Default false. | |
| metadata | No | /Info (+ XMP under PDF/A): author, subject, keywords, /Trapped. | |
| pageSize | No | Portrait page preset (points): A4 595.28×841.89 (default), Letter 612×792, Legal 612×1008, A3 841.89×1190.55, Tabloid 792×1224. print.* boxes must fit it. | |
| normalize | No | Unicode normalization before shaping ('NFC' recommended for glyph coverage; NFD/NFKC/NFKD accepted). Omit = none. | |
| watermark | No | Optional semi-transparent watermark rendered centred on every page: `text` (e.g. 'DRAFT'), `image` (JPEG/PNG), or both combined. At least one of text / image is required. opacity < 1.0 (text or image, including the defaults) is rejected under pdfA='pdfa1b' (ISO 19005-1 forbids transparency). | |
| embedFonts | No | Embed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A claim (ISO 19005 §6.2.11.4.1) and for strict=true; adds ~0.3 MiB. | |
| footerText | No | Optional footer text rendered at the bottom of every page. | |
| outputMode | No | Either 'base64' (returns the PDF inline as a base64 string) or 'file' (writes to a path inside the configured PDFNATIVE_MCP_OUTPUT_DIR sandbox). | base64 |
| outputPath | No | Required when outputMode='file'. Relative path inside the sandbox; must end with .pdf. | |
| pageLabels | No | Page-label ranges (the visible page numbers in the viewer, e.g. roman front-matter then decimal body). startPage values must be unique and strictly increasing. | |
| creationDate | No | ISO-8601 instant for /CreationDate (+ XMP). Pin it for byte-identical output across calls (same host TZ); omitted = wall clock, so every call differs. | |
| outputIntent | No | Custom PDF/A OutputIntent: an RGB ICC profile + condition strings replacing the built-in sRGB intent (CMYK rejected). | |
| footerTemplate | No | Running footer on every page. Replaces the default footer: footerText is then ignored and page numbers appear only via {page}/{pages}. | |
| headerTemplate | No | Running header on every page (left / center / right zones); reserves 15 pt. | |
| viewerPreferences | No | Reader presentation hints (catalog /PageLayout, /PageMode, /ViewerPreferences). PDF/A-safe; all optional. | |
| includeDiagnostics | No | Return the PDF/A diagnostics raised while building as `diagnostics[]` (possibly empty). |
Output Schema
| Name | Required | Description |
|---|---|---|
| mode | Yes | |
| summary | No | Tool-specific summary, when produced. |
| filePath | No | Sandboxed absolute path (file mode). |
| sizeBytes | Yes | |
| diagnostics | No | PDF/A diagnostics (when includeDiagnostics=true). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare idempotentHint=true and destructiveHint=false, lowering the behavioral burden, and the description contradicts none of them. It adds meaningful context beyond the schema: every block shares its body with the dedicated sibling tool, pdfA requires embedFonts for a valid claim, and optional groups such as outline/pageLabels/viewerPreferences/watermark are folded into functional categories. It does not describe error/edge behavior, but the 100% output schema and annotations cover enough.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single dense paragraph with no filler; the core purpose and routing are front-loaded and the rest is a compact feature-group summary. The block enumeration makes it long, but every sentence earns its place, so it is tight rather than padded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
This is a high-complexity tool (25 parameters, deeply nested blocks, output schema present), and the description correctly delegates parameter detail to the schema while carrying what the schema cannot: the routing to siblings and the body-parity with dedicated tools. Minor non-obvious interplay such as a printed TOC depending on heading blocks is left to the schema, an acceptable and small gap for such a large surface.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the input schema itself describes every one of the 25 parameters with defaults, exclusivities and constraints, so the baseline of 3 applies. The description adds only cheap cross-block glue (body parity with dedicated tools, functional groups), which is useful but not required for parameter understanding.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with 'Multi-page PDF composed from ordered blocks' - a specific verb and resource plus the construction principle - and enumerates every block kind the engine offers. It also declares itself the 'DEFAULT' for any document, which clearly separates it from the block-specific sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit selection rule: 'DEFAULT for any document; use the dedicated tools only for a standalone artefact, add_attachment for embedded files and add_international_text for non-Latin scripts.' It names the exact alternatives and the conditions that call for them, so the routing is never left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
inspect_layoutInspect document layout (dry run)ARead-onlyIdempotent
Pagination preview WITHOUT generating a PDF: page count and where every block lands (page, x, top, width, height in points). Same blocks as generate_basic_pdf plus every input that moves a block (title, footerText, pdfA, normalize, embedFonts, pageSize, margins, headerTemplate, footerTemplate): pass what you will give generate_basic_pdf and the page count matches. Known engine gap: a 'toc' block is measured as 0 pt here (its real height depends on the headings), so documents with a toc may paginate one page later. Read-only, deterministic. Token-frugal: verbosity:'summary', fields:['totalPages'].
| Name | Required | Description | Default |
|---|---|---|---|
| pdfA | No | Tagged (PDF/A) layout mode, as you would pass it to generate_basic_pdf. PDF/A level: pdfa1b (simple text+images), pdfa2b/pdfa2u (richer; 2u = Unicode mapping), pdfa3b (attachments / Factur-X). Pair with embedFonts=true for a valid claim. Exclusive with encryption. See docs/guides/PDFA.md. | |
| title | Yes | Document title — reserves the title band on page 1 exactly as generate_basic_pdf does. | |
| blocks | Yes | Ordered list of content blocks composing the document body. | |
| fields | No | Optional dot-path projection applied to the structured result (e.g. ['totalPages'] or ['pages.blocks.type']). Composes after verbosity. Unknown paths are omitted. | |
| margins | No | Margins in points, all four required (0–200). Default 45 / 36 / 35 / 36. | |
| pageSize | No | Portrait page preset (points): A4 595.28×841.89 (default), Letter 612×792, Legal 612×1008, A3 841.89×1190.55, Tabloid 792×1224. print.* boxes must fit it. | |
| normalize | No | Unicode normalization before shaping ('NFC' recommended for glyph coverage; NFD/NFKC/NFKD accepted). Omit = none. | |
| verbosity | No | 'full' (default) or 'summary' (scalars only: pageWidth, pageHeight, totalPages, blockCount; pages[] and margins dropped). | full |
| embedFonts | No | Measure with the embedded Noto Sans Latin metrics instead of Helvetica — pass the same value you will give generate_basic_pdf. (Embed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A claim (ISO 19005 §6.2.11.4.1) and for strict=true; adds ~0.3 MiB.) | |
| footerText | No | Footer text as you would pass it to generate_basic_pdf (reserves the footer band). | |
| footerTemplate | No | Running footer on every page. Replaces the default footer: footerText is then ignored and page numbers appear only via {page}/{pages}. | |
| headerTemplate | No | Running header on every page (left / center / right zones); reserves 15 pt. |
Output Schema
| Name | Required | Description |
|---|---|---|
| pages | No | Per-page block placement, in render order. A table that spans pages appears once per slice. |
| margins | No | Page margins { top, right, bottom, left } in points. |
| pageWidth | No | Page width in points (595.28 = A4). |
| blockCount | No | summary only: number of placed blocks (table slices count once each). |
| pageHeight | No | Page height in points (841.89 = A4). |
| totalPages | No | Number of pages the blocks paginate into. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations (readOnlyHint, idempotentHint, destructiveHint) already cover safety, and the description adds meaningful behavior beyond them: it does NOT generate a PDF, it is deterministic, and it has a known engine gap for 'toc' blocks which can make pagination one page short. The token-frugal usage note ('verbosity:'summary', fields:['totalPages']') adds practical behavioral guidance. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Every sentence earns its place: the first sentence states the purpose plus output shape, the second defines the parameter semantics through the sibling relation, the third discloses a known limitation, and the fourth summarizes safety and efficiency. Front-loaded with the most critical fact (no PDF), no filler, and not bloated despite the large schema. The description is short but complete.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description is complete for a complex 12-parameter tool with 100% schema coverage and a present output schema. It covers the tool's role among siblings, its return semantics, its known edge case, and its performance/token profile. Nothing needed to invoke it correctly is missing — it distinguishes itself from the sibling, states contract with the parameters, and flags the only caveat in the measurement.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already has 100% description coverage, so the baseline is 3 even without extra description. The description adds cross-cutting semantic value by saying that all these parameters behave exactly as in generate_basic_pdf, meaning the schema descriptions can be interpreted consistently across tools. It also highlights the dependency: pass the same values to get a matching page count. It doesn't duplicate per-parameter schema detail but does add meaning about parameter usage intent.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Pagination preview WITHOUT generating a PDF', a specific verb-resource pairing that immediately distinguishes this tool from generate_basic_pdf. The purpose is further sharpened by listing the exact output: page count and where every block lands (page, x, top, width, height in points). It is far beyond a tautology and clearly names the sibling it is not.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly instructs the agent to pass the same inputs that would be given to generate_basic_pdf, including the full list of layout-affecting parameters. It names the sibling tool directly and clarifies the precondition/use case: validate pagination before generating a PDF. The line about a toc measured as 0 pt also tells the agent when the page count may be unreliable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
inspect_pdfInspect PDF metadataARead-onlyIdempotent
Read-only facts about a PDF: version, pageCount, encryption, pdfA claim (the claim, not its validity — use veraPDF for that), signatureCount, hasSignaturePlaceholder, attachments[], info; presence-gated dss / docTimestampCount / trapped; signatures:true lists every field (subFilter, isDocTimestamp, isPlaceholder, byteRange, vriKey); pages:true adds per-page sizes and boxes. check:[…] turns it into a CI assertion ('pdfa','signed','encrypted','placeholder','attachments','dss','docTimestamp','trapped') → checks (requested keys only) + checksPassed. Encrypted sources: pass password. Token-frugal: verbosity:'summary', fields:[…].
| Name | Required | Description | Default |
|---|---|---|---|
| check | No | CI assertions → checks (requested keys only) + checksPassed (all hold). 'signed' = a signature field with signed content exists (structural; validity is verify_pdf's job), 'placeholder' = an unsigned placeholder exists, 'dss' = /DSS present, 'docTimestamp' = a /DocTimeStamp exists, 'trapped' = /Info /Trapped set, 'annotations' = at least one page annotation exists. | |
| pages | No | When true, include per-page metadata in the response. | |
| fields | No | Optional dot-path projection applied to the structured result (e.g. ['pageCount','signatureCount']). Composes after verbosity. Unknown paths are omitted. | |
| password | No | Password (user or owner) of an encrypted source. Never logged or echoed. | |
| pdfBase64 | Yes | Base64-encoded PDF bytes to inspect. | |
| verbosity | No | 'full' (default) or 'summary' (scalars only: version, pageCount, encryption, pdfA, signatureCount, hasSignaturePlaceholder, attachmentCount, + docTimestampCount / trapped / checksPassed when present; arrays and dss dropped). | full |
| signatures | No | When true, include a signatures[] array describing every signature field (field name, SubFilter, document-timestamp flag, placeholder flag, ByteRange, /Contents length, /VRI key). Off by default to keep responses compact. | |
| annotations | No | When true, include an annotations[] array listing every page annotation (/Annots: links, text notes, highlights, shapes, widgets…) with its 0-based page, subtype, rect and, when present, contents (truncated to 200 chars), title, color, quadPoints and link url. Off by default to keep responses compact. |
Output Schema
| Name | Required | Description |
|---|---|---|
| dss | No | Document Security Store summary (ISO 32000-2 §12.8.4.3), present only when the catalog has a /DSS. |
| info | No | Document /Info dictionary entries decoded as strings. |
| pdfA | No | Detected PDF/A claim (e.g. '1B', '2B', '2U', '3B') from XMP metadata, or null when absent. |
| checks | No | One boolean per REQUESTED check (keys = the check[] you passed, nothing else). |
| perPage | No | |
| trapped | No | /Info /Trapped flag, present only when the document carries one. |
| version | No | PDF version (e.g. "1.7"). |
| pageCount | No | |
| encryption | No | |
| pageLabels | No | Logical page-numbering ranges from the /PageLabels number tree (ISO 32000-1 §12.4.2), or absent when the document has none. Each range gives the 0-based first page, numbering style, optional prefix and start value. |
| signatures | No | Signature fields (opt-in via the `signatures` input). Document timestamps are listed inline with isDocTimestamp=true. |
| annotations | No | Page annotations (opt-in via the `annotations` input), in page order then /Annots order. Only the keys the annotation actually carries are emitted. |
| attachments | No | Embedded files exposed via /Names → /EmbeddedFiles (PDF/A-3, Factur-X). |
| checksPassed | No | Present when check[] was supplied: true when every requested check holds. |
| encryptionInfo | No | Precise Standard Security Handler details (pdfnative v1.6.0), present only when the document is encrypted and was opened successfully. Objects served by the reader are already decrypted. |
| signatureCount | No | |
| annotationCount | No | Total number of page annotations (opt-in via the `annotations` input). |
| attachmentCount | No | summary only: number of embedded files. |
| docTimestampCount | No | Number of /DocTimeStamp signature fields, present only when at least one exists. |
| hasSignaturePlaceholder | No | True when at least one signature widget exists with empty /Contents — i.e. an unsigned placeholder awaiting `sign_pdf`. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and idempotentHint, and the description builds on this by adding richer behavioral detail: presence-gated fields, password handling for encrypted sources, check/checksPassed semantics, per-page output, and token-frugal verbosity. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense, front-loaded, and every sentence carries actionable information. It earns high marks for efficiency, though it reads as one long paragraph with many semicolon-separated ideas; a slightly clearer structure could make it a 5.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the 8 parameters, output schema, and complexity of the flags, description fully covers the important operational semantics: what is returned, how flags change shape, how checks behave, how passwords are used, and how token output can be reduced. The description does not need to restate the full schema because the schema describes the structured requests.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds genuine even lowering value beyond the schema: signatures:true means every field; pages:true means per-page sizes and boxes; check:list is a CI assertion returning checks + checksPassed; password is called out for encrypted sources; verbosity and fields are tied to token-frugality.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with "Read-only facts about a PDF" and enumerates concrete properties (version, pageCount, encryption, signatureCount, etc.), so the tool's purpose is immediately obvious. It also clearly distinguishes itself from validation by calling the pdfA result a claim, not its validity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly frames the tool as metadata inspection and even redirects pdfA validity checking to veraPDF, giving an explicit alternative. It does not exhaustively map all sibling alternatives—for instance, it does not explicitly say 'signature validity is verify_pdf's job' in the description—but the read-only framing makes the intended use clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
merge_pdfsMerge PDFsAIdempotent
Concatenate 2–50 PDFs (pdfsBase64[]) into one fresh, self-contained document. Page-tree rebuild: signatures and AcroForm are dropped, XMP (and thus a PDF/A claim) does not survive — re-declare PDF/A on the generating tools; page boxes and /UserUnit do survive; URI links kept unless dropAnnotations:true. Encrypted sources open with one password (PASSWORD_REQUIRED / PASSWORD_INVALID); output unencrypted unless encrypt. Guards: 256 MiB assembly (maxOutputSizeBytes), 50 MiB output (OUTPUT_TOO_LARGE).
| Name | Required | Description | Default |
|---|---|---|---|
| encrypt | No | Re-encrypt the output (Standard Security Handler; AES-128 default or AES-256; RC4 never emitted). | |
| password | No | Password applied to every encrypted source (pdfnative v1.6.0). Sources with an empty user password open without it. The merged output is unencrypted unless `encrypt` is set. | |
| outputMode | No | 'base64' (default) returns the PDF inline; 'file' writes it inside the PDFNATIVE_MCP_OUTPUT_DIR sandbox (SECURITY_VIOLATION when the sandbox is not configured). | base64 |
| outputPath | No | Required when outputMode='file'. Relative path inside the sandbox; must end with .pdf (no absolute paths, no '..'). | |
| pdfsBase64 | Yes | Base64-encoded source PDFs to concatenate, in order. 2–50 documents. Signatures and AcroForms are dropped (a page-tree edit invalidates them); encrypted PDFs are rejected. | |
| dropAnnotations | No | When true, drop ALL annotations. Default (false) keeps self-contained URI link annotations and drops cross-document/widget annotations. | |
| maxOutputSizeBytes | No | In-memory assembly guard (pdfnative maxOutputSize): the merge throws before materialising an object graph larger than this. Defaults to 268435456 (256 MiB). Note the emitted PDF is separately capped at 50 MiB by the output layer. |
Output Schema
| Name | Required | Description |
|---|---|---|
| mode | Yes | |
| summary | No | Tool-specific summary, when produced. |
| filePath | No | Sandboxed absolute path (file mode). |
| sizeBytes | Yes | |
| diagnostics | No | PDF/A diagnostics (when includeDiagnostics=true). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Given annotations only cover readOnly/destructive/idempotent hints, the description carries substantial behavioral detail: it explicitly states that signatures and AcroForms are dropped, XMP/PDF-A doesn't survive, page boxes and /UserUnit survive, URI links are kept conditionally, encryption is handled with an optional password, and size guards (256 MiB assembly, 50 MiB output). This goes far beyond what annotations alone reveal and precisely informs the agent of post-conditions and failure modes.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but well-structured: it opens with the core operation, then systematically discloses page-tree destructive effects, encryption handling, and size guards. Every sentence earns its place; no filler or restatement of the tool name. The front-loaded main operation ensures an agent gets the gist quickly, with edge cases and constraints following logically.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a fairly complex merge tool with nested `encrypt`/`permissions` objects, 7 parameters, and an existing output schema, the description provides all essential decision-relevant context: drop behavior, encryption behavior, output modes, guard limits, and error signals. Nothing an agent needs to safely invoke this tool is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, and the description reinforces the key parameter semantics beyond the schema: it explains the semantic meaning of `pdfsBase64` (concatenation order), the behavioral consequence on signatures/AcroForms, the conditional behavior of `dropAnnotations`, the assembly guard role of `maxOutputSizeBytes`, and the encryption output implications. This adds real value and clarifies edge cases the schema alone doesn't convey.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Concatenate'), a clear resource ('PDFs'), the input range (2–50), the output type (fresh, self-contained document), and explicitly differentiates behavior from sibling tools by detailing what does and doesn't survive the merge. It is unambiguous and distinctive even among many PDF-related sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit contextual behavior and even names the alternative behavior via 'dropAnnotations:true' and the `encrypt` option. It doesn't explicitly say 'use this tool when...' or name a sibling alternative, but the limit and error-code guards make the intended usage clear. The main gap is that it doesn't contrast with split_pdf/extract_pages for page-level operations, but the description sufficiently covers merge-specific use cases.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
prepare_signature_placeholderPrepare signature placeholderAIdempotent
New PDF carrying an unsigned /Sig placeholder for a LATER sign_pdf call. OPTIONAL — sign_pdf auto-injects one. Use it to size the placeholder (placeholderBytes for > 4096-bit keys, reserveTimestamp for an RFC 3161 token), to pin the widget page (pageIndex), to choose subFilter 'ETSI.CAdES.detached' (PAdES), or to ship the placeholder separately. signerName/reason/location/contactInfo/signingTime are frozen into /Sig here — sign_pdf cannot rewrite them later. NOTE: the unsigned file is not yet a conformant PDF/A (empty /Contents); it becomes one once signed. PDF/A, print, metadata and creationDate options as on every document tool.
| Name | Required | Description | Default |
|---|---|---|---|
| pdfA | No | PDF/A level: pdfa1b (simple text+images), pdfa2b/pdfa2u (richer; 2u = Unicode mapping), pdfa3b (attachments / Factur-X). Pair with embedFonts=true for a valid claim. Exclusive with encryption. See docs/guides/PDFA.md. The unsigned placeholder is NOT yet conformant (empty /Contents, ISO 19005-2 §6.4.3); it is once signed with sign_pdf profile:'pades'. | |
| debug | No | Draw margin / block / cell guide rectangles (unmarked content — not for PDF/UA output). Geometry unchanged. Default false. | |
| No | Print production (ISO 32000-1 §14.11): page boxes, `bleed` shorthand (TrimBox = MediaBox inset), crop/registration marks outside the TrimBox, /UserUnit for large formats (PDF 1.7; not under pdfa1b). See docs/guides/PRINT.md. | ||
| title | Yes | Document title. Used as the PDF metadata title and rendered at the top of page 1. | |
| blocks | No | Optional document body blocks rendered before the signature field. | |
| reason | No | Reason for signing (e.g. "Approved", "I agree to the terms"). | |
| strict | No | Fail with PDF_A_COMPLIANCE_VIOLATION instead of producing a non-conformant PDF/A file (e.g. PDFA_NO_FONT_ENTRIES without embedFonts). Pair with embedFonts=true. | |
| margins | No | Margins in points, all four required (0–200). Default 45 / 36 / 35 / 36. | |
| compress | No | FlateDecode the streams (smaller file, different bytes; PDF/A unaffected, XMP stays plain). Default false. | |
| location | No | Signing location (city / country). | |
| metadata | No | /Info (+ XMP under PDF/A): author, subject, keywords, /Trapped. | |
| pageSize | No | Portrait page preset (points): A4 595.28×841.89 (default), Letter 612×792, Legal 612×1008, A3 841.89×1190.55, Tabloid 792×1224. print.* boxes must fit it. | |
| fieldName | No | Optional AcroForm field name for the signature widget (default 'Signature1'). | |
| pageIndex | No | Zero-based page index the (invisible) widget attaches to (default 0). | |
| subFilter | No | Signature SubFilter baked into the /Sig dictionary (frozen at placeholder time). Use 'ETSI.CAdES.detached' for PAdES baseline signatures (sign_pdf profile='pades'). Default 'adbe.pkcs7.detached'. | |
| embedFonts | No | Embed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A claim (ISO 19005 §6.2.11.4.1) and for strict=true; adds ~0.3 MiB. | |
| outputMode | No | Either 'base64' (returns the PDF inline) or 'file' (writes to a sandboxed path inside PDFNATIVE_MCP_OUTPUT_DIR). | base64 |
| outputPath | No | Required when outputMode='file'. Relative path inside the sandbox; must end with .pdf. | |
| signerName | No | Name of the intended signer, embedded in the /Sig dictionary. | |
| contactInfo | No | Contact information for the signer. | |
| signingTime | No | /Sig /M — the claimed signing instant (ISO-8601), frozen into the placeholder dictionary. Omitted: the wall clock at placeholder time. Pin it (with creationDate) for byte-identical output across calls. | |
| creationDate | No | ISO-8601 instant for /CreationDate (+ XMP). Pin it for byte-identical output across calls (same host TZ); omitted = wall clock, so every call differs. | |
| outputIntent | No | Custom PDF/A OutputIntent: an RGB ICC profile + condition strings replacing the built-in sRGB intent (CMYK rejected). | |
| footerTemplate | No | Running footer on every page. Replaces the default footer: footerText is then ignored and page numbers appear only via {page}/{pages}. | |
| headerTemplate | No | Running header on every page (left / center / right zones); reserves 15 pt. | |
| placeholderBytes | No | Reserved bytes for the future CMS /Contents blob (default 16384; 24576 when reserveTimestamp=true). Increase only for >4096-bit RSA, long chains or large TSA tokens. | |
| reserveTimestamp | No | Reserve room for an RFC 3161 signature timestamp (sign_pdf timestamp=true): adds 8 KiB to the default placeholder size. Ignored when placeholderBytes is set explicitly. | |
| includeDiagnostics | No | Return the PDF/A diagnostics raised while building as `diagnostics[]` (possibly empty). |
Output Schema
| Name | Required | Description |
|---|---|---|
| mode | Yes | |
| summary | No | Tool-specific summary, when produced. |
| filePath | No | Sandboxed absolute path (file mode). |
| sizeBytes | Yes | |
| diagnostics | No | PDF/A diagnostics (when includeDiagnostics=true). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare idempotentHint=true and destructiveHint=false, so no contradiction. The description adds genuine behavior beyond those: the unsigned file is NOT yet a conformant PDF/A (empty /Contents) and becomes conformant only once signed; signature metadata is frozen at placeholder time and can't be rewritten by sign_pdf later. It also discloses the 'auto-inject' behavior of the sibling, which is a non-obvious interaction an agent needs to predict placeholder sizing.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description front-loads the core purpose in the first sentence, packs the key behavioral gap (PDF/A non-conformance) in one sentence, and closes with a short cross-tool invariant sentence. The parameter differentiation is compressed into one sentence with a parallel list. No filler, no repetition of schema content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With 28 parameters, 100% schema coverage, nested objects and an output schema present, the description's job is mostly to disambiguate the tool within the sibling family and call out cross-parameter interactions, both of which it does well. The gap: the description lacks a compact example payload and does not define a concrete 'how to produce a good placeholder for a >4096-bit key' recipe. The schema and output schema carry a large portion of the load, so this is adequate-but-not-complete for such a large tool signature.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so baseline is 3 per the rubric. The description earns an extra point by explaining the cross-parameter interaction: placeholderBytes default context, reserveTimestamp adds 8 KiB, and reserveTimestamp is ignored when placeholderBytes is set explicitly. It also links subFilter to the sign_pdf profile='pades' and pageIndex to a latent widget. This is real semantic value beyond the schema's per-field descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb-plus-resource statement: 'New PDF carrying an unsigned /Sig placeholder for a LATER sign_pdf call.' It clearly distinguishes the tool from sign_pdf by framing this as the placeholder preparation step, and it names the sibling sign_pdf explicitly in the first sentence. The scope (what gets frozen, what can be resized) is specific rather than vague.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description states when to use this tool and, crucially, when NOT to: 'OPTIONAL — sign_pdf auto-injects one.' The description enumerates concrete use cases (reserve space for >4096-bit keys, pin widget page, choose PAdES subFilter, ship placeholder separately). It also warns that signerName/reason/location/contactInfo/signingTime are frozen here and cannot be rewritten by sign_pdf later, giving the agent a clear decision rule between this tool and its sibling.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_form_fieldsRead AcroForm fieldsARead-onlyIdempotent
Read-only list of an existing PDF's AcroForm fields: fully-qualified name, type (text | checkbox | radio | dropdown | listbox | button | signature | unknown), value, flags (readOnly / required / multiline), options, widget placements. Call it BEFORE fill_form to learn the names. Encrypted sources: password. Token-frugal: verbosity:'summary' → { fieldCount }.
| Name | Required | Description | Default |
|---|---|---|---|
| fields | No | Optional dot-path projection applied to the structured result (e.g. ['fields.name','fields.type']). Composes after verbosity. Unknown paths are omitted. | |
| password | No | Password (user or owner) of an encrypted source. Never logged or echoed. | |
| pdfBase64 | Yes | Base64-encoded PDF bytes whose AcroForm fields should be enumerated. | |
| verbosity | No | Response verbosity. 'full' (default) returns the fields[] array; 'summary' returns a token-frugal { fieldCount } and drops the array. | full |
Output Schema
| Name | Required | Description |
|---|---|---|
| fields | No | |
| fieldCount | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark it as read-only and idempotent, and the description adds useful behavior details: password handling for encrypted PDFs and a token-frugal 'summary' response mode that returns only fieldCount. It does not disclose every edge case, but the core behavioral traits are well covered by the annotations and description together.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose is front-loaded, and every sentence earns a place. The long first sentence packs critical output attributes efficiently, followed by short, actionable notes about fill_form, password, and verbosity. There is no excess filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the annotations, the rich parameter schema, and the presence of an output schema, the description covers the remaining necessary context. It tells the agent when to call it, how to handle encrypted files, and how to customise response size, which is complete for a read-only enumeration tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
All four parameters already have thorough schema descriptions, so the baseline is met regardless. The description briefly mentions password and verbosity behavior, but those details are largely restating what is already in the schema. It adds little beyond what the input schema conveys.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states a read-only list of AcroForm fields and enumerates what is returned: name, type, value, flags, options, and widget placements. It also ties the operation to the sibling fill_form tool, so its role in the workflow is unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says 'Call it BEFORE fill_form to learn the names,' giving the agent a concrete, actionable use case and emphasizing that this tool is a prerequisite for fill_form. It does not mention when not to use it or provide other alternative tools, so it lacks full exclusionary guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sign_pdfSign PDF (RSA / ECDSA, PAdES)A
CMS / PAdES signature in ONE call: a missing /Sig placeholder is auto-injected (prepare_signature_placeholder is optional). Inputs: pdfBase64, algorithm (rsa-sha256/384/512, ecdsa-sha256 P-256), certDerBase64 (+ certChainDerBase64 intermediates) and the DER key (rsaKeyPkcs1DerBase64 for rsa-*, ecPrivateKeyDerBase64 or ecPrivateScalarHex for ECDSA; PEM is rejected with the openssl remedy). profile:'pades' (ETSI EN 319 142-1 baseline) is the right choice when add_ltv / timestamp_pdf follow; timestamp:true = PAdES B-T through the operator TSA (TSA_NOT_CONFIGURED otherwise, no network without it). signerName/reason/location/contactInfo/signingTime are baked into the placeholder THIS call injects (a pre-built placeholder keeps its own). Several unsigned placeholders → pass fieldName (PLACEHOLDER_AMBIGUOUS); allowMultiple:true + a new fieldName adds a further signature. Verify with verify_pdf.
| Name | Required | Description | Default |
|---|---|---|---|
| reason | No | /Sig /Reason — baked into the placeholder when this call injects it. | |
| profile | No | 'pkcs7' (default, adbe.pkcs7.detached) or 'pades' (ETSI EN 319 142-1 baseline; ETSI.CAdES.detached when the placeholder is injected here). Use 'pades' before timestamp / add_ltv / timestamp_pdf. | pkcs7 |
| location | No | /Sig /Location — baked into the placeholder when this call injects it. | |
| algorithm | Yes | Signature algorithm. 'rsa-sha384' / 'rsa-sha512' (pdfnative 1.7) upgrade the whole CMS digest chain. ECDSA only supports P-256 with SHA-256. | |
| fieldName | No | Name of the signature field to sign (required when several unsigned placeholders exist) and of the placeholder injected by this call. | |
| pdfBase64 | Yes | Base64-encoded PDF bytes. When the PDF already contains an unsigned /Sig placeholder it is signed in place; otherwise the placeholder is auto-injected (set autoInjectPlaceholder=false to opt out). | |
| timestamp | No | PAdES B-T: request an RFC 3161 signature timestamp from the operator-configured TSA (PDFNATIVE_MCP_TSA_URL). Fails with TSA_NOT_CONFIGURED when no TSA is configured — the server never contacts the network otherwise. | |
| outputMode | No | 'base64' (default) returns the PDF inline; 'file' writes it inside the PDFNATIVE_MCP_OUTPUT_DIR sandbox (SECURITY_VIOLATION when the sandbox is not configured). | base64 |
| outputPath | No | Required when outputMode='file'. Relative path inside the sandbox; must end with .pdf (no absolute paths, no '..'). | |
| signerName | No | /Sig /Name — baked into the placeholder when this call injects it. | |
| contactInfo | No | /Sig /ContactInfo — baked into the placeholder when this call injects it. | |
| signingTime | No | ISO-8601 signing instant → /Sig /M (only when THIS call injects the placeholder) and the CMS signing-time (pkcs7 profile). Default: now. Not trusted time — use timestamp:true for that. | |
| allowMultiple | No | Add a NEW signature next to existing (already signed) fields instead of signing the first placeholder. Requires fieldName. Each signature is an incremental revision; earlier signatures stay valid. | |
| certDerBase64 | Yes | Base64 of the signer X.509 certificate in DER form. Convert from PEM with: openssl x509 -in cert.pem -outform DER | base64 -w0 | |
| certChainDerBase64 | No | Optional intermediate CA certificates (DER base64) embedded in the CMS so verifiers and add_ltv can build the chain without fetching caIssuers. | |
| ecPrivateScalarHex | No | Hex-encoded P-256 private scalar `d` (exactly 64 lowercase or uppercase hex chars, no 0x prefix). Mutually exclusive with ecPrivateKeyDerBase64; either is accepted for ECDSA. | |
| rsaKeyPkcs1DerBase64 | No | Base64 of the RSA private key in DER form — PKCS#1 RSAPrivateKey (openssl rsa -in key.pem -outform DER -traditional | base64 -w0) or PKCS#8 PrivateKeyInfo (openssl pkey -in key.pem -outform DER | base64 -w0). NOT PEM. Required for the rsa-* algorithms. | |
| autoInjectPlaceholder | No | When true (default) and the input PDF has no /Sig widget, pdfnative.addSignaturePlaceholder is called before signing — enabling single-call signing of any PDF. | |
| ecPrivateKeyDerBase64 | No | Base64 of an ECDSA P-256 private key in SEC1 (RFC 5915) or PKCS#8 (RFC 5208) DER form. Convert from PEM with: openssl pkey -in key.pem -outform DER | base64 -w0 Mutually exclusive with ecPrivateScalarHex. |
Output Schema
| Name | Required | Description |
|---|---|---|
| mode | Yes | |
| summary | No | Tool-specific summary, when produced. |
| filePath | No | Sandboxed absolute path (file mode). |
| sizeBytes | Yes | |
| diagnostics | No | PDF/A diagnostics (when includeDiagnostics=true). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes well beyond the annotations (readOnlyHint=false, idempotentHint=false) by disclosing real behavioral consequences: auto-injection of a /Sig placeholder occurs in the same call, the injectable signature parameters are baked only into a newly injected placeholder, allowMultiple creates incremental revisions while previous signatures remain valid, and timestamp:true contacts the operator TSA while otherwise the server never touches the network. Known error states (TSA_NOT_CONFIGURED, PLACEHOLDER_AMBIGUOUS, SECURITY_VIOLATION) are explicitly named, giving the agent accurate failure expectations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but information-dense, and it is front-loaded with the core one-call capability before covering edge cases, error codes, and cross-tool relationships. Every sentence contributes either a usage constraint, an error condition, or a routing decision, though there is some redundancy with the schema's parameter-level descriptions that could be trimmed. For a 19-parameter signing tool, this length is justified.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's 19 parameters and intricate PDF-signing semantics, the description covers the full decision surface: placeholder injection, placeholder ambiguity, multi-signature behavior, time-stamping trust, key format acceptance, and sandbox/network failure modes. Since an output schema exists, not restating return values is acceptable, and the description even tells the agent where to verify the result. No critical operational detail is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the structured schema already documents every parameter's meaning, formats, mutual exclusivity, and openssl conversion remedies. The description adds orchestration-level context (how algorithm selects the corresponding key parameter, how the injected placeholder interprets signerName/reason/location/contactInfo/signingTime) rather than new per-parameter semantics. This matches the baseline of 3 for a fully covered schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The first sentence names a specific verb (sign), a specific resource (PDF), and the two format families (CMS / PAdES), immediately distinguishing it from sibling utilities like add_ltv, timestamp_pdf, and verify_pdf. It also clarifies the one-call advantage over prepare_signature_placeholder, making the tool's identity unmistakable. The title reinforces the same scope without adding confusion.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when profile:'pades' should be chosen ('right choice when add_ltv / timestamp_pdf follow'), when fieldName is required ('Several unsigned placeholders → pass fieldName'), and when allowMultiple applies ('adds a further signature'). It also names the verification counterpart ('Verify with verify_pdf') and explicitly rejects PEM with a remedy. Conditional usage rules are given with concrete triggers, so no selection is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
split_pdfSplit PDF into rangesAIdempotent
Split one PDF into several documents, one per ranges[] entry ({ start, end? }, 0-based inclusive; end defaults to start). Multi-output result: base64 mode returns one embedded resource per part; file mode writes indexed siblings ('out.pdf' → 'out-1.pdf', 'out-2.pdf', …). Same page-tree caveats as merge_pdfs (signatures/AcroForm/XMP dropped; boxes kept). Encrypted sources: password. Need ONE document from a page subset? Use extract_pages.
| Name | Required | Description | Default |
|---|---|---|---|
| ranges | Yes | Page ranges to extract, one output PDF per range. 0-based, inclusive; `end` defaults to `start` (a single page). | |
| encrypt | No | Re-encrypt the output (Standard Security Handler; AES-128 default or AES-256; RC4 never emitted). Applied to every produced range. | |
| password | No | Password (user or owner) of an encrypted source. Never logged or echoed. | |
| pdfBase64 | Yes | Base64-encoded source PDF. Pass `password` for an encrypted source. | |
| outputMode | No | 'base64' (default) returns the PDF inline; 'file' writes it inside the PDFNATIVE_MCP_OUTPUT_DIR sandbox (SECURITY_VIOLATION when the sandbox is not configured). | base64 |
| outputPath | No | Base output path (file mode). Each PDF is written to an indexed sibling: 'out.pdf' → 'out-1.pdf', 'out-2.pdf', … | |
| dropAnnotations | No | When true, drop ALL annotations. Default keeps self-contained URI link annotations. | |
| maxOutputSizeBytes | No | Maximum size, in bytes, of each produced PDF. Defaults to 268435456 (256 MiB). |
Output Schema
| Name | Required | Description |
|---|---|---|
| mode | Yes | |
| count | Yes | |
| parts | Yes | |
| totalBytes | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses multi-output behavior, output naming conventions in file mode, what happens in base64 mode, and important PDF caveats (signatures/AcroForm/XMP dropped; boxes kept). It also notes encrypted sources using password. These go beyond the annotations, which only describe readOnly/idemptency/destructive hints, and would meaningfully affect ai-agent expectations for the result.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and information-dense: four sentences that front-load the core operation, then deliver range semantics, output behavior, page-tree caveats, encrypted-source handling, and the sibling alternative. Every sentence earns its place and no extraneous content is present.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 8 parameters, nested objects, and an output schema, the description covers the defining split behavior, the two output modes with concrete file naming, the main transformation caveats, and the canonical alternative. Given the rich schema and output schema, nothing essential is missing for selecting or invoking it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the input schema already documents every parameter including the zero-based inclusive nature of ranges, outputPath semantics, password behavior, and outputMode defaults. The description reinforces the central `ranges[]` semantics and output naming but does not add meaningful meaning beyond what the schema already provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states a specific verb and resource: 'Split one PDF into several documents, one per ranges[] entry'. It also distinguishes itself from extract_pages by explicitly naming the alternative for extracting a single document, so an agent can tell the tools apart at the description level.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Includes explicit routing guidance: 'Need ONE document from a page subset? Use extract_pages.' It also references merge_pdfs for shared page-tree caveats, helping the agent understand this tool is best when multiple ranges are wanted, and points to password handling for encrypted sources. Clear enough to select this tool over the alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
timestamp_pdfAdd a document timestamp (PAdES B-LTA)A
PAdES B-LTA: append an RFC 3161 document timestamp (/DocTimeStamp, ETSI.RFC3161) over the whole document. Ladder step 4 after add_ltv; re-run before the TSA certificate expires. fieldName omitted → DocTimeStamp1, 2, …; a fieldName colliding with a signed field fails. Uses the OPERATOR TSA (PDFNATIVE_MCP_TSA_URL; TSA_NOT_CONFIGURED otherwise, no network without it). The token's status, imprint and nonce are checked before embedding (its own signature is verified by verify_pdf). Unencrypted PDFs only.
| Name | Required | Description | Default |
|---|---|---|---|
| fieldName | No | Signature field name for the timestamp. Omit it to get 'DocTimeStamp1', 'DocTimeStamp2', … auto-suffixed on each re-timestamp; an explicit name that collides with an existing signed field fails. | |
| pdfBase64 | Yes | Base64-encoded PDF (unencrypted). Typically already signed (+ add_ltv) — a document timestamp on an unsigned PDF is allowed but proves only existence at that time. | |
| outputMode | No | 'base64' (default) returns the PDF inline; 'file' writes it inside the PDFNATIVE_MCP_OUTPUT_DIR sandbox (SECURITY_VIOLATION when the sandbox is not configured). | base64 |
| outputPath | No | Relative path inside PDFNATIVE_MCP_OUTPUT_DIR (required when outputMode='file'). | |
| placeholderBytes | No | Room reserved for the TimeStampToken (default 12288). Raise it for TSAs that return large certificate chains. |
Output Schema
| Name | Required | Description |
|---|---|---|
| mode | Yes | |
| summary | No | Tool-specific summary, when produced. |
| filePath | No | Sandboxed absolute path (file mode). |
| sizeBytes | Yes | |
| diagnostics | No | PDF/A diagnostics (when includeDiagnostics=true). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Even though annotations mark readOnlyHint=false, the description goes far beyond that: it discloses exact behavior (append over whole document, omitted fieldName auto-naming, TSA dependency, status/imprint/nonce checks, sandbox output behavior, and the SECURITY_VIOLATION risk when the sandbox is unconfigured). It does not contradict the provided annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Every sentence in the description is dense and purposeful: scope, procedure, failure mode, configuration dependency, security checks, and constraints are all covered without fluff. The content is compact yet complete for a five-parameter tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool complexity, the annotations, the 100% schema description coverage, and the presence of an output schema, the tool is both internally complete. It covers when to use, ordering relative, constraints, configuration environment, output modes, and security-specific behavior.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds meaningful semantics for fieldName: omitted values produce DocTimeStamp1, 2, ... and colliding with a signed field fails. It also adds value by tying placeholderBytes to TSA certificate chain size in the frontend conceptual model.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('append an RFC 3161 document timestamp') and names the precise resource (/DocTimeStamp, ETSI.RFC3161). It clearly separates this from sibling tools by calling it 'Ladder step 4 after add_ltv' and mentioning verify_pdf for verifying its signature.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit usage context: it must be run after add_ltv, should be re-run before the TSA certificate expires, cannot be applied to encrypted PDFs, and fieldName collisions with signed fields fail. It also states the condition under which the tool is unavailable (TSA_NOT_CONFIGURED).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_metadataUpdate document metadataA
Rewrite /Info (title, author, subject, keywords) of an EXISTING PDF as an incremental update; XMP stays in sync on PDF/A documents; /ModDate is refreshed (pin modDate for reproducible bytes on the same host TZ). Earlier revisions and signatures stay byte-identical — the new revision is unsigned (sign_pdf / timestamp_pdf again if needed). Encrypted sources → ENCRYPTED_SOURCE. For metadata at generation time use the metadata option of the document tools.
| Name | Required | Description | Default |
|---|---|---|---|
| title | No | New /Info /Title (mirrored to XMP dc:title when the document carries XMP). | |
| author | No | New /Info /Author (XMP dc:creator). | |
| modDate | No | ISO-8601 modification instant for /ModDate and xmp:ModifyDate. Defaults to now; pin it for reproducible output. | |
| subject | No | New /Info /Subject (XMP dc:description). | |
| keywords | No | New /Info /Keywords (XMP pdf:Keywords). | |
| pdfBase64 | Yes | Base64-encoded PDF to update (unencrypted). | |
| outputMode | No | 'base64' (default) returns the PDF inline; 'file' writes it inside the PDFNATIVE_MCP_OUTPUT_DIR sandbox (SECURITY_VIOLATION when the sandbox is not configured). | base64 |
| outputPath | No | Relative path inside PDFNATIVE_MCP_OUTPUT_DIR (required when outputMode='file'). |
Output Schema
| Name | Required | Description |
|---|---|---|
| mode | Yes | |
| summary | No | Tool-specific summary, when produced. |
| filePath | No | Sandboxed absolute path (file mode). |
| sizeBytes | Yes | |
| diagnostics | No | PDF/A diagnostics (when includeDiagnostics=true). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
It discloses several behavioral traits: the update is incremental, XMP stays in sync on PDF/A documents, /ModDate is refreshed, earlier revisions and signatures remain byte-identical, and the new revision is unsigned. These details go well beyond the annotations and explain consequences that materially affect an agent's subsequent decisions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four purposeful sentences stretch the agent exactly what it needs: what the tool does, what else is affected, what is preserved, and when not to use it. There is almost no redundant phrasing, and the most important facts are front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity, the 100% parameter coverage, and the presence of an output schema, the description covers the remaining operational concerns: encrypted-source failure, signature preservation, XMP behavior, and reproducibility. An agent has enough context to select and invoke this tool correctly and to plan follow-up actions such as re-signing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already describes all 8 parameters with 100% coverage, so the description does not need to restate them. The only added parameter-level guidance is the modDate pinning tip ('same host TZ'), which the schema also partially captures. This adds marginal value, so the baseline score of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Rewrite /Info (title, author, subject, keywords) of an EXISTING PDF as an incremental update.' It makes the scope precise and distinguishes itself from metadata files placed at document generation time by pointing to the `metadata` option of document tools, so an agent can separate this from `generate_basic_pdf` and similar.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The last sentence is an explicit routing rule: 'For metadata at generation time use the `metadata` option of the document tools.' The description also gives conditional guidance for encrypted sources and for whether a signature needs to be reapplied (sign_pdf / timestamp_pdf again), which tells an agent what to do before and after this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
validate_pdfValidate PDF/UA structureARead-onlyIdempotent
Read-only PDF/UA-1 (ISO 14289-1) structural gate for Tagged PDF: /MarkInfo /Marked, /StructTreeRoot (+ /ParentTree), XMP /Metadata, /Lang, per-page MCID uniqueness. Result { standard:'pdf-ua-1', valid, errors[], warnings[], summary }. Fast and structural only — NOT a reference validator (veraPDF): fonts, colour and rendering are not checked. Unparsable input → PDF_PARSE_FAILED. Generate tagged input with pdfA (e.g. 'pdfa2u') first.
| Name | Required | Description | Default |
|---|---|---|---|
| fields | No | Optional dot-path projection applied to the structured result (e.g. ['valid']). Composes after verbosity. Unknown paths are omitted. | |
| pdfBase64 | Yes | Base64-encoded PDF bytes to validate for PDF/UA (ISO 14289-1) structural conformance. | |
| verbosity | No | Response verbosity. 'full' (default) returns errors[] and warnings[]; 'summary' returns a token-frugal verdict { standard, valid, errorCount, warningCount, summary } and drops the message arrays. | full |
Output Schema
| Name | Required | Description |
|---|---|---|
| valid | No | True when no blocking structural violations were found. |
| errors | No | Blocking PDF/UA conformance violations. Empty when valid is true. |
| summary | No | Human-readable one-line summary of the result. |
| standard | No | Conformance standard checked (ISO 14289-1). |
| warnings | No | Non-blocking best-practice recommendations. |
| errorCount | No | summary only: number of errors. |
| warningCount | No | summary only: number of warnings. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare read-only, idempotent, non-destructive, and limited open-world semantics; the description adds specific behavioral detail by listing the exact inspection points (MarkInfo, StructTreeRoot, ParentTree, XMP Metadata, Lang, MCID uniqueness). It also discloses the denfinite error condition: 'Unparsable input → PDF_PARSE_FAILED', and clearly states scope limits and fonts/color/rendering are not checked. This goes well beyond what the annotations provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact yet information-dense with every sentence earning its place: it states the exact checks, the result shape, the error behavior, the limitations, and the intended workflow. It reads well and front-loads the most important 'structural gate' phrase.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With annotations, a fully documented input schema, and an output-like result shape in the description, the agent has everything needed to call this tool correctly. The description also mentions 'Generate tagged input with pdfa first' to tie the surrounding workflow, and gives the precise response shape 'valid, errors[], warnings[], summary'.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already documents all three parameters descriptions: pdfBase64 with base64 details, verbosity with default/enum, and fields with projection behavior. Schema description coverage is 100%, so the baseline applies. The tool description adds no additional parameter-level meaning, but none is necessary.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the operation ('validate'), the resource ('PDF/UA structure'), and the exact standard ('PDF/UA-1 ISO 14289-1'), and enumerates the structural checks it performs. It distinguishes itself from a reference validator: 'NOT a reference validator (veraPDF): fonts, colour and rendering are not checked'. However, it does not explicitly differentiate itself from sibling tools like verify_pdf or inspect_pdf by name.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit when-to-use guidance: 'Read-only PDF/UA-1 structural gate' and 'fast and structural only'. It also states a clear exclusion: 'NOT a reference validator:' fonts, colour and rendering are not checked, so the agent knows when not to rely on it. The workflow hint 'Generate tagged PDF with pdfA first' provides a useful conditional prerequisite.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
verify_pdfVerify PDF signaturesARead-onlyIdempotent
Read-only verification of every signature: ByteRange digest vs CMS messageDigest (integrity), CMS signatureValue vs the embedded signer certificate (RSA-SHA256/384/512, ECDSA P-256), chain trust when trustedRootsDerBase64 is given ('self-signed' | 'unverified' | 'trusted' otherwise). /DocTimeStamp entries are verified as RFC 3161 tokens and count in allValid like any signature. Result: { allValid, signatureCount, summary, signatures:[{ valid, integrity, signerSubject, signingTime, chainTrust, errors[] }] }. ltv:true adds the PAdES view: per-signature profile, timestamp, revocation (read from embedded /DSS only — responder signatures are not re-verified) and ltvLevel B-B / B-T / B-LT / B-LTA with explicit caveats. Token-frugal: verbosity:'summary', fields:['allValid'].
| Name | Required | Description | Default |
|---|---|---|---|
| ltv | No | Add the PAdES view: per signature profile, timestamp, revocation (embedded /DSS only), ltvLevel (B-B / B-T / B-LT / B-LTA); document-level dss, ltvLevel, caveats. | |
| fields | No | Optional dot-path projection applied to the structured result (e.g. ['allValid'] or ['signatures.valid']). Composes after verbosity. Unknown paths are omitted. | |
| password | No | Password (user or owner) of an encrypted source. Never logged or echoed. | |
| pdfBase64 | Yes | Base64-encoded PDF bytes to verify. | |
| verbosity | No | Response verbosity. 'full' (default) returns the per-signature signatures[] array; 'summary' returns a token-frugal verdict { signatureCount, allValid, invalid, summary } (+ ltvLevel when ltv:true) and drops signatures[], dss and caveats. | full |
| trustedRootsDerBase64 | No | Optional list of base64-encoded X.509 root certificates (DER). When supplied, each signer certificate is validated against these roots; otherwise chainTrust is reported as self-signed or unverified. |
Output Schema
| Name | Required | Description |
|---|---|---|
| dss | No | ltv only. Document Security Store summary, or null when the catalog has no /DSS. |
| caveats | No | ltv only. Fixed statements about what the LTV evaluation does not cover. |
| invalid | No | summary only: number of invalid signatures. |
| summary | No | |
| allValid | No | true when the document carries at least one signature and every entry of signatures[] — CMS signatures and /DocTimeStamp tokens alike — is valid (integrity + signature check + chain trust when trustedRootsDerBase64 is given). A tampered document timestamp fails the verdict; a sound one never does. |
| ltvLevel | No | ltv only. Minimum level across non-timestamp signatures ('B-B' when there are none). |
| signatures | No | |
| signatureCount | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes beyond the readOnlyHint and idempotentHint annotations by explaining exactly what is verified, how chainTrust is determined, how /DocTimeStamp is treated, and what ltv:true does. It also includes important caveats such as embedded /DSS-only revocation data and the fact that responder signatures are not re-verified. This gives the agent a strong model of the tool's behavior before invoking it.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but well structured, front-loading the core verification purpose and then layering optional modes. Every sentence adds meaningful information, and the structured result shape and token-frugal guidance are presented in compact, scannable form.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity, the input schema, annotations, and output schema, the description covers the essential semantic, behavioral, and output-critical details. It explains verification scope, trust behavior, timestamp handling, LTV caveats, and result shapes well enough for an agent to decide whether to call it and what to expect.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already documents all six parameters with high coverage, so the baseline is solid. The description adds genuine semantic value by explaining the effect of trustedRootsDerBase64, the LTV behavior tied to ltv:true, and the token-frugal interaction between verbosity and fields.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a precise operation: read-only verification of every PDF signature, including integrity, signature value, chain trust, timestamps, and PAdES LTV behavior. It clearly distinguishes the tool's scope from generic PDF validation by enumerating specific verification mechanics and output fields.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description makes the tool's purpose and behavior easy to infer: it is for signature-specific verification, with optional LTV analysis. However, it does not explicitly tell the agent when to choose verify_pdf over sibling tools like validate_pdf or inspect_pdf, nor does it state any exclusions. Usage context is implied rather than directly described.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
27 tool updates
- Changed
add_attachment19 fields changed- added
Input schema / properties / compressAdded value: +{ + "description": "FlateDecode the streams (smaller file, different bytes; PDF/A unaffected, XMP stays plain). Default false.", + "type": "boolean" +} - added
Input schema / properties / creationDateAdded value: +{ + "description": "ISO-8601 instant for /CreationDate (+ XMP). Pin it for byte-identical output across calls (same host TZ); omitted = wall clock, so every call differs.", + "format": "date-time", + "type": "string" +} - added
Input schema / properties / debugAdded value: +{ + "description": "Draw margin / block / cell guide rectangles (unmarked content — not for PDF/UA output). Geometry unchanged. Default false.", + "type": "boolean" +} - added
Input schema / properties / embedFontsAdded value: +{ + "default": false, + "description": "Embed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A claim (ISO 19005 §6.2.11.4.1) and for strict=true; adds ~0.3 MiB.", + "type": "boolean" +} - added
Input schema / properties / footerTemplateAdded value: +{ + "additionalProperties": false, + "description": "Running footer on every page. Replaces the default footer: footerText is then ignored and page numbers appear only via {page}/{pages}.", + "properties": { + "center": { + "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).", + "maxLength": 200, + "type": "string" + }, + "color": { + "description": "Hex colour.", + "pattern": "^#[0-9a-fA-F]{6}$", + "type": "string" + }, + "fontSize": { + "description": "Default 7.", + "maximum": 14, + "minimum": 6, + "type": "number" + }, + "left": { + "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).", + "maxLength": 200, + "type": "string" + }, + "right": { + "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).", + "maxLength": 200, + "type": "string" + } + }, + "type": "object" +} - added
Input schema / properties / headerTemplateAdded value: +{ + "additionalProperties": false, + "description": "Running header on every page (left / center / right zones); reserves 15 pt.", + "properties": { + "center": { + "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).", + "maxLength": 200, + "type": "string" + }, + "color": { + "description": "Hex colour.", + "pattern": "^#[0-9a-fA-F]{6}$", + "type": "string" + }, + "fontSize": { + "description": "Default 7.", + "maximum": 14, + "minimum": 6, + "type": "number" + }, + "left": { + "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).", + "maxLength": 200, + "type": "string" + }, + "right": { + "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).", + "maxLength": 200, + "type": "string" + } + }, + "type": "object" +} - added
Input schema / properties / includeDiagnosticsAdded value: +{ + "default": false, + "description": "Return the PDF/A diagnostics raised while building as `diagnostics[]` (possibly empty).", + "type": "boolean" +} - added
Input schema / properties / marginsAdded value: +{ + "additionalProperties": false, + "description": "Margins in points, all four required (0–200). Default 45 / 36 / 35 / 36.", + "properties": { + "bottom": { + "maximum": 200, + "minimum": 0, + "type": "number" + }, + "left": { + "maximum": 200, + "minimum": 0, + "type": "number" + }, + "right": { + "maximum": 200, + "minimum": 0, + "type": "number" + }, + "top": { + "maximum": 200, + "minimum": 0, + "type": "number" + } + }, + "required": [ + "top", + "right", + "bottom", + "left" + ], + "type": "object" +} - added
Input schema / properties / metadataAdded value: +{ + "additionalProperties": false, + "description": "/Info (+ XMP under PDF/A): author, subject, keywords, /Trapped.", + "properties": { + "author": { + "maxLength": 500, + "type": "string" + }, + "keywords": { + "maxLength": 1000, + "type": "string" + }, + "subject": { + "maxLength": 1000, + "type": "string" + }, + "trapped": { + "description": "/Trapped print flag.", + "enum": [ + "True", + "False", + "Unknown" + ], + "type": "string" + } + }, + "type": "object" +} - added
Input schema / properties / outputIntentAdded value: +{ + "additionalProperties": false, + "description": "Custom PDF/A OutputIntent: an RGB ICC profile + condition strings replacing the built-in sRGB intent (CMYK rejected).", + "properties": { + "iccProfileBase64": { + "description": "ICC profile bytes, base64 (RGB, ≤ 8 MiB).", + "maxLength": 11000000, + "minLength": 1, + "type": "string" + }, + "info": { + "maxLength": 500, + "type": "string" + }, + "outputCondition": { + "maxLength": 200, + "type": "string" + }, + "outputConditionIdentifier": { + "description": "e.g. \"sRGB IEC61966-2.1\".", + "maxLength": 200, + "minLength": 1, + "type": "string" + }, + "registryName": { + "description": "Default \"http://www.color.org\".", + "maxLength": 200, + "type": "string" + } + }, + "required": [ + "iccProfileBase64", + "outputConditionIdentifier" + ], + "type": "object" +} - added
Input schema / properties / outputMode / descriptionAdded value: +"'base64' (default) returns the PDF inline; 'file' writes it inside the PDFNATIVE_MCP_OUTPUT_DIR sandbox (SECURITY_VIOLATION when the sandbox is not configured)." - added
Input schema / properties / outputPath / descriptionAdded value: +"Required when outputMode='file'. Relative path inside the sandbox; must end with .pdf (no absolute paths, no '..')." - added
Input schema / properties / pageSizeAdded value: +{ + "description": "Portrait page preset (points): A4 595.28×841.89 (default), Letter 612×792, Legal 612×1008, A3 841.89×1190.55, Tabloid 792×1224. print.* boxes must fit it.", + "enum": [ + "A4", + "Letter", + "Legal", + "A3", + "Tabloid" + ], + "type": "string" +} - added
Input schema / properties / printAdded value: +{ + "additionalProperties": false, + "description": "Print production (ISO 32000-1 §14.11): page boxes, `bleed` shorthand (TrimBox = MediaBox inset), crop/registration marks outside the TrimBox, /UserUnit for large formats (PDF 1.7; not under pdfa1b). See docs/guides/PRINT.md.", + "properties": { + "artBox": { + "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.", + "items": { + "type": "number" + }, + "maxItems": 4, + "minItems": 4, + "type": "array" + }, + "bleed": { + "description": "Bleed in points (8.5 = 3 mm); sets TrimBox = MediaBox inset. Exclusive with trimBox.", + "exclusiveMinimum": 0, + "maximum": 200, + "type": "number" + }, + "bleedBox": { + "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.", + "items": { + "type": "number" + }, + "maxItems": 4, + "minItems": 4, + "type": "array" + }, + "cropBox": { + "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.", + "items": { + "type": "number" + }, + "maxItems": 4, + "minItems": 4, + "type": "array" + }, + "marks": { + "description": "Printer's marks (needs bleed or trimBox): true for defaults, or an object.", + "oneOf": [ + { + "type": "boolean" + }, + { + "additionalProperties": false, + "properties": { + "crop": { + "description": "Corner crop (trim) marks. Default true.", + "type": "boolean" + }, + "length": { + "description": "Mark length in points. Default 14.", + "maximum": 100, + "minimum": 1, + "type": "number" + }, + "offset": { + "description": "Gap between TrimBox and marks in points. Default 5.", + "maximum": 100, + "minimum": 0, + "type": "number" + }, + "registration": { + "description": "Edge-midpoint registration targets. Default true.", + "type": "boolean" + }, + "weight": { + "description": "Stroke width in points. Default 0.25.", + "maximum": 5, + "minimum": 0.05, + "type": "number" + } + }, + "type": "object" + } + ] + }, + "trimBox": { + "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.", + "items": { + "type": "number" + }, + "maxItems": 4, + "minItems": 4, + "type": "array" + }, + "userUnit": { + "description": "/UserUnit (multiples of 1/72 in) for pages over 14400 pt. Rejected under pdfa1b.", + "maximum": 75000, + "minimum": 1, + "type": "number" + } + }, + "type": "object" +} - added
Input schema / properties / strictAdded value: +{ + "default": false, + "description": "Fail with PDF_A_COMPLIANCE_VIOLATION instead of producing a non-conformant PDF/A file (e.g. PDFA_NO_FONT_ENTRIES without embedFonts). Pair with embedFonts=true.", + "type": "boolean" +} - changed
Output schema / descriptionPrevious value: -"Structured result of a PDF-producing tool. In base64 mode the PDF bytes are delivered out-of-band as an embedded `resource` content block (data: URI), NOT duplicated here, to keep responses token-frugal. In file mode `filePath` is the sandboxed absolute path."New value: +"Result of a PDF-producing tool. base64 mode: the PDF arrives as an embedded `resource` content block (not duplicated here); file mode: `filePath`." - added
Output schema / properties / diagnosticsAdded value: +{ + "description": "PDF/A diagnostics (when includeDiagnostics=true).", + "items": { + "additionalProperties": false, + "properties": { + "code": { + "type": "string" + }, + "message": { + "type": "string" + }, + "severity": { + "enum": [ + "warning" + ], + "type": "string" + } + }, + "required": [ + "code", + "message", + "severity" + ], + "type": "object" + }, + "type": "array" +} - changed
Output schema / properties / filePath / descriptionPrevious value: -"Absolute sandboxed file path (when mode='file')."New value: +"Sandboxed absolute path (file mode)." - added
Output schema / properties / summaryAdded value: +{ + "additionalProperties": true, + "description": "Tool-specific summary, when produced.", + "type": "object" +}
- Changed
add_barcode21 fields changed- added
Input schema / properties / compressAdded value: +{ + "description": "FlateDecode the streams (smaller file, different bytes; PDF/A unaffected, XMP stays plain). Default false.", + "type": "boolean" +} - added
Input schema / properties / creationDateAdded value: +{ + "description": "ISO-8601 instant for /CreationDate (+ XMP). Pin it for byte-identical output across calls (same host TZ); omitted = wall clock, so every call differs.", + "format": "date-time", + "type": "string" +} - added
Input schema / properties / debugAdded value: +{ + "description": "Draw margin / block / cell guide rectangles (unmarked content — not for PDF/UA output). Geometry unchanged. Default false.", + "type": "boolean" +} - added
Input schema / properties / embedFontsAdded value: +{ + "default": false, + "description": "Embed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A claim (ISO 19005 §6.2.11.4.1) and for strict=true; adds ~0.3 MiB.", + "type": "boolean" +} - added
Input schema / properties / encryptAdded value: +{ + "additionalProperties": false, + "description": "Encrypt at build time (AES-128 default / AES-256) and KEEP the AcroForm — unlike encrypt_pdf, which rebuilds the page tree. Exclusive with pdfA. Randomised output, never cached.", + "properties": { + "algorithm": { + "default": "aes128", + "description": "aes128 (V4/R4, widest compatibility) or aes256 (V5/R6).", + "enum": [ + "aes128", + "aes256" + ], + "type": "string" + }, + "ownerPassword": { + "description": "Owner password (full access).", + "maxLength": 4096, + "minLength": 1, + "type": "string" + }, + "permissions": { + "additionalProperties": false, + "description": "Permission flags; each defaults to allowed.", + "properties": { + "copy": { + "type": "boolean" + }, + "extractText": { + "type": "boolean" + }, + "modify": { + "type": "boolean" + }, + "print": { + "type": "boolean" + } + }, + "type": "object" + }, + "userPassword": { + "description": "Open password; omitted/empty = opens without a prompt.", + "maxLength": 4096, + "type": "string" + } + }, + "required": [ + "ownerPassword" + ], + "type": "object" +} - added
Input schema / properties / footerTemplateAdded value: +{ + "additionalProperties": false, + "description": "Running footer on every page. Replaces the default footer: footerText is then ignored and page numbers appear only via {page}/{pages}.", + "properties": { + "center": { + "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).", + "maxLength": 200, + "type": "string" + }, + "color": { + "description": "Hex colour.", + "pattern": "^#[0-9a-fA-F]{6}$", + "type": "string" + }, + "fontSize": { + "description": "Default 7.", + "maximum": 14, + "minimum": 6, + "type": "number" + }, + "left": { + "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).", + "maxLength": 200, + "type": "string" + }, + "right": { + "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).", + "maxLength": 200, + "type": "string" + } + }, + "type": "object" +} - added
Input schema / properties / headerTemplateAdded value: +{ + "additionalProperties": false, + "description": "Running header on every page (left / center / right zones); reserves 15 pt.", + "properties": { + "center": { + "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).", + "maxLength": 200, + "type": "string" + }, + "color": { + "description": "Hex colour.", + "pattern": "^#[0-9a-fA-F]{6}$", + "type": "string" + }, + "fontSize": { + "description": "Default 7.", + "maximum": 14, + "minimum": 6, + "type": "number" + }, + "left": { + "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).", + "maxLength": 200, + "type": "string" + }, + "right": { + "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).", + "maxLength": 200, + "type": "string" + } + }, + "type": "object" +} - added
Input schema / properties / includeDiagnosticsAdded value: +{ + "default": false, + "description": "Return the PDF/A diagnostics raised while building as `diagnostics[]` (possibly empty).", + "type": "boolean" +} - added
Input schema / properties / marginsAdded value: +{ + "additionalProperties": false, + "description": "Margins in points, all four required (0–200). Default 45 / 36 / 35 / 36.", + "properties": { + "bottom": { + "maximum": 200, + "minimum": 0, + "type": "number" + }, + "left": { + "maximum": 200, + "minimum": 0, + "type": "number" + }, + "right": { + "maximum": 200, + "minimum": 0, + "type": "number" + }, + "top": { + "maximum": 200, + "minimum": 0, + "type": "number" + } + }, + "required": [ + "top", + "right", + "bottom", + "left" + ], + "type": "object" +} - added
Input schema / properties / metadataAdded value: +{ + "additionalProperties": false, + "description": "/Info (+ XMP under PDF/A): author, subject, keywords, /Trapped.", + "properties": { + "author": { + "maxLength": 500, + "type": "string" + }, + "keywords": { + "maxLength": 1000, + "type": "string" + }, + "subject": { + "maxLength": 1000, + "type": "string" + }, + "trapped": { + "description": "/Trapped print flag.", + "enum": [ + "True", + "False", + "Unknown" + ], + "type": "string" + } + }, + "type": "object" +} - added
Input schema / properties / outputIntentAdded value: +{ + "additionalProperties": false, + "description": "Custom PDF/A OutputIntent: an RGB ICC profile + condition strings replacing the built-in sRGB intent (CMYK rejected).", + "properties": { + "iccProfileBase64": { + "description": "ICC profile bytes, base64 (RGB, ≤ 8 MiB).", + "maxLength": 11000000, + "minLength": 1, + "type": "string" + }, + "info": { + "maxLength": 500, + "type": "string" + }, + "outputCondition": { + "maxLength": 200, + "type": "string" + }, + "outputConditionIdentifier": { + "description": "e.g. \"sRGB IEC61966-2.1\".", + "maxLength": 200, + "minLength": 1, + "type": "string" + }, + "registryName": { + "description": "Default \"http://www.color.org\".", + "maxLength": 200, + "type": "string" + } + }, + "required": [ + "iccProfileBase64", + "outputConditionIdentifier" + ], + "type": "object" +} - added
Input schema / properties / outputMode / descriptionAdded value: +"'base64' (default) returns the PDF inline; 'file' writes it inside the PDFNATIVE_MCP_OUTPUT_DIR sandbox (SECURITY_VIOLATION when the sandbox is not configured)." - added
Input schema / properties / outputPath / descriptionAdded value: +"Required when outputMode='file'. Relative path inside the sandbox; must end with .pdf (no absolute paths, no '..')." - added
Input schema / properties / pageSizeAdded value: +{ + "description": "Portrait page preset (points): A4 595.28×841.89 (default), Letter 612×792, Legal 612×1008, A3 841.89×1190.55, Tabloid 792×1224. print.* boxes must fit it.", + "enum": [ + "A4", + "Letter", + "Legal", + "A3", + "Tabloid" + ], + "type": "string" +} - changed
Input schema / properties / pdfA / descriptionPrevious value: -"Optional PDF/A conformance level (powered by pdfnative v1.2). Use 'pdfa1b' for archival of simple text+images, 'pdfa2b'/'pdfa2u' for richer content (2u guarantees Unicode mapping), 'pdfa3b' when embedding source attachments (Factur-X / ZUGFeRD). Mutually exclusive with PDF encryption. See docs/guides/PDFA.md."New value: +"PDF/A level: pdfa1b (simple text+images), pdfa2b/pdfa2u (richer; 2u = Unicode mapping), pdfa3b (attachments / Factur-X). Pair with embedFonts=true for a valid claim. Exclusive with encryption. See docs/guides/PDFA.md." - added
Input schema / properties / printAdded value: +{ + "additionalProperties": false, + "description": "Print production (ISO 32000-1 §14.11): page boxes, `bleed` shorthand (TrimBox = MediaBox inset), crop/registration marks outside the TrimBox, /UserUnit for large formats (PDF 1.7; not under pdfa1b). See docs/guides/PRINT.md.", + "properties": { + "artBox": { + "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.", + "items": { + "type": "number" + }, + "maxItems": 4, + "minItems": 4, + "type": "array" + }, + "bleed": { + "description": "Bleed in points (8.5 = 3 mm); sets TrimBox = MediaBox inset. Exclusive with trimBox.", + "exclusiveMinimum": 0, + "maximum": 200, + "type": "number" + }, + "bleedBox": { + "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.", + "items": { + "type": "number" + }, + "maxItems": 4, + "minItems": 4, + "type": "array" + }, + "cropBox": { + "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.", + "items": { + "type": "number" + }, + "maxItems": 4, + "minItems": 4, + "type": "array" + }, + "marks": { + "description": "Printer's marks (needs bleed or trimBox): true for defaults, or an object.", + "oneOf": [ + { + "type": "boolean" + }, + { + "additionalProperties": false, + "properties": { + "crop": { + "description": "Corner crop (trim) marks. Default true.", + "type": "boolean" + }, + "length": { + "description": "Mark length in points. Default 14.", + "maximum": 100, + "minimum": 1, + "type": "number" + }, + "offset": { + "description": "Gap between TrimBox and marks in points. Default 5.", + "maximum": 100, + "minimum": 0, + "type": "number" + }, + "registration": { + "description": "Edge-midpoint registration targets. Default true.", + "type": "boolean" + }, + "weight": { + "description": "Stroke width in points. Default 0.25.", + "maximum": 5, + "minimum": 0.05, + "type": "number" + } + }, + "type": "object" + } + ] + }, + "trimBox": { + "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.", + "items": { + "type": "number" + }, + "maxItems": 4, + "minItems": 4, + "type": "array" + }, + "userUnit": { + "description": "/UserUnit (multiples of 1/72 in) for pages over 14400 pt. Rejected under pdfa1b.", + "maximum": 75000, + "minimum": 1, + "type": "number" + } + }, + "type": "object" +} - added
Input schema / properties / strictAdded value: +{ + "default": false, + "description": "Fail with PDF_A_COMPLIANCE_VIOLATION instead of producing a non-conformant PDF/A file (e.g. PDFA_NO_FONT_ENTRIES without embedFonts). Pair with embedFonts=true.", + "type": "boolean" +} - changed
Output schema / descriptionPrevious value: -"Structured result of a PDF-producing tool. In base64 mode the PDF bytes are delivered out-of-band as an embedded `resource` content block (data: URI), NOT duplicated here, to keep responses token-frugal. In file mode `filePath` is the sandboxed absolute path."New value: +"Result of a PDF-producing tool. base64 mode: the PDF arrives as an embedded `resource` content block (not duplicated here); file mode: `filePath`." - added
Output schema / properties / diagnosticsAdded value: +{ + "description": "PDF/A diagnostics (when includeDiagnostics=true).", + "items": { + "additionalProperties": false, + "properties": { + "code": { + "type": "string" + }, + "message": { + "type": "string" + }, + "severity": { + "enum": [ + "warning" + ], + "type": "string" + } + }, + "required": [ + "code", + "message", + "severity" + ], + "type": "object" + }, + "type": "array" +} - changed
Output schema / properties / filePath / descriptionPrevious value: -"Absolute sandboxed file path (when mode='file')."New value: +"Sandboxed absolute path (file mode)." - added
Output schema / properties / summaryAdded value: +{ + "additionalProperties": true, + "description": "Tool-specific summary, when produced.", + "type": "object" +}
- Changed
add_chart29 fields changed- added
Input schema / properties / axis / properties / scaleAdded value: +{ + "description": "Value-axis scale. 'log' requires strictly positive values and is not available for stacked charts.", + "enum": [ + "linear", + "log" + ], + "type": "string" +} - added
Input schema / properties / axis2Added value: +{ + "additionalProperties": false, + "description": "Secondary RIGHT value axis (drawn only when a series sets yAxis:'right').", + "properties": { + "scale": { + "enum": [ + "linear", + "log" + ], + "type": "string" + }, + "ticks": { + "maximum": 20, + "minimum": 2, + "type": "integer" + }, + "yMax": { + "type": "number" + }, + "yMin": { + "type": "number" + } + }, + "type": "object" +} - changed
Input schema / properties / chartType / descriptionPrevious value: -"Chart kind. 'pie'/'donut' use exactly one series; 'bar'/'barH'/'line' support multiple series."New value: +"Chart kind. 'pie'/'donut' use exactly one series; 'bar'/'barH'/'stackedBar'/'stackedBarH'/'line'/'area'/'scatter' support multiple series. 'scatter' requires xValues on every series and a positional xAxis.type ('linear' or 'time')." - changed
Input schema / properties / chartType / enumPrevious value: -[ - "bar", - "barH", - "line", - "pie", - "donut" -]New value: +[ + "bar", + "barH", + "stackedBar", + "stackedBarH", + "line", + "area", + "scatter", + "pie", + "donut" +] - added
Input schema / properties / compressAdded value: +{ + "description": "FlateDecode the streams (smaller file, different bytes; PDF/A unaffected, XMP stays plain). Default false.", + "type": "boolean" +} - added
Input schema / properties / creationDateAdded value: +{ + "description": "ISO-8601 instant for /CreationDate (+ XMP). Pin it for byte-identical output across calls (same host TZ); omitted = wall clock, so every call differs.", + "format": "date-time", + "type": "string" +} - added
Input schema / properties / dataLabelsAdded value: +{ + "description": "Per-point value labels: true for defaults, or an object to format them.", + "oneOf": [ + { + "type": "boolean" + }, + { + "additionalProperties": false, + "properties": { + "decimals": { + "maximum": 6, + "minimum": 0, + "type": "integer" + }, + "prefix": { + "maxLength": 16, + "type": "string" + }, + "suffix": { + "maxLength": 16, + "type": "string" + } + }, + "type": "object" + } + ] +} - added
Input schema / properties / debugAdded value: +{ + "description": "Draw margin / block / cell guide rectangles (unmarked content — not for PDF/UA output). Geometry unchanged. Default false.", + "type": "boolean" +} - added
Input schema / properties / embedFontsAdded value: +{ + "default": false, + "description": "Embed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A claim (ISO 19005 §6.2.11.4.1) and for strict=true; adds ~0.3 MiB.", + "type": "boolean" +} - added
Input schema / properties / encryptAdded value: +{ + "additionalProperties": false, + "description": "Encrypt at build time (AES-128 default / AES-256) and KEEP the AcroForm — unlike encrypt_pdf, which rebuilds the page tree. Exclusive with pdfA. Randomised output, never cached.", + "properties": { + "algorithm": { + "default": "aes128", + "description": "aes128 (V4/R4, widest compatibility) or aes256 (V5/R6).", + "enum": [ + "aes128", + "aes256" + ], + "type": "string" + }, + "ownerPassword": { + "description": "Owner password (full access).", + "maxLength": 4096, + "minLength": 1, + "type": "string" + }, + "permissions": { + "additionalProperties": false, + "description": "Permission flags; each defaults to allowed.", + "properties": { + "copy": { + "type": "boolean" + }, + "extractText": { + "type": "boolean" + }, + "modify": { + "type": "boolean" + }, + "print": { + "type": "boolean" + } + }, + "type": "object" + }, + "userPassword": { + "description": "Open password; omitted/empty = opens without a prompt.", + "maxLength": 4096, + "type": "string" + } + }, + "required": [ + "ownerPassword" + ], + "type": "object" +} - added
Input schema / properties / footerTemplateAdded value: +{ + "additionalProperties": false, + "description": "Running footer on every page. Replaces the default footer: footerText is then ignored and page numbers appear only via {page}/{pages}.", + "properties": { + "center": { + "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).", + "maxLength": 200, + "type": "string" + }, + "color": { + "description": "Hex colour.", + "pattern": "^#[0-9a-fA-F]{6}$", + "type": "string" + }, + "fontSize": { + "description": "Default 7.", + "maximum": 14, + "minimum": 6, + "type": "number" + }, + "left": { + "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).", + "maxLength": 200, + "type": "string" + }, + "right": { + "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).", + "maxLength": 200, + "type": "string" + } + }, + "type": "object" +} - added
Input schema / properties / headerTemplateAdded value: +{ + "additionalProperties": false, + "description": "Running header on every page (left / center / right zones); reserves 15 pt.", + "properties": { + "center": { + "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).", + "maxLength": 200, + "type": "string" + }, + "color": { + "description": "Hex colour.", + "pattern": "^#[0-9a-fA-F]{6}$", + "type": "string" + }, + "fontSize": { + "description": "Default 7.", + "maximum": 14, + "minimum": 6, + "type": "number" + }, + "left": { + "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).", + "maxLength": 200, + "type": "string" + }, + "right": { + "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).", + "maxLength": 200, + "type": "string" + } + }, + "type": "object" +} - added
Input schema / properties / includeDiagnosticsAdded value: +{ + "default": false, + "description": "Return the PDF/A diagnostics raised while building as `diagnostics[]` (possibly empty).", + "type": "boolean" +} - added
Input schema / properties / labelRotationAdded value: +{ + "description": "Rotate category labels counter-clockwise by this many degrees (disables the automatic stride).", + "maximum": 90, + "minimum": 0, + "type": "number" +} - added
Input schema / properties / labelStrideAdded value: +{ + "description": "Draw every Nth category label. Default: automatic (measured non-overlap); 1 draws every label.", + "maximum": 1000, + "minimum": 1, + "type": "integer" +} - added
Input schema / properties / marginsAdded value: +{ + "additionalProperties": false, + "description": "Margins in points, all four required (0–200). Default 45 / 36 / 35 / 36.", + "properties": { + "bottom": { + "maximum": 200, + "minimum": 0, + "type": "number" + }, + "left": { + "maximum": 200, + "minimum": 0, + "type": "number" + }, + "right": { + "maximum": 200, + "minimum": 0, + "type": "number" + }, + "top": { + "maximum": 200, + "minimum": 0, + "type": "number" + } + }, + "required": [ + "top", + "right", + "bottom", + "left" + ], + "type": "object" +} - added
Input schema / properties / metadataAdded value: +{ + "additionalProperties": false, + "description": "/Info (+ XMP under PDF/A): author, subject, keywords, /Trapped.", + "properties": { + "author": { + "maxLength": 500, + "type": "string" + }, + "keywords": { + "maxLength": 1000, + "type": "string" + }, + "subject": { + "maxLength": 1000, + "type": "string" + }, + "trapped": { + "description": "/Trapped print flag.", + "enum": [ + "True", + "False", + "Unknown" + ], + "type": "string" + } + }, + "type": "object" +} - added
Input schema / properties / outputIntentAdded value: +{ + "additionalProperties": false, + "description": "Custom PDF/A OutputIntent: an RGB ICC profile + condition strings replacing the built-in sRGB intent (CMYK rejected).", + "properties": { + "iccProfileBase64": { + "description": "ICC profile bytes, base64 (RGB, ≤ 8 MiB).", + "maxLength": 11000000, + "minLength": 1, + "type": "string" + }, + "info": { + "maxLength": 500, + "type": "string" + }, + "outputCondition": { + "maxLength": 200, + "type": "string" + }, + "outputConditionIdentifier": { + "description": "e.g. \"sRGB IEC61966-2.1\".", + "maxLength": 200, + "minLength": 1, + "type": "string" + }, + "registryName": { + "description": "Default \"http://www.color.org\".", + "maxLength": 200, + "type": "string" + } + }, + "required": [ + "iccProfileBase64", + "outputConditionIdentifier" + ], + "type": "object" +} - added
Input schema / properties / pageSizeAdded value: +{ + "description": "Portrait page preset (points): A4 595.28×841.89 (default), Letter 612×792, Legal 612×1008, A3 841.89×1190.55, Tabloid 792×1224. print.* boxes must fit it.", + "enum": [ + "A4", + "Letter", + "Legal", + "A3", + "Tabloid" + ], + "type": "string" +} - changed
Input schema / properties / pdfA / descriptionPrevious value: -"Optional PDF/A conformance level (powered by pdfnative v1.2). Use 'pdfa1b' for archival of simple text+images, 'pdfa2b'/'pdfa2u' for richer content (2u guarantees Unicode mapping), 'pdfa3b' when embedding source attachments (Factur-X / ZUGFeRD). Mutually exclusive with PDF encryption. See docs/guides/PDFA.md."New value: +"PDF/A level: pdfa1b (simple text+images), pdfa2b/pdfa2u (richer; 2u = Unicode mapping), pdfa3b (attachments / Factur-X). Pair with embedFonts=true for a valid claim. Exclusive with encryption. See docs/guides/PDFA.md." - added
Input schema / properties / printAdded value: +{ + "additionalProperties": false, + "description": "Print production (ISO 32000-1 §14.11): page boxes, `bleed` shorthand (TrimBox = MediaBox inset), crop/registration marks outside the TrimBox, /UserUnit for large formats (PDF 1.7; not under pdfa1b). See docs/guides/PRINT.md.", + "properties": { + "artBox": { + "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.", + "items": { + "type": "number" + }, + "maxItems": 4, + "minItems": 4, + "type": "array" + }, + "bleed": { + "description": "Bleed in points (8.5 = 3 mm); sets TrimBox = MediaBox inset. Exclusive with trimBox.", + "exclusiveMinimum": 0, + "maximum": 200, + "type": "number" + }, + "bleedBox": { + "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.", + "items": { + "type": "number" + }, + "maxItems": 4, + "minItems": 4, + "type": "array" + }, + "cropBox": { + "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.", + "items": { + "type": "number" + }, + "maxItems": 4, + "minItems": 4, + "type": "array" + }, + "marks": { + "description": "Printer's marks (needs bleed or trimBox): true for defaults, or an object.", + "oneOf": [ + { + "type": "boolean" + }, + { + "additionalProperties": false, + "properties": { + "crop": { + "description": "Corner crop (trim) marks. Default true.", + "type": "boolean" + }, + "length": { + "description": "Mark length in points. Default 14.", + "maximum": 100, + "minimum": 1, + "type": "number" + }, + "offset": { + "description": "Gap between TrimBox and marks in points. Default 5.", + "maximum": 100, + "minimum": 0, + "type": "number" + }, + "registration": { + "description": "Edge-midpoint registration targets. Default true.", + "type": "boolean" + }, + "weight": { + "description": "Stroke width in points. Default 0.25.", + "maximum": 5, + "minimum": 0.05, + "type": "number" + } + }, + "type": "object" + } + ] + }, + "trimBox": { + "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.", + "items": { + "type": "number" + }, + "maxItems": 4, + "minItems": 4, + "type": "array" + }, + "userUnit": { + "description": "/UserUnit (multiples of 1/72 in) for pages over 14400 pt. Rejected under pdfa1b.", + "maximum": 75000, + "minimum": 1, + "type": "number" + } + }, + "type": "object" +} - added
Input schema / properties / series / items / properties / xValuesAdded value: +{ + "description": "Per-point x positions (same length as values) for scatter charts and for line/area charts with xAxis.type 'linear' or 'time'.", + "items": { + "description": "Positional x value: a number (linear axis) or an ISO-8601 date / epoch milliseconds (time axis).", + "maxLength": 64, + "type": [ + "number", + "string" + ] + }, + "maxItems": 1000, + "minItems": 1, + "type": "array" +} - added
Input schema / properties / series / items / properties / yAxisAdded value: +{ + "description": "Bind the series to the left (default) or the secondary right value axis (cartesian charts only; configure its range with 'axis2').", + "enum": [ + "left", + "right" + ], + "type": "string" +} - added
Input schema / properties / strictAdded value: +{ + "default": false, + "description": "Fail with PDF_A_COMPLIANCE_VIOLATION instead of producing a non-conformant PDF/A file (e.g. PDFA_NO_FONT_ENTRIES without embedFonts). Pair with embedFonts=true.", + "type": "boolean" +} - added
Input schema / properties / xAxisAdded value: +{ + "additionalProperties": false, + "description": "Horizontal axis. 'category' (default) positions points by index; 'linear' / 'time' position them by series xValues (line/area/scatter only). Time ticks are UTC-deterministic.", + "properties": { + "grid": { + "description": "Draw vertical gridlines.", + "type": "boolean" + }, + "max": { + "description": "Axis maximum (number, or ISO-8601 / epoch ms for time axes).", + "maxLength": 64, + "type": [ + "number", + "string" + ] + }, + "min": { + "description": "Axis minimum (number, or ISO-8601 / epoch ms for time axes).", + "maxLength": 64, + "type": [ + "number", + "string" + ] + }, + "ticks": { + "maximum": 20, + "minimum": 2, + "type": "integer" + }, + "type": { + "enum": [ + "category", + "linear", + "time" + ], + "type": "string" + } + }, + "type": "object" +} - changed
Output schema / descriptionPrevious value: -"Structured result of a PDF-producing tool. In base64 mode the PDF bytes are delivered out-of-band as an embedded `resource` content block (data: URI), NOT duplicated here, to keep responses token-frugal. In file mode `filePath` is the sandboxed absolute path."New value: +"Result of a PDF-producing tool. base64 mode: the PDF arrives as an embedded `resource` content block (not duplicated here); file mode: `filePath`." - added
Output schema / properties / diagnosticsAdded value: +{ + "description": "PDF/A diagnostics (when includeDiagnostics=true).", + "items": { + "additionalProperties": false, + "properties": { + "code": { + "type": "string" + }, + "message": { + "type": "string" + }, + "severity": { + "enum": [ + "warning" + ], + "type": "string" + } + }, + "required": [ + "code", + "message", + "severity" + ], + "type": "object" + }, + "type": "array" +} - changed
Output schema / properties / filePath / descriptionPrevious value: -"Absolute sandboxed file path (when mode='file')."New value: +"Sandboxed absolute path (file mode)." - added
Output schema / properties / summaryAdded value: +{ + "additionalProperties": true, + "description": "Tool-specific summary, when produced.", + "type": "object" +}
- Changed
add_form27 fields changed- added
Input schema / properties / compressAdded value: +{ + "description": "FlateDecode the streams (smaller file, different bytes; PDF/A unaffected, XMP stays plain). Default false.", + "type": "boolean" +} - added
Input schema / properties / creationDateAdded value: +{ + "description": "ISO-8601 instant for /CreationDate (+ XMP). Pin it for byte-identical output across calls (same host TZ); omitted = wall clock, so every call differs.", + "format": "date-time", + "type": "string" +} - added
Input schema / properties / debugAdded value: +{ + "description": "Draw margin / block / cell guide rectangles (unmarked content — not for PDF/UA output). Geometry unchanged. Default false.", + "type": "boolean" +} - added
Input schema / properties / embedFontsAdded value: +{ + "default": false, + "description": "Embed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A claim (ISO 19005 §6.2.11.4.1) and for strict=true; adds ~0.3 MiB.", + "type": "boolean" +} - added
Input schema / properties / encryptAdded value: +{ + "additionalProperties": false, + "description": "Encrypt at build time (AES-128 default / AES-256) and KEEP the AcroForm — unlike encrypt_pdf, which rebuilds the page tree. Exclusive with pdfA. Randomised output, never cached.", + "properties": { + "algorithm": { + "default": "aes128", + "description": "aes128 (V4/R4, widest compatibility) or aes256 (V5/R6).", + "enum": [ + "aes128", + "aes256" + ], + "type": "string" + }, + "ownerPassword": { + "description": "Owner password (full access).", + "maxLength": 4096, + "minLength": 1, + "type": "string" + }, + "permissions": { + "additionalProperties": false, + "description": "Permission flags; each defaults to allowed.", + "properties": { + "copy": { + "type": "boolean" + }, + "extractText": { + "type": "boolean" + }, + "modify": { + "type": "boolean" + }, + "print": { + "type": "boolean" + } + }, + "type": "object" + }, + "userPassword": { + "description": "Open password; omitted/empty = opens without a prompt.", + "maxLength": 4096, + "type": "string" + } + }, + "required": [ + "ownerPassword" + ], + "type": "object" +} - changed
Input schema / properties / fields / items / properties / checked / descriptionPrevious value: -"Initial checked state for checkbox fields."New value: +"Initial checked state for checkbox / radio fields." - changed
Input schema / properties / fields / items / properties / fieldType / descriptionPrevious value: -"Type of form control to render."New value: +"Type of form control to render. Radio fields sharing a name form one radio group." - changed
Input schema / properties / fields / items / properties / fieldType / enumPrevious value: -[ - "text", - "textarea", - "checkbox", - "radio", - "dropdown" -]New value: +[ + "text", + "textarea", + "checkbox", + "radio", + "dropdown", + "listbox" +] - changed
Input schema / properties / fields / items / properties / height / descriptionPrevious value: -"Field height in points (optional)."New value: +"Field height in points (default depends on the type)." - changed
Input schema / properties / fields / items / properties / name / descriptionPrevious value: -"Unique field name used as the PDF annotation identifier."New value: +"Unique field name used as the PDF annotation identifier (/T)." - changed
Input schema / properties / fields / items / properties / options / descriptionPrevious value: -"Choices for dropdown or radio fields."New value: +"Choices for dropdown, listbox or radio fields." - added
Input schema / properties / fields / items / properties / placeholderAdded value: +{ + "description": "Hint text shown while the field is empty.", + "maxLength": 200, + "type": "string" +} - changed
Input schema / properties / fields / items / properties / width / descriptionPrevious value: -"Field width in points (optional)."New value: +"Field width in points (default: full content width)." - added
Input schema / properties / footerTemplateAdded value: +{ + "additionalProperties": false, + "description": "Running footer on every page. Replaces the default footer: footerText is then ignored and page numbers appear only via {page}/{pages}.", + "properties": { + "center": { + "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).", + "maxLength": 200, + "type": "string" + }, + "color": { + "description": "Hex colour.", + "pattern": "^#[0-9a-fA-F]{6}$", + "type": "string" + }, + "fontSize": { + "description": "Default 7.", + "maximum": 14, + "minimum": 6, + "type": "number" + }, + "left": { + "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).", + "maxLength": 200, + "type": "string" + }, + "right": { + "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).", + "maxLength": 200, + "type": "string" + } + }, + "type": "object" +} - added
Input schema / properties / headerTemplateAdded value: +{ + "additionalProperties": false, + "description": "Running header on every page (left / center / right zones); reserves 15 pt.", + "properties": { + "center": { + "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).", + "maxLength": 200, + "type": "string" + }, + "color": { + "description": "Hex colour.", + "pattern": "^#[0-9a-fA-F]{6}$", + "type": "string" + }, + "fontSize": { + "description": "Default 7.", + "maximum": 14, + "minimum": 6, + "type": "number" + }, + "left": { + "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).", + "maxLength": 200, + "type": "string" + }, + "right": { + "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).", + "maxLength": 200, + "type": "string" + } + }, + "type": "object" +} - added
Input schema / properties / includeDiagnosticsAdded value: +{ + "default": false, + "description": "Return the PDF/A diagnostics raised while building as `diagnostics[]` (possibly empty).", + "type": "boolean" +} - added
Input schema / properties / marginsAdded value: +{ + "additionalProperties": false, + "description": "Margins in points, all four required (0–200). Default 45 / 36 / 35 / 36.", + "properties": { + "bottom": { + "maximum": 200, + "minimum": 0, + "type": "number" + }, + "left": { + "maximum": 200, + "minimum": 0, + "type": "number" + }, + "right": { + "maximum": 200, + "minimum": 0, + "type": "number" + }, + "top": { + "maximum": 200, + "minimum": 0, + "type": "number" + } + }, + "required": [ + "top", + "right", + "bottom", + "left" + ], + "type": "object" +} - added
Input schema / properties / metadataAdded value: +{ + "additionalProperties": false, + "description": "/Info (+ XMP under PDF/A): author, subject, keywords, /Trapped.", + "properties": { + "author": { + "maxLength": 500, + "type": "string" + }, + "keywords": { + "maxLength": 1000, + "type": "string" + }, + "subject": { + "maxLength": 1000, + "type": "string" + }, + "trapped": { + "description": "/Trapped print flag.", + "enum": [ + "True", + "False", + "Unknown" + ], + "type": "string" + } + }, + "type": "object" +} - added
Input schema / properties / outputIntentAdded value: +{ + "additionalProperties": false, + "description": "Custom PDF/A OutputIntent: an RGB ICC profile + condition strings replacing the built-in sRGB intent (CMYK rejected).", + "properties": { + "iccProfileBase64": { + "description": "ICC profile bytes, base64 (RGB, ≤ 8 MiB).", + "maxLength": 11000000, + "minLength": 1, + "type": "string" + }, + "info": { + "maxLength": 500, + "type": "string" + }, + "outputCondition": { + "maxLength": 200, + "type": "string" + }, + "outputConditionIdentifier": { + "description": "e.g. \"sRGB IEC61966-2.1\".", + "maxLength": 200, + "minLength": 1, + "type": "string" + }, + "registryName": { + "description": "Default \"http://www.color.org\".", + "maxLength": 200, + "type": "string" + } + }, + "required": [ + "iccProfileBase64", + "outputConditionIdentifier" + ], + "type": "object" +} - added
Input schema / properties / pageSizeAdded value: +{ + "description": "Portrait page preset (points): A4 595.28×841.89 (default), Letter 612×792, Legal 612×1008, A3 841.89×1190.55, Tabloid 792×1224. print.* boxes must fit it.", + "enum": [ + "A4", + "Letter", + "Legal", + "A3", + "Tabloid" + ], + "type": "string" +} - changed
Input schema / properties / pdfA / descriptionPrevious value: -"Optional PDF/A conformance level (powered by pdfnative v1.2). Use 'pdfa1b' for archival of simple text+images, 'pdfa2b'/'pdfa2u' for richer content (2u guarantees Unicode mapping), 'pdfa3b' when embedding source attachments (Factur-X / ZUGFeRD). Mutually exclusive with PDF encryption. See docs/guides/PDFA.md."New value: +"PDF/A level: pdfa1b (simple text+images), pdfa2b/pdfa2u (richer; 2u = Unicode mapping), pdfa3b (attachments / Factur-X). Pair with embedFonts=true for a valid claim. Exclusive with encryption. See docs/guides/PDFA.md." - added
Input schema / properties / printAdded value: +{ + "additionalProperties": false, + "description": "Print production (ISO 32000-1 §14.11): page boxes, `bleed` shorthand (TrimBox = MediaBox inset), crop/registration marks outside the TrimBox, /UserUnit for large formats (PDF 1.7; not under pdfa1b). See docs/guides/PRINT.md.", + "properties": { + "artBox": { + "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.", + "items": { + "type": "number" + }, + "maxItems": 4, + "minItems": 4, + "type": "array" + }, + "bleed": { + "description": "Bleed in points (8.5 = 3 mm); sets TrimBox = MediaBox inset. Exclusive with trimBox.", + "exclusiveMinimum": 0, + "maximum": 200, + "type": "number" + }, + "bleedBox": { + "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.", + "items": { + "type": "number" + }, + "maxItems": 4, + "minItems": 4, + "type": "array" + }, + "cropBox": { + "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.", + "items": { + "type": "number" + }, + "maxItems": 4, + "minItems": 4, + "type": "array" + }, + "marks": { + "description": "Printer's marks (needs bleed or trimBox): true for defaults, or an object.", + "oneOf": [ + { + "type": "boolean" + }, + { + "additionalProperties": false, + "properties": { + "crop": { + "description": "Corner crop (trim) marks. Default true.", + "type": "boolean" + }, + "length": { + "description": "Mark length in points. Default 14.", + "maximum": 100, + "minimum": 1, + "type": "number" + }, + "offset": { + "description": "Gap between TrimBox and marks in points. Default 5.", + "maximum": 100, + "minimum": 0, + "type": "number" + }, + "registration": { + "description": "Edge-midpoint registration targets. Default true.", + "type": "boolean" + }, + "weight": { + "description": "Stroke width in points. Default 0.25.", + "maximum": 5, + "minimum": 0.05, + "type": "number" + } + }, + "type": "object" + } + ] + }, + "trimBox": { + "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.", + "items": { + "type": "number" + }, + "maxItems": 4, + "minItems": 4, + "type": "array" + }, + "userUnit": { + "description": "/UserUnit (multiples of 1/72 in) for pages over 14400 pt. Rejected under pdfa1b.", + "maximum": 75000, + "minimum": 1, + "type": "number" + } + }, + "type": "object" +} - added
Input schema / properties / strictAdded value: +{ + "default": false, + "description": "Fail with PDF_A_COMPLIANCE_VIOLATION instead of producing a non-conformant PDF/A file (e.g. PDFA_NO_FONT_ENTRIES without embedFonts). Pair with embedFonts=true.", + "type": "boolean" +} - changed
Output schema / descriptionPrevious value: -"Structured result of a PDF-producing tool. In base64 mode the PDF bytes are delivered out-of-band as an embedded `resource` content block (data: URI), NOT duplicated here, to keep responses token-frugal. In file mode `filePath` is the sandboxed absolute path."New value: +"Result of a PDF-producing tool. base64 mode: the PDF arrives as an embedded `resource` content block (not duplicated here); file mode: `filePath`." - added
Output schema / properties / diagnosticsAdded value: +{ + "description": "PDF/A diagnostics (when includeDiagnostics=true).", + "items": { + "additionalProperties": false, + "properties": { + "code": { + "type": "string" + }, + "message": { + "type": "string" + }, + "severity": { + "enum": [ + "warning" + ], + "type": "string" + } + }, + "required": [ + "code", + "message", + "severity" + ], + "type": "object" + }, + "type": "array" +} - changed
Output schema / properties / filePath / descriptionPrevious value: -"Absolute sandboxed file path (when mode='file')."New value: +"Sandboxed absolute path (file mode)." - added
Output schema / properties / summaryAdded value: +{ + "additionalProperties": true, + "description": "Tool-specific summary, when produced.", + "type": "object" +}
- Changed
add_international_text27 fields changed- added
Input schema / properties / compressAdded value: +{ + "description": "FlateDecode the streams (smaller file, different bytes; PDF/A unaffected, XMP stays plain). Default false.", + "type": "boolean" +} - added
Input schema / properties / creationDateAdded value: +{ + "description": "ISO-8601 instant for /CreationDate (+ XMP). Pin it for byte-identical output across calls (same host TZ); omitted = wall clock, so every call differs.", + "format": "date-time", + "type": "string" +} - added
Input schema / properties / debugAdded value: +{ + "description": "Draw margin / block / cell guide rectangles (unmarked content — not for PDF/UA output). Geometry unchanged. Default false.", + "type": "boolean" +} - added
Input schema / properties / encryptAdded value: +{ + "additionalProperties": false, + "description": "Encrypt at build time (AES-128 default / AES-256) and KEEP the AcroForm — unlike encrypt_pdf, which rebuilds the page tree. Exclusive with pdfA. Randomised output, never cached.", + "properties": { + "algorithm": { + "default": "aes128", + "description": "aes128 (V4/R4, widest compatibility) or aes256 (V5/R6).", + "enum": [ + "aes128", + "aes256" + ], + "type": "string" + }, + "ownerPassword": { + "description": "Owner password (full access).", + "maxLength": 4096, + "minLength": 1, + "type": "string" + }, + "permissions": { + "additionalProperties": false, + "description": "Permission flags; each defaults to allowed.", + "properties": { + "copy": { + "type": "boolean" + }, + "extractText": { + "type": "boolean" + }, + "modify": { + "type": "boolean" + }, + "print": { + "type": "boolean" + } + }, + "type": "object" + }, + "userPassword": { + "description": "Open password; omitted/empty = opens without a prompt.", + "maxLength": 4096, + "type": "string" + } + }, + "required": [ + "ownerPassword" + ], + "type": "object" +} - added
Input schema / properties / footerTemplateAdded value: +{ + "additionalProperties": false, + "description": "Running footer on every page. Replaces the default footer: footerText is then ignored and page numbers appear only via {page}/{pages}.", + "properties": { + "center": { + "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).", + "maxLength": 200, + "type": "string" + }, + "color": { + "description": "Hex colour.", + "pattern": "^#[0-9a-fA-F]{6}$", + "type": "string" + }, + "fontSize": { + "description": "Default 7.", + "maximum": 14, + "minimum": 6, + "type": "number" + }, + "left": { + "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).", + "maxLength": 200, + "type": "string" + }, + "right": { + "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).", + "maxLength": 200, + "type": "string" + } + }, + "type": "object" +} - added
Input schema / properties / headerTemplateAdded value: +{ + "additionalProperties": false, + "description": "Running header on every page (left / center / right zones); reserves 15 pt.", + "properties": { + "center": { + "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).", + "maxLength": 200, + "type": "string" + }, + "color": { + "description": "Hex colour.", + "pattern": "^#[0-9a-fA-F]{6}$", + "type": "string" + }, + "fontSize": { + "description": "Default 7.", + "maximum": 14, + "minimum": 6, + "type": "number" + }, + "left": { + "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).", + "maxLength": 200, + "type": "string" + }, + "right": { + "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).", + "maxLength": 200, + "type": "string" + } + }, + "type": "object" +} - added
Input schema / properties / includeDiagnosticsAdded value: +{ + "default": false, + "description": "Return the PDF/A diagnostics raised while building as `diagnostics[]` (possibly empty).", + "type": "boolean" +} - added
Input schema / properties / lang / anyOfAdded value: +[ + { + "enum": [ + "ar", + "he", + "th", + "ja", + "zh", + "ko", + "el", + "hi", + "bn", + "ta", + "ru", + "ka", + "hy", + "tr", + "pl", + "vi", + "latin", + "te", + "si", + "bo", + "km", + "my", + "am", + "emoji", + "math" + ], + "type": "string" + }, + { + "items": { + "enum": [ + "ar", + "he", + "th", + "ja", + "zh", + "ko", + "el", + "hi", + "bn", + "ta", + "ru", + "ka", + "hy", + "tr", + "pl", + "vi", + "latin", + "te", + "si", + "bo", + "km", + "my", + "am", + "emoji", + "math" + ], + "type": "string" + }, + "maxItems": 25, + "minItems": 1, + "type": "array" + }, + { + "description": "Comma-separated list of supported codes.", + "maxLength": 80, + "minLength": 2, + "type": "string" + } +] - removed
Input schema / properties / lang / oneOfRemoved value: -[ - { - "enum": [ - "ar", - "he", - "th", - "ja", - "zh", - "ko", - "el", - "hi", - "bn", - "ta", - "ru", - "ka", - "hy", - "tr", - "pl", - "vi", - "latin", - "te", - "si", - "bo", - "km", - "my", - "am", - "emoji", - "math" - ], - "type": "string" - }, - { - "items": { - "enum": [ - "ar", - "he", - "th", - "ja", - "zh", - "ko", - "el", - "hi", - "bn", - "ta", - "ru", - "ka", - "hy", - "tr", - "pl", - "vi", - "latin", - "te", - "si", - "bo", - "km", - "my", - "am", - "emoji", - "math" - ], - "type": "string" - }, - "maxItems": 25, - "minItems": 1, - "type": "array" - }, - { - "description": "Comma-separated list of supported codes.", - "maxLength": 80, - "minLength": 2, - "type": "string" - } -] - added
Input schema / properties / marginsAdded value: +{ + "additionalProperties": false, + "description": "Margins in points, all four required (0–200). Default 45 / 36 / 35 / 36.", + "properties": { + "bottom": { + "maximum": 200, + "minimum": 0, + "type": "number" + }, + "left": { + "maximum": 200, + "minimum": 0, + "type": "number" + }, + "right": { + "maximum": 200, + "minimum": 0, + "type": "number" + }, + "top": { + "maximum": 200, + "minimum": 0, + "type": "number" + } + }, + "required": [ + "top", + "right", + "bottom", + "left" + ], + "type": "object" +} - added
Input schema / properties / metadataAdded value: +{ + "additionalProperties": false, + "description": "/Info (+ XMP under PDF/A): author, subject, keywords, /Trapped.", + "properties": { + "author": { + "maxLength": 500, + "type": "string" + }, + "keywords": { + "maxLength": 1000, + "type": "string" + }, + "subject": { + "maxLength": 1000, + "type": "string" + }, + "trapped": { + "description": "/Trapped print flag.", + "enum": [ + "True", + "False", + "Unknown" + ], + "type": "string" + } + }, + "type": "object" +} - changed
Input schema / properties / normalize / descriptionPrevious value: -"Unicode normalization form applied before shaping. Defaults to 'NFC' (recommended for international scripts: composes decomposed sequences for the widest glyph coverage). Override with 'NFD'/'NFKC'/'NFKD' only for specialised needs."New value: +"Unicode normalization before shaping. Default 'NFC' (widest glyph coverage); NFD/NFKC/NFKD or false for special needs." - added
Input schema / properties / outputIntentAdded value: +{ + "additionalProperties": false, + "description": "Custom PDF/A OutputIntent: an RGB ICC profile + condition strings replacing the built-in sRGB intent (CMYK rejected).", + "properties": { + "iccProfileBase64": { + "description": "ICC profile bytes, base64 (RGB, ≤ 8 MiB).", + "maxLength": 11000000, + "minLength": 1, + "type": "string" + }, + "info": { + "maxLength": 500, + "type": "string" + }, + "outputCondition": { + "maxLength": 200, + "type": "string" + }, + "outputConditionIdentifier": { + "description": "e.g. \"sRGB IEC61966-2.1\".", + "maxLength": 200, + "minLength": 1, + "type": "string" + }, + "registryName": { + "description": "Default \"http://www.color.org\".", + "maxLength": 200, + "type": "string" + } + }, + "required": [ + "iccProfileBase64", + "outputConditionIdentifier" + ], + "type": "object" +} - added
Input schema / properties / outputMode / descriptionAdded value: +"'base64' (default) returns the PDF inline; 'file' writes it inside the PDFNATIVE_MCP_OUTPUT_DIR sandbox (SECURITY_VIOLATION when the sandbox is not configured)." - added
Input schema / properties / outputPath / descriptionAdded value: +"Required when outputMode='file'. Relative path inside the sandbox; must end with .pdf (no absolute paths, no '..')." - added
Input schema / properties / pageSizeAdded value: +{ + "description": "Portrait page preset (points): A4 595.28×841.89 (default), Letter 612×792, Legal 612×1008, A3 841.89×1190.55, Tabloid 792×1224. print.* boxes must fit it.", + "enum": [ + "A4", + "Letter", + "Legal", + "A3", + "Tabloid" + ], + "type": "string" +} - changed
Input schema / properties / pdfA / descriptionPrevious value: -"Optional PDF/A conformance level. When set, Tagged PDF + sRGB OutputIntent + XMP metadata are emitted; the 'latin' Noto Sans fallback is auto-registered for non-WinAnsi Latin (ISO 19005-1 §6.3.4). See docs/guides/PDFA.md for the full authoring guide."New value: +"PDF/A level (Tagged PDF + sRGB OutputIntent + XMP). Fonts are embedded here, so the claim is valid as-is. See docs/guides/PDFA.md." - added
Input schema / properties / printAdded value: +{ + "additionalProperties": false, + "description": "Print production (ISO 32000-1 §14.11): page boxes, `bleed` shorthand (TrimBox = MediaBox inset), crop/registration marks outside the TrimBox, /UserUnit for large formats (PDF 1.7; not under pdfa1b). See docs/guides/PRINT.md.", + "properties": { + "artBox": { + "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.", + "items": { + "type": "number" + }, + "maxItems": 4, + "minItems": 4, + "type": "array" + }, + "bleed": { + "description": "Bleed in points (8.5 = 3 mm); sets TrimBox = MediaBox inset. Exclusive with trimBox.", + "exclusiveMinimum": 0, + "maximum": 200, + "type": "number" + }, + "bleedBox": { + "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.", + "items": { + "type": "number" + }, + "maxItems": 4, + "minItems": 4, + "type": "array" + }, + "cropBox": { + "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.", + "items": { + "type": "number" + }, + "maxItems": 4, + "minItems": 4, + "type": "array" + }, + "marks": { + "description": "Printer's marks (needs bleed or trimBox): true for defaults, or an object.", + "oneOf": [ + { + "type": "boolean" + }, + { + "additionalProperties": false, + "properties": { + "crop": { + "description": "Corner crop (trim) marks. Default true.", + "type": "boolean" + }, + "length": { + "description": "Mark length in points. Default 14.", + "maximum": 100, + "minimum": 1, + "type": "number" + }, + "offset": { + "description": "Gap between TrimBox and marks in points. Default 5.", + "maximum": 100, + "minimum": 0, + "type": "number" + }, + "registration": { + "description": "Edge-midpoint registration targets. Default true.", + "type": "boolean" + }, + "weight": { + "description": "Stroke width in points. Default 0.25.", + "maximum": 5, + "minimum": 0.05, + "type": "number" + } + }, + "type": "object" + } + ] + }, + "trimBox": { + "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.", + "items": { + "type": "number" + }, + "maxItems": 4, + "minItems": 4, + "type": "array" + }, + "userUnit": { + "description": "/UserUnit (multiples of 1/72 in) for pages over 14400 pt. Rejected under pdfa1b.", + "maximum": 75000, + "minimum": 1, + "type": "number" + } + }, + "type": "object" +} - added
Input schema / properties / strictAdded value: +{ + "default": false, + "description": "Fail with PDF_A_COMPLIANCE_VIOLATION instead of producing a non-conformant PDF/A file (e.g. PDFA_NO_FONT_ENTRIES without embedFonts). Pair with embedFonts=true.", + "type": "boolean" +} - added
Input schema / properties / viewerPreferences / properties / duplexAdded value: +{ + "description": "Print-dialog paper handling default (/Duplex): single-sided or double-sided flipping on the short/long edge.", + "enum": [ + "simplex", + "duplexFlipShortEdge", + "duplexFlipLongEdge" + ], + "type": "string" +} - added
Input schema / properties / viewerPreferences / properties / numCopiesAdded value: +{ + "description": "Default number of copies for the Print dialog (/NumCopies; viewers honour 2-5 per ISO 32000 Table 150).", + "maximum": 1000, + "minimum": 1, + "type": "integer" +} - added
Input schema / properties / viewerPreferences / properties / pickTrayByPDFSizeAdded value: +{ + "description": "Ask the printer to pick the input tray from the PDF page size (/PickTrayByPDFSize).", + "type": "boolean" +} - added
Input schema / properties / viewerPreferences / properties / printPageRangeAdded value: +{ + "description": "Default page ranges for the Print dialog (/PrintPageRange) as inclusive 1-based [first, last] pairs, e.g. [[1, 4], [7, 7]].", + "items": { + "items": { + "minimum": 1, + "type": "integer" + }, + "maxItems": 2, + "minItems": 2, + "type": "array" + }, + "maxItems": 100, + "type": "array" +} - changed
Output schema / descriptionPrevious value: -"Structured result of a PDF-producing tool. In base64 mode the PDF bytes are delivered out-of-band as an embedded `resource` content block (data: URI), NOT duplicated here, to keep responses token-frugal. In file mode `filePath` is the sandboxed absolute path."New value: +"Result of a PDF-producing tool. base64 mode: the PDF arrives as an embedded `resource` content block (not duplicated here); file mode: `filePath`." - added
Output schema / properties / diagnosticsAdded value: +{ + "description": "PDF/A diagnostics (when includeDiagnostics=true).", + "items": { + "additionalProperties": false, + "properties": { + "code": { + "type": "string" + }, + "message": { + "type": "string" + }, + "severity": { + "enum": [ + "warning" + ], + "type": "string" + } + }, + "required": [ + "code", + "message", + "severity" + ], + "type": "object" + }, + "type": "array" +} - changed
Output schema / properties / filePath / descriptionPrevious value: -"Absolute sandboxed file path (when mode='file')."New value: +"Sandboxed absolute path (file mode)." - added
Output schema / properties / summaryAdded value: +{ + "additionalProperties": true, + "description": "Tool-specific summary, when produced.", + "type": "object" +}
- Added
add_ltv - Changed
add_table42 fields changed- changed
Input schema / properties / autoFitColumns / descriptionPrevious value: -"When true, column widths auto-fit content (pdfnative v1.1). Switches the backend to buildDocumentPDFBytes; byte output differs from the default path."New value: +"Auto-fit column widths to content. Output bytes then depend on text metrics (not byte-deterministic across content changes)." - changed
Input schema / properties / caption / descriptionPrevious value: -"Caption rendered above the table (and emitted as /Caption structure element in tagged/PDF/A mode). pdfnative v1.2."New value: +"Caption rendered above the table (tagged as /Caption under PDF/A)." - changed
Input schema / properties / cellBorders / descriptionPrevious value: -"Per-cell vector borders (pdfnative v1.4). Switches the backend to buildDocumentPDFBytes. Choose individual sides or `all`."New value: +"Per-cell vector borders (pure strokes, PDF/A-safe). Choose individual sides or `all`." - changed
Input schema / properties / cellPadding / descriptionPrevious value: -"Horizontal cell padding in points applied to both insets (default 3). pdfnative v1.2."New value: +"Horizontal cell padding in points (default 3)." - changed
Input schema / properties / cellVAlign / descriptionPrevious value: -"Vertical alignment of cell content (pdfnative v1.4). Switches the backend to buildDocumentPDFBytes."New value: +"Vertical alignment of cell content." - changed
Input schema / properties / clipCells / descriptionPrevious value: -"When true, cell contents are clipped to column bounds via PDF clip-path operators (pdfnative v1.1). Recommended for PDF/A and visual safety. Switches the backend to buildDocumentPDFBytes."New value: +"Clip cell contents to the column bounds (PDF clip operators). Recommended for PDF/A and visual safety." - added
Input schema / properties / compressAdded value: +{ + "description": "FlateDecode the streams (smaller file, different bytes; PDF/A unaffected, XMP stays plain). Default false.", + "type": "boolean" +} - added
Input schema / properties / creationDateAdded value: +{ + "description": "ISO-8601 instant for /CreationDate (+ XMP). Pin it for byte-identical output across calls (same host TZ); omitted = wall clock, so every call differs.", + "format": "date-time", + "type": "string" +} - added
Input schema / properties / debugAdded value: +{ + "description": "Draw margin / block / cell guide rectangles (unmarked content — not for PDF/UA output). Geometry unchanged. Default false.", + "type": "boolean" +} - added
Input schema / properties / embedFontsAdded value: +{ + "default": false, + "description": "Embed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A claim (ISO 19005 §6.2.11.4.1) and for strict=true; adds ~0.3 MiB.", + "type": "boolean" +} - added
Input schema / properties / encryptAdded value: +{ + "additionalProperties": false, + "description": "Encrypt at build time (AES-128 default / AES-256) and KEEP the AcroForm — unlike encrypt_pdf, which rebuilds the page tree. Exclusive with pdfA. Randomised output, never cached.", + "properties": { + "algorithm": { + "default": "aes128", + "description": "aes128 (V4/R4, widest compatibility) or aes256 (V5/R6).", + "enum": [ + "aes128", + "aes256" + ], + "type": "string" + }, + "ownerPassword": { + "description": "Owner password (full access).", + "maxLength": 4096, + "minLength": 1, + "type": "string" + }, + "permissions": { + "additionalProperties": false, + "description": "Permission flags; each defaults to allowed.", + "properties": { + "copy": { + "type": "boolean" + }, + "extractText": { + "type": "boolean" + }, + "modify": { + "type": "boolean" + }, + "print": { + "type": "boolean" + } + }, + "type": "object" + }, + "userPassword": { + "description": "Open password; omitted/empty = opens without a prompt.", + "maxLength": 4096, + "type": "string" + } + }, + "required": [ + "ownerPassword" + ], + "type": "object" +} - added
Input schema / properties / footerTemplateAdded value: +{ + "additionalProperties": false, + "description": "Running footer on every page. Replaces the default footer: footerText is then ignored and page numbers appear only via {page}/{pages}.", + "properties": { + "center": { + "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).", + "maxLength": 200, + "type": "string" + }, + "color": { + "description": "Hex colour.", + "pattern": "^#[0-9a-fA-F]{6}$", + "type": "string" + }, + "fontSize": { + "description": "Default 7.", + "maximum": 14, + "minimum": 6, + "type": "number" + }, + "left": { + "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).", + "maxLength": 200, + "type": "string" + }, + "right": { + "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).", + "maxLength": 200, + "type": "string" + } + }, + "type": "object" +} - added
Input schema / properties / headerTemplateAdded value: +{ + "additionalProperties": false, + "description": "Running header on every page (left / center / right zones); reserves 15 pt.", + "properties": { + "center": { + "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).", + "maxLength": 200, + "type": "string" + }, + "color": { + "description": "Hex colour.", + "pattern": "^#[0-9a-fA-F]{6}$", + "type": "string" + }, + "fontSize": { + "description": "Default 7.", + "maximum": 14, + "minimum": 6, + "type": "number" + }, + "left": { + "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).", + "maxLength": 200, + "type": "string" + }, + "right": { + "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).", + "maxLength": 200, + "type": "string" + } + }, + "type": "object" +} - added
Input schema / properties / includeDiagnosticsAdded value: +{ + "default": false, + "description": "Return the PDF/A diagnostics raised while building as `diagnostics[]` (possibly empty).", + "type": "boolean" +} - added
Input schema / properties / marginsAdded value: +{ + "additionalProperties": false, + "description": "Margins in points, all four required (0–200). Default 45 / 36 / 35 / 36.", + "properties": { + "bottom": { + "maximum": 200, + "minimum": 0, + "type": "number" + }, + "left": { + "maximum": 200, + "minimum": 0, + "type": "number" + }, + "right": { + "maximum": 200, + "minimum": 0, + "type": "number" + }, + "top": { + "maximum": 200, + "minimum": 0, + "type": "number" + } + }, + "required": [ + "top", + "right", + "bottom", + "left" + ], + "type": "object" +} - added
Input schema / properties / metadataAdded value: +{ + "additionalProperties": false, + "description": "/Info (+ XMP under PDF/A): author, subject, keywords, /Trapped.", + "properties": { + "author": { + "maxLength": 500, + "type": "string" + }, + "keywords": { + "maxLength": 1000, + "type": "string" + }, + "subject": { + "maxLength": 1000, + "type": "string" + }, + "trapped": { + "description": "/Trapped print flag.", + "enum": [ + "True", + "False", + "Unknown" + ], + "type": "string" + } + }, + "type": "object" +} - changed
Input schema / properties / minRowHeight / descriptionPrevious value: -"Minimum row height in points (default 12). pdfnative v1.2."New value: +"Minimum row height in points (default 12)." - added
Input schema / properties / outputIntentAdded value: +{ + "additionalProperties": false, + "description": "Custom PDF/A OutputIntent: an RGB ICC profile + condition strings replacing the built-in sRGB intent (CMYK rejected).", + "properties": { + "iccProfileBase64": { + "description": "ICC profile bytes, base64 (RGB, ≤ 8 MiB).", + "maxLength": 11000000, + "minLength": 1, + "type": "string" + }, + "info": { + "maxLength": 500, + "type": "string" + }, + "outputCondition": { + "maxLength": 200, + "type": "string" + }, + "outputConditionIdentifier": { + "description": "e.g. \"sRGB IEC61966-2.1\".", + "maxLength": 200, + "minLength": 1, + "type": "string" + }, + "registryName": { + "description": "Default \"http://www.color.org\".", + "maxLength": 200, + "type": "string" + } + }, + "required": [ + "iccProfileBase64", + "outputConditionIdentifier" + ], + "type": "object" +} - added
Input schema / properties / pageSizeAdded value: +{ + "description": "Portrait page preset (points): A4 595.28×841.89 (default), Letter 612×792, Legal 612×1008, A3 841.89×1190.55, Tabloid 792×1224. print.* boxes must fit it.", + "enum": [ + "A4", + "Letter", + "Legal", + "A3", + "Tabloid" + ], + "type": "string" +} - changed
Input schema / properties / pdfA / descriptionPrevious value: -"Optional PDF/A conformance level (powered by pdfnative v1.2). Use 'pdfa1b' for archival of simple text+images, 'pdfa2b'/'pdfa2u' for richer content (2u guarantees Unicode mapping), 'pdfa3b' when embedding source attachments (Factur-X / ZUGFeRD). Mutually exclusive with PDF encryption. See docs/guides/PDFA.md."New value: +"PDF/A level: pdfa1b (simple text+images), pdfa2b/pdfa2u (richer; 2u = Unicode mapping), pdfa3b (attachments / Factur-X). Pair with embedFonts=true for a valid claim. Exclusive with encryption. See docs/guides/PDFA.md." - added
Input schema / properties / printAdded value: +{ + "additionalProperties": false, + "description": "Print production (ISO 32000-1 §14.11): page boxes, `bleed` shorthand (TrimBox = MediaBox inset), crop/registration marks outside the TrimBox, /UserUnit for large formats (PDF 1.7; not under pdfa1b). See docs/guides/PRINT.md.", + "properties": { + "artBox": { + "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.", + "items": { + "type": "number" + }, + "maxItems": 4, + "minItems": 4, + "type": "array" + }, + "bleed": { + "description": "Bleed in points (8.5 = 3 mm); sets TrimBox = MediaBox inset. Exclusive with trimBox.", + "exclusiveMinimum": 0, + "maximum": 200, + "type": "number" + }, + "bleedBox": { + "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.", + "items": { + "type": "number" + }, + "maxItems": 4, + "minItems": 4, + "type": "array" + }, + "cropBox": { + "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.", + "items": { + "type": "number" + }, + "maxItems": 4, + "minItems": 4, + "type": "array" + }, + "marks": { + "description": "Printer's marks (needs bleed or trimBox): true for defaults, or an object.", + "oneOf": [ + { + "type": "boolean" + }, + { + "additionalProperties": false, + "properties": { + "crop": { + "description": "Corner crop (trim) marks. Default true.", + "type": "boolean" + }, + "length": { + "description": "Mark length in points. Default 14.", + "maximum": 100, + "minimum": 1, + "type": "number" + }, + "offset": { + "description": "Gap between TrimBox and marks in points. Default 5.", + "maximum": 100, + "minimum": 0, + "type": "number" + }, + "registration": { + "description": "Edge-midpoint registration targets. Default true.", + "type": "boolean" + }, + "weight": { + "description": "Stroke width in points. Default 0.25.", + "maximum": 5, + "minimum": 0.05, + "type": "number" + } + }, + "type": "object" + } + ] + }, + "trimBox": { + "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.", + "items": { + "type": "number" + }, + "maxItems": 4, + "minItems": 4, + "type": "array" + }, + "userUnit": { + "description": "/UserUnit (multiples of 1/72 in) for pages over 14400 pt. Rejected under pdfa1b.", + "maximum": 75000, + "minimum": 1, + "type": "number" + } + }, + "type": "object" +} - changed
Input schema / properties / repeatHeader / descriptionPrevious value: -"Repeat the header row on every continuation page (pdfnative v1.2). Default true."New value: +"Repeat the header row on every continuation page (default true)." - added
Input schema / properties / strictAdded value: +{ + "default": false, + "description": "Fail with PDF_A_COMPLIANCE_VIOLATION instead of producing a non-conformant PDF/A file (e.g. PDFA_NO_FONT_ENTRIES without embedFonts). Pair with embedFonts=true.", + "type": "boolean" +} - added
Input schema / properties / viewerPreferences / properties / duplexAdded value: +{ + "description": "Print-dialog paper handling default (/Duplex): single-sided or double-sided flipping on the short/long edge.", + "enum": [ + "simplex", + "duplexFlipShortEdge", + "duplexFlipLongEdge" + ], + "type": "string" +} - added
Input schema / properties / viewerPreferences / properties / numCopiesAdded value: +{ + "description": "Default number of copies for the Print dialog (/NumCopies; viewers honour 2-5 per ISO 32000 Table 150).", + "maximum": 1000, + "minimum": 1, + "type": "integer" +} - added
Input schema / properties / viewerPreferences / properties / pickTrayByPDFSizeAdded value: +{ + "description": "Ask the printer to pick the input tray from the PDF page size (/PickTrayByPDFSize).", + "type": "boolean" +} - added
Input schema / properties / viewerPreferences / properties / printPageRangeAdded value: +{ + "description": "Default page ranges for the Print dialog (/PrintPageRange) as inclusive 1-based [first, last] pairs, e.g. [[1, 4], [7, 7]].", + "items": { + "items": { + "minimum": 1, + "type": "integer" + }, + "maxItems": 2, + "minItems": 2, + "type": "array" + }, + "maxItems": 100, + "type": "array" +} - changed
Input schema / properties / watermark / descriptionPrevious value: -"Optional semi-transparent text watermark rendered on every page (e.g. 'DRAFT', 'CONFIDENTIAL'). Text only in this version. opacity < 1.0 is rejected under pdfA='pdfa1b' (ISO 19005-1 forbids transparency)."New value: +"Optional semi-transparent watermark rendered centred on every page: `text` (e.g. 'DRAFT'), `image` (JPEG/PNG), or both combined. At least one of text / image is required. opacity < 1.0 (text or image, including the defaults) is rejected under pdfA='pdfa1b' (ISO 19005-1 forbids transparency)." - changed
Input schema / properties / watermark / properties / angle / descriptionPrevious value: -"Rotation in degrees (counterclockwise). Default -45."New value: +"Text rotation in degrees (counterclockwise). Default -45." - changed
Input schema / properties / watermark / properties / color / descriptionPrevious value: -"RGB colour as a [r, g, b] triple in the 0.0–1.0 range. Default light gray [0.75, 0.75, 0.75]."New value: +"Text RGB colour as a [r, g, b] triple in the 0.0–1.0 range. Default light gray [0.75, 0.75, 0.75]." - changed
Input schema / properties / watermark / properties / fontSize / descriptionPrevious value: -"Font size in points. Default 60, auto-fit to the page."New value: +"Text font size in points. Default 60, auto-fit to the page." - added
Input schema / properties / watermark / properties / imageAdded value: +{ + "additionalProperties": false, + "description": "Image watermark (JPEG or PNG) centred on every page, optionally combined with `text`. Bytes are validated against the JPEG/PNG magic numbers; mimeType must match.", + "properties": { + "height": { + "description": "Display height in points (default: from the image pixel size).", + "exclusiveMinimum": 0, + "maximum": 14400, + "type": "number" + }, + "imageBase64": { + "description": "Base64-encoded JPEG or 8-bit opaque PNG bytes (max 8 MiB decoded; alpha-channel, palette and interlaced PNGs are rejected with a remedy). Plain base64, no data: URI prefix.", + "maxLength": 12000000, + "minLength": 4, + "type": "string" + }, + "mimeType": { + "description": "'image/jpeg' or 'image/png' — must match the actual bytes.", + "enum": [ + "image/jpeg", + "image/png" + ], + "type": "string" + }, + "opacity": { + "description": "Image opacity 0.0–1.0. Default 0.10.", + "maximum": 1, + "minimum": 0, + "type": "number" + }, + "width": { + "description": "Display width in points (default: from the image pixel size).", + "exclusiveMinimum": 0, + "maximum": 14400, + "type": "number" + } + }, + "required": [ + "imageBase64", + "mimeType" + ], + "type": "object" +} - changed
Input schema / properties / watermark / properties / opacity / descriptionPrevious value: -"Opacity 0.0–1.0. Default 0.15."New value: +"Text opacity 0.0–1.0. Default 0.15. (Image opacity is image.opacity.)" - changed
Input schema / properties / watermark / properties / position / descriptionPrevious value: -"'background' (behind page content, default) or 'foreground' (above it)."New value: +"'background' (behind page content, default) or 'foreground' (above it). Applies to text and image alike." - changed
Input schema / properties / watermark / properties / text / descriptionPrevious value: -"Watermark text."New value: +"Watermark text. Optional when `image` is given." - removed
Input schema / properties / watermark / requiredRemoved value: -[ - "text" -] - changed
Input schema / properties / wrap / descriptionPrevious value: -"Cell wrap policy (pdfnative v1.2). 'auto' (default) wraps only when a cell overflows; 'always' wraps every cell; 'never' uses v1.1 character truncation."New value: +"Cell wrap policy: 'auto' (default) wraps only overflowing cells; 'always' wraps every cell; 'never' truncates." - changed
Input schema / properties / zebra / descriptionPrevious value: -"Enable zebra striping (alternate-row light tint, PDF/A-1b safe). pdfnative v1.2."New value: +"Alternate-row light tint (static fill, PDF/A-1b safe)." - changed
Output schema / descriptionPrevious value: -"Structured result of a PDF-producing tool. In base64 mode the PDF bytes are delivered out-of-band as an embedded `resource` content block (data: URI), NOT duplicated here, to keep responses token-frugal. In file mode `filePath` is the sandboxed absolute path."New value: +"Result of a PDF-producing tool. base64 mode: the PDF arrives as an embedded `resource` content block (not duplicated here); file mode: `filePath`." - added
Output schema / properties / diagnosticsAdded value: +{ + "description": "PDF/A diagnostics (when includeDiagnostics=true).", + "items": { + "additionalProperties": false, + "properties": { + "code": { + "type": "string" + }, + "message": { + "type": "string" + }, + "severity": { + "enum": [ + "warning" + ], + "type": "string" + } + }, + "required": [ + "code", + "message", + "severity" + ], + "type": "object" + }, + "type": "array" +} - changed
Output schema / properties / filePath / descriptionPrevious value: -"Absolute sandboxed file path (when mode='file')."New value: +"Sandboxed absolute path (file mode)." - added
Output schema / properties / summaryAdded value: +{ + "additionalProperties": true, + "description": "Tool-specific summary, when produced.", + "type": "object" +}
- Changed
annotate_pdf6 fields changed- added
Input schema / properties / outputMode / descriptionAdded value: +"'base64' (default) returns the PDF inline; 'file' writes it inside the PDFNATIVE_MCP_OUTPUT_DIR sandbox (SECURITY_VIOLATION when the sandbox is not configured)." - added
Input schema / properties / outputPath / descriptionAdded value: +"Required when outputMode='file'. Relative path inside the sandbox; must end with .pdf (no absolute paths, no '..')." - changed
Output schema / descriptionPrevious value: -"Structured result of a PDF-producing tool. In base64 mode the PDF bytes are delivered out-of-band as an embedded `resource` content block (data: URI), NOT duplicated here, to keep responses token-frugal. In file mode `filePath` is the sandboxed absolute path."New value: +"Result of a PDF-producing tool. base64 mode: the PDF arrives as an embedded `resource` content block (not duplicated here); file mode: `filePath`." - added
Output schema / properties / diagnosticsAdded value: +{ + "description": "PDF/A diagnostics (when includeDiagnostics=true).", + "items": { + "additionalProperties": false, + "properties": { + "code": { + "type": "string" + }, + "message": { + "type": "string" + }, + "severity": { + "enum": [ + "warning" + ], + "type": "string" + } + }, + "required": [ + "code", + "message", + "severity" + ], + "type": "object" + }, + "type": "array" +} - changed
Output schema / properties / filePath / descriptionPrevious value: -"Absolute sandboxed file path (when mode='file')."New value: +"Sandboxed absolute path (file mode)." - added
Output schema / properties / summaryAdded value: +{ + "additionalProperties": true, + "description": "Tool-specific summary, when produced.", + "type": "object" +}
- Changed
decrypt_pdf5 fields changed- added
Input schema / properties / outputMode / descriptionAdded value: +"'base64' (default) returns the PDF inline; 'file' writes it inside the PDFNATIVE_MCP_OUTPUT_DIR sandbox (SECURITY_VIOLATION when the sandbox is not configured)." - changed
Output schema / descriptionPrevious value: -"Structured result of a PDF-producing tool. In base64 mode the PDF bytes are delivered out-of-band as an embedded `resource` content block (data: URI), NOT duplicated here, to keep responses token-frugal. In file mode `filePath` is the sandboxed absolute path."New value: +"Result of a PDF-producing tool. base64 mode: the PDF arrives as an embedded `resource` content block (not duplicated here); file mode: `filePath`." - added
Output schema / properties / diagnosticsAdded value: +{ + "description": "PDF/A diagnostics (when includeDiagnostics=true).", + "items": { + "additionalProperties": false, + "properties": { + "code": { + "type": "string" + }, + "message": { + "type": "string" + }, + "severity": { + "enum": [ + "warning" + ], + "type": "string" + } + }, + "required": [ + "code", + "message", + "severity" + ], + "type": "object" + }, + "type": "array" +} - changed
Output schema / properties / filePath / descriptionPrevious value: -"Absolute sandboxed file path (when mode='file')."New value: +"Sandboxed absolute path (file mode)." - added
Output schema / properties / summaryAdded value: +{ + "additionalProperties": true, + "description": "Tool-specific summary, when produced.", + "type": "object" +}
- Changed
embed_image23 fields changed- added
Input schema / properties / alignAdded value: +{ + "default": "left", + "description": "Horizontal placement of the image inside the content width.", + "enum": [ + "left", + "center", + "right" + ], + "type": "string" +} - added
Input schema / properties / altAdded value: +{ + "description": "Accessible description of the image (tagged /Figure /Alt). Provide it for non-decorative images under PDF/A or PDF/UA.", + "maxLength": 500, + "type": "string" +} - added
Input schema / properties / compressAdded value: +{ + "description": "FlateDecode the streams (smaller file, different bytes; PDF/A unaffected, XMP stays plain). Default false.", + "type": "boolean" +} - added
Input schema / properties / creationDateAdded value: +{ + "description": "ISO-8601 instant for /CreationDate (+ XMP). Pin it for byte-identical output across calls (same host TZ); omitted = wall clock, so every call differs.", + "format": "date-time", + "type": "string" +} - added
Input schema / properties / debugAdded value: +{ + "description": "Draw margin / block / cell guide rectangles (unmarked content — not for PDF/UA output). Geometry unchanged. Default false.", + "type": "boolean" +} - added
Input schema / properties / embedFontsAdded value: +{ + "default": false, + "description": "Embed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A claim (ISO 19005 §6.2.11.4.1) and for strict=true; adds ~0.3 MiB.", + "type": "boolean" +} - added
Input schema / properties / encryptAdded value: +{ + "additionalProperties": false, + "description": "Encrypt at build time (AES-128 default / AES-256) and KEEP the AcroForm — unlike encrypt_pdf, which rebuilds the page tree. Exclusive with pdfA. Randomised output, never cached.", + "properties": { + "algorithm": { + "default": "aes128", + "description": "aes128 (V4/R4, widest compatibility) or aes256 (V5/R6).", + "enum": [ + "aes128", + "aes256" + ], + "type": "string" + }, + "ownerPassword": { + "description": "Owner password (full access).", + "maxLength": 4096, + "minLength": 1, + "type": "string" + }, + "permissions": { + "additionalProperties": false, + "description": "Permission flags; each defaults to allowed.", + "properties": { + "copy": { + "type": "boolean" + }, + "extractText": { + "type": "boolean" + }, + "modify": { + "type": "boolean" + }, + "print": { + "type": "boolean" + } + }, + "type": "object" + }, + "userPassword": { + "description": "Open password; omitted/empty = opens without a prompt.", + "maxLength": 4096, + "type": "string" + } + }, + "required": [ + "ownerPassword" + ], + "type": "object" +} - added
Input schema / properties / footerTemplateAdded value: +{ + "additionalProperties": false, + "description": "Running footer on every page. Replaces the default footer: footerText is then ignored and page numbers appear only via {page}/{pages}.", + "properties": { + "center": { + "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).", + "maxLength": 200, + "type": "string" + }, + "color": { + "description": "Hex colour.", + "pattern": "^#[0-9a-fA-F]{6}$", + "type": "string" + }, + "fontSize": { + "description": "Default 7.", + "maximum": 14, + "minimum": 6, + "type": "number" + }, + "left": { + "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).", + "maxLength": 200, + "type": "string" + }, + "right": { + "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).", + "maxLength": 200, + "type": "string" + } + }, + "type": "object" +} - added
Input schema / properties / headerTemplateAdded value: +{ + "additionalProperties": false, + "description": "Running header on every page (left / center / right zones); reserves 15 pt.", + "properties": { + "center": { + "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).", + "maxLength": 200, + "type": "string" + }, + "color": { + "description": "Hex colour.", + "pattern": "^#[0-9a-fA-F]{6}$", + "type": "string" + }, + "fontSize": { + "description": "Default 7.", + "maximum": 14, + "minimum": 6, + "type": "number" + }, + "left": { + "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).", + "maxLength": 200, + "type": "string" + }, + "right": { + "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).", + "maxLength": 200, + "type": "string" + } + }, + "type": "object" +} - changed
Input schema / properties / imageBase64 / descriptionPrevious value: -"Base64-encoded image bytes. Supports JPEG and PNG formats."New value: +"Base64 image bytes. JPEG (baseline; 1, 3 or 4 components — CMYK raises PDFA_DEVICE_CMYK_IMAGE under PDF/A) or PNG (8-bit greyscale/RGB, non-interlaced; alpha-channel and palette PNGs are rejected with a remedy). No data: URI." - added
Input schema / properties / includeDiagnosticsAdded value: +{ + "default": false, + "description": "Return the PDF/A diagnostics raised while building as `diagnostics[]` (possibly empty).", + "type": "boolean" +} - added
Input schema / properties / marginsAdded value: +{ + "additionalProperties": false, + "description": "Margins in points, all four required (0–200). Default 45 / 36 / 35 / 36.", + "properties": { + "bottom": { + "maximum": 200, + "minimum": 0, + "type": "number" + }, + "left": { + "maximum": 200, + "minimum": 0, + "type": "number" + }, + "right": { + "maximum": 200, + "minimum": 0, + "type": "number" + }, + "top": { + "maximum": 200, + "minimum": 0, + "type": "number" + } + }, + "required": [ + "top", + "right", + "bottom", + "left" + ], + "type": "object" +} - added
Input schema / properties / metadataAdded value: +{ + "additionalProperties": false, + "description": "/Info (+ XMP under PDF/A): author, subject, keywords, /Trapped.", + "properties": { + "author": { + "maxLength": 500, + "type": "string" + }, + "keywords": { + "maxLength": 1000, + "type": "string" + }, + "subject": { + "maxLength": 1000, + "type": "string" + }, + "trapped": { + "description": "/Trapped print flag.", + "enum": [ + "True", + "False", + "Unknown" + ], + "type": "string" + } + }, + "type": "object" +} - changed
Input schema / properties / mimeType / descriptionPrevious value: -"MIME type of the image. Must match the actual encoding of imageBase64."New value: +"MIME type of the image. Must match the actual encoding of imageBase64 (magic bytes are checked)." - added
Input schema / properties / outputIntentAdded value: +{ + "additionalProperties": false, + "description": "Custom PDF/A OutputIntent: an RGB ICC profile + condition strings replacing the built-in sRGB intent (CMYK rejected).", + "properties": { + "iccProfileBase64": { + "description": "ICC profile bytes, base64 (RGB, ≤ 8 MiB).", + "maxLength": 11000000, + "minLength": 1, + "type": "string" + }, + "info": { + "maxLength": 500, + "type": "string" + }, + "outputCondition": { + "maxLength": 200, + "type": "string" + }, + "outputConditionIdentifier": { + "description": "e.g. \"sRGB IEC61966-2.1\".", + "maxLength": 200, + "minLength": 1, + "type": "string" + }, + "registryName": { + "description": "Default \"http://www.color.org\".", + "maxLength": 200, + "type": "string" + } + }, + "required": [ + "iccProfileBase64", + "outputConditionIdentifier" + ], + "type": "object" +} - added
Input schema / properties / pageSizeAdded value: +{ + "description": "Portrait page preset (points): A4 595.28×841.89 (default), Letter 612×792, Legal 612×1008, A3 841.89×1190.55, Tabloid 792×1224. print.* boxes must fit it.", + "enum": [ + "A4", + "Letter", + "Legal", + "A3", + "Tabloid" + ], + "type": "string" +} - changed
Input schema / properties / pdfA / descriptionPrevious value: -"Optional PDF/A conformance level (powered by pdfnative v1.2). Use 'pdfa1b' for archival of simple text+images, 'pdfa2b'/'pdfa2u' for richer content (2u guarantees Unicode mapping), 'pdfa3b' when embedding source attachments (Factur-X / ZUGFeRD). Mutually exclusive with PDF encryption. See docs/guides/PDFA.md."New value: +"PDF/A level: pdfa1b (simple text+images), pdfa2b/pdfa2u (richer; 2u = Unicode mapping), pdfa3b (attachments / Factur-X). Pair with embedFonts=true for a valid claim. Exclusive with encryption. See docs/guides/PDFA.md." - added
Input schema / properties / printAdded value: +{ + "additionalProperties": false, + "description": "Print production (ISO 32000-1 §14.11): page boxes, `bleed` shorthand (TrimBox = MediaBox inset), crop/registration marks outside the TrimBox, /UserUnit for large formats (PDF 1.7; not under pdfa1b). See docs/guides/PRINT.md.", + "properties": { + "artBox": { + "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.", + "items": { + "type": "number" + }, + "maxItems": 4, + "minItems": 4, + "type": "array" + }, + "bleed": { + "description": "Bleed in points (8.5 = 3 mm); sets TrimBox = MediaBox inset. Exclusive with trimBox.", + "exclusiveMinimum": 0, + "maximum": 200, + "type": "number" + }, + "bleedBox": { + "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.", + "items": { + "type": "number" + }, + "maxItems": 4, + "minItems": 4, + "type": "array" + }, + "cropBox": { + "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.", + "items": { + "type": "number" + }, + "maxItems": 4, + "minItems": 4, + "type": "array" + }, + "marks": { + "description": "Printer's marks (needs bleed or trimBox): true for defaults, or an object.", + "oneOf": [ + { + "type": "boolean" + }, + { + "additionalProperties": false, + "properties": { + "crop": { + "description": "Corner crop (trim) marks. Default true.", + "type": "boolean" + }, + "length": { + "description": "Mark length in points. Default 14.", + "maximum": 100, + "minimum": 1, + "type": "number" + }, + "offset": { + "description": "Gap between TrimBox and marks in points. Default 5.", + "maximum": 100, + "minimum": 0, + "type": "number" + }, + "registration": { + "description": "Edge-midpoint registration targets. Default true.", + "type": "boolean" + }, + "weight": { + "description": "Stroke width in points. Default 0.25.", + "maximum": 5, + "minimum": 0.05, + "type": "number" + } + }, + "type": "object" + } + ] + }, + "trimBox": { + "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.", + "items": { + "type": "number" + }, + "maxItems": 4, + "minItems": 4, + "type": "array" + }, + "userUnit": { + "description": "/UserUnit (multiples of 1/72 in) for pages over 14400 pt. Rejected under pdfa1b.", + "maximum": 75000, + "minimum": 1, + "type": "number" + } + }, + "type": "object" +} - added
Input schema / properties / strictAdded value: +{ + "default": false, + "description": "Fail with PDF_A_COMPLIANCE_VIOLATION instead of producing a non-conformant PDF/A file (e.g. PDFA_NO_FONT_ENTRIES without embedFonts). Pair with embedFonts=true.", + "type": "boolean" +} - changed
Output schema / descriptionPrevious value: -"Structured result of a PDF-producing tool. In base64 mode the PDF bytes are delivered out-of-band as an embedded `resource` content block (data: URI), NOT duplicated here, to keep responses token-frugal. In file mode `filePath` is the sandboxed absolute path."New value: +"Result of a PDF-producing tool. base64 mode: the PDF arrives as an embedded `resource` content block (not duplicated here); file mode: `filePath`." - added
Output schema / properties / diagnosticsAdded value: +{ + "description": "PDF/A diagnostics (when includeDiagnostics=true).", + "items": { + "additionalProperties": false, + "properties": { + "code": { + "type": "string" + }, + "message": { + "type": "string" + }, + "severity": { + "enum": [ + "warning" + ], + "type": "string" + } + }, + "required": [ + "code", + "message", + "severity" + ], + "type": "object" + }, + "type": "array" +} - changed
Output schema / properties / filePath / descriptionPrevious value: -"Absolute sandboxed file path (when mode='file')."New value: +"Sandboxed absolute path (file mode)." - added
Output schema / properties / summaryAdded value: +{ + "additionalProperties": true, + "description": "Tool-specific summary, when produced.", + "type": "object" +}
- Changed
encrypt_pdf9 fields changed- changed
Input schema / properties / algorithm / descriptionPrevious value: -"Content cipher: aes128 (V4/R4, widest compatibility) or aes256 (V5/R6, strongest)."New value: +"aes128 (V4/R4, widest compatibility) or aes256 (V5/R6)." - added
Input schema / properties / outputMode / descriptionAdded value: +"'base64' (default) returns the PDF inline; 'file' writes it inside the PDFNATIVE_MCP_OUTPUT_DIR sandbox (SECURITY_VIOLATION when the sandbox is not configured)." - changed
Input schema / properties / ownerPassword / descriptionPrevious value: -"Owner password (required, non-empty). Controls permissions and full access."New value: +"Owner password (full access)." - changed
Input schema / properties / permissions / descriptionPrevious value: -"Access permission flags (enforced by conforming readers). Each defaults to allowed when omitted."New value: +"Permission flags; each defaults to allowed." - changed
Input schema / properties / userPassword / descriptionPrevious value: -"User (open) password. Omitted or empty string means the document opens without a password prompt."New value: +"Open password; omitted/empty = opens without a prompt." - changed
Output schema / descriptionPrevious value: -"Structured result of a PDF-producing tool. In base64 mode the PDF bytes are delivered out-of-band as an embedded `resource` content block (data: URI), NOT duplicated here, to keep responses token-frugal. In file mode `filePath` is the sandboxed absolute path."New value: +"Result of a PDF-producing tool. base64 mode: the PDF arrives as an embedded `resource` content block (not duplicated here); file mode: `filePath`." - added
Output schema / properties / diagnosticsAdded value: +{ + "description": "PDF/A diagnostics (when includeDiagnostics=true).", + "items": { + "additionalProperties": false, + "properties": { + "code": { + "type": "string" + }, + "message": { + "type": "string" + }, + "severity": { + "enum": [ + "warning" + ], + "type": "string" + } + }, + "required": [ + "code", + "message", + "severity" + ], + "type": "object" + }, + "type": "array" +} - changed
Output schema / properties / filePath / descriptionPrevious value: -"Absolute sandboxed file path (when mode='file')."New value: +"Sandboxed absolute path (file mode)." - added
Output schema / properties / summaryAdded value: +{ + "additionalProperties": true, + "description": "Tool-specific summary, when produced.", + "type": "object" +}
- Added
extract_attachments - Added
extract_pages - Changed
extract_text7 fields changed- changed
Input schema / properties / password / descriptionPrevious value: -"Password to open an encrypted source PDF (user or owner — both are tried). Omit for unencrypted documents. Never logged or echoed back."New value: +"Password (user or owner) of an encrypted source. Never logged or echoed." - added
Output schema / descriptionAdded value: +"Structured text-extraction result. Every property is optional because the result can be projected: verbosity:'summary' returns only the scalar summary fields, fields:[...] keeps a dot-path subset. Defaults return the full shape." - added
Output schema / properties / charCountAdded value: +{ + "description": "summary only: length of fullText.", + "minimum": 0, + "type": "integer" +} - changed
Output schema / properties / extractableReason / descriptionPrevious value: -"Human-readable explanation when extractable=false. Absent when extractable=true."New value: +"Present when extractable is false: why no text could be decoded." - removed
Output schema / properties / pages / items / properties / runs / items / requiredRemoved value: -[ - "text", - "x", - "y", - "fontSize", - "fontName" -] - removed
Output schema / properties / pages / items / requiredRemoved value: -[ - "index", - "text" -] - removed
Output schema / requiredRemoved value: -[ - "pageCount", - "extractedPageCount", - "extractable", - "pages", - "fullText" -]
- Added
fill_form - Changed
generate_basic_pdf34 fields changed- changed
Input schema / properties / blocks / items / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "level": { - "enum": [ - 1, - 2, - 3 - ], - "type": "integer" - }, - "text": { - "maxLength": 500, - "minLength": 1, - "type": "string" - }, - "type": { - "const": "heading" - } - }, - "required": [ - "type", - "text", - "level" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "text": { - "description": "Paragraph text. Embedded newlines ('\\n') are automatically split into separate paragraphs — no need to pre-split; never emit a literal newline expecting a soft line break.", - "maxLength": 50000, - "minLength": 1, - "type": "string" - }, - "type": { - "const": "paragraph" - } - }, - "required": [ - "type", - "text" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "items": { - "description": "List items. A string is a leaf; an object { text, items } nests a sub-list (bullets/numbers indent; numbered sub-lists restart at 1).", - "items": { - "oneOf": [ - { - "maxLength": 1000, - "minLength": 1, - "type": "string" - }, - { - "additionalProperties": false, - "properties": { - "items": { - "items": { - "oneOf": [ - { - "maxLength": 1000, - "minLength": 1, - "type": "string" - }, - { - "additionalProperties": false, - "properties": { - "items": { - "items": { - "oneOf": [ - { - "maxLength": 1000, - "minLength": 1, - "type": "string" - }, - { - "additionalProperties": false, - "properties": { - "items": { - "items": { - "oneOf": [ - { - "maxLength": 1000, - "minLength": 1, - "type": "string" - }, - { - "additionalProperties": false, - "properties": { - "items": { - "items": { - "oneOf": [ - { - "maxLength": 1000, - "minLength": 1, - "type": "string" - }, - { - "additionalProperties": false, - "properties": { - "items": { - "items": { - "oneOf": [ - { - "maxLength": 1000, - "minLength": 1, - "type": "string" - }, - { - "additionalProperties": false, - "properties": { - "text": { - "maxLength": 1000, - "minLength": 1, - "type": "string" - } - }, - "required": [ - "text" - ], - "type": "object" - } - ] - }, - "maxItems": 1000, - "minItems": 1, - "type": "array" - }, - "text": { - "maxLength": 1000, - "minLength": 1, - "type": "string" - } - }, - "required": [ - "text" - ], - "type": "object" - } - ] - }, - "maxItems": 1000, - "minItems": 1, - "type": "array" - }, - "text": { - "maxLength": 1000, - "minLength": 1, - "type": "string" - } - }, - "required": [ - "text" - ], - "type": "object" - } - ] - }, - "maxItems": 1000, - "minItems": 1, - "type": "array" - }, - "text": { - "maxLength": 1000, - "minLength": 1, - "type": "string" - } - }, - "required": [ - "text" - ], - "type": "object" - } - ] - }, - "maxItems": 1000, - "minItems": 1, - "type": "array" - }, - "text": { - "maxLength": 1000, - "minLength": 1, - "type": "string" - } - }, - "required": [ - "text" - ], - "type": "object" - } - ] - }, - "maxItems": 1000, - "minItems": 1, - "type": "array" - }, - "text": { - "maxLength": 1000, - "minLength": 1, - "type": "string" - } - }, - "required": [ - "text" - ], - "type": "object" - } - ] - }, - "maxItems": 1000, - "minItems": 1, - "type": "array" - }, - "style": { - "default": "bullet", - "enum": [ - "bullet", - "numbered" - ], - "type": "string" - }, - "type": { - "const": "list" - } - }, - "required": [ - "type", - "items" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "type": { - "const": "pageBreak" - } - }, - "required": [ - "type" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "height": { - "maximum": 500, - "minimum": 1, - "type": "number" - }, - "type": { - "const": "spacer" - } - }, - "required": [ - "type", - "height" - ], - "type": "object" - }, - { - "additionalProperties": false, - "description": "Native vector chart (pdfnative v1.6.0) — bar / horizontal-bar / line / pie / donut, rendered as pure PDF path operators.", - "properties": { - "align": { - "description": "Horizontal alignment within the content width. Default 'left'.", - "enum": [ - "left", - "center", - "right" - ], - "type": "string" - }, - "altText": { - "description": "Alt text for the tagged-PDF /Figure /Alt. Auto-generated when omitted.", - "maxLength": 500, - "type": "string" - }, - "axis": { - "additionalProperties": false, - "description": "Value-axis options (bar/line only).", - "properties": { - "grid": { - "description": "Draw horizontal gridlines.", - "type": "boolean" - }, - "ticks": { - "description": "Target tick count (nice 1/2/5×10ⁿ steps).", - "maximum": 20, - "minimum": 2, - "type": "integer" - }, - "yMax": { - "description": "Force the axis maximum (values are clamped to the plot band).", - "type": "number" - }, - "yMin": { - "description": "Force the axis minimum (values are clamped to the plot band).", - "type": "number" - } - }, - "type": "object" - }, - "categories": { - "description": "Category / slice labels (x-axis). Defaults to 1-based indices when omitted.", - "items": { - "maxLength": 200, - "type": "string" - }, - "maxItems": 1000, - "type": "array" - }, - "chartType": { - "description": "Chart kind. 'pie'/'donut' use exactly one series; 'bar'/'barH'/'line' support multiple series.", - "enum": [ - "bar", - "barH", - "line", - "pie", - "donut" - ], - "type": "string" - }, - "colors": { - "description": "Palette override (per-series for bar/line, per-slice for pie/donut).", - "items": { - "description": "CSS-style hex colour, e.g. \"#3366cc\".", - "pattern": "^#?[0-9a-fA-F]{6}$", - "type": "string" - }, - "maxItems": 50, - "type": "array" - }, - "height": { - "description": "Plot-area height in points. Default 240.", - "maximum": 2000, - "minimum": 50, - "type": "number" - }, - "legend": { - "description": "Legend placement. Defaults to 'bottom' for multi-series/pie, else 'none'.", - "enum": [ - "bottom", - "none" - ], - "type": "string" - }, - "markers": { - "description": "Draw point markers on line series. Default false.", - "type": "boolean" - }, - "series": { - "description": "Data series. Pie/donut charts use exactly one series (each value becomes a slice).", - "items": { - "additionalProperties": false, - "properties": { - "color": { - "description": "CSS-style hex colour, e.g. \"#3366cc\".", - "pattern": "^#?[0-9a-fA-F]{6}$", - "type": "string" - }, - "label": { - "description": "Series label (shown in the legend).", - "maxLength": 200, - "minLength": 1, - "type": "string" - }, - "values": { - "description": "Numeric values, one per category. Negative values are supported for bar/line.", - "items": { - "type": "number" - }, - "maxItems": 1000, - "minItems": 1, - "type": "array" - } - }, - "required": [ - "label", - "values" - ], - "type": "object" - }, - "maxItems": 50, - "minItems": 1, - "type": "array" - }, - "title": { - "description": "Chart title rendered above the plot.", - "maxLength": 200, - "type": "string" - }, - "type": { - "const": "chart" - }, - "width": { - "description": "Plot width in points (clamped to content width). Default 460.", - "maximum": 2000, - "minimum": 50, - "type": "number" - } - }, - "required": [ - "type", - "chartType", - "series" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "level": { + "enum": [ + 1, + 2, + 3 + ], + "type": "integer" + }, + "text": { + "maxLength": 500, + "minLength": 1, + "type": "string" + }, + "type": { + "const": "heading" + } + }, + "required": [ + "type", + "text", + "level" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "text": { + "description": "Paragraph text. Embedded newlines ('\\n') are automatically split into separate paragraphs — no need to pre-split; never emit a literal newline expecting a soft line break.", + "maxLength": 50000, + "minLength": 1, + "type": "string" + }, + "type": { + "const": "paragraph" + } + }, + "required": [ + "type", + "text" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "items": { + "description": "List items. A string is a leaf; an object { text, items } nests a sub-list (bullets/numbers indent; numbered sub-lists restart at 1).", + "items": { + "oneOf": [ + { + "maxLength": 1000, + "minLength": 1, + "type": "string" + }, + { + "additionalProperties": false, + "properties": { + "items": { + "items": { + "oneOf": [ + { + "maxLength": 1000, + "minLength": 1, + "type": "string" + }, + { + "additionalProperties": false, + "properties": { + "items": { + "items": { + "oneOf": [ + { + "maxLength": 1000, + "minLength": 1, + "type": "string" + }, + { + "additionalProperties": false, + "properties": { + "items": { + "items": { + "oneOf": [ + { + "maxLength": 1000, + "minLength": 1, + "type": "string" + }, + { + "additionalProperties": false, + "properties": { + "items": { + "items": { + "oneOf": [ + { + "maxLength": 1000, + "minLength": 1, + "type": "string" + }, + { + "additionalProperties": false, + "properties": { + "items": { + "items": { + "oneOf": [ + { + "maxLength": 1000, + "minLength": 1, + "type": "string" + }, + { + "additionalProperties": false, + "properties": { + "text": { + "maxLength": 1000, + "minLength": 1, + "type": "string" + } + }, + "required": [ + "text" + ], + "type": "object" + } + ] + }, + "maxItems": 1000, + "minItems": 1, + "type": "array" + }, + "text": { + "maxLength": 1000, + "minLength": 1, + "type": "string" + } + }, + "required": [ + "text" + ], + "type": "object" + } + ] + }, + "maxItems": 1000, + "minItems": 1, + "type": "array" + }, + "text": { + "maxLength": 1000, + "minLength": 1, + "type": "string" + } + }, + "required": [ + "text" + ], + "type": "object" + } + ] + }, + "maxItems": 1000, + "minItems": 1, + "type": "array" + }, + "text": { + "maxLength": 1000, + "minLength": 1, + "type": "string" + } + }, + "required": [ + "text" + ], + "type": "object" + } + ] + }, + "maxItems": 1000, + "minItems": 1, + "type": "array" + }, + "text": { + "maxLength": 1000, + "minLength": 1, + "type": "string" + } + }, + "required": [ + "text" + ], + "type": "object" + } + ] + }, + "maxItems": 1000, + "minItems": 1, + "type": "array" + }, + "text": { + "maxLength": 1000, + "minLength": 1, + "type": "string" + } + }, + "required": [ + "text" + ], + "type": "object" + } + ] + }, + "maxItems": 1000, + "minItems": 1, + "type": "array" + }, + "style": { + "default": "bullet", + "enum": [ + "bullet", + "numbered" + ], + "type": "string" + }, + "type": { + "const": "list" + } + }, + "required": [ + "type", + "items" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "type": { + "const": "pageBreak" + } + }, + "required": [ + "type" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "height": { + "maximum": 500, + "minimum": 1, + "type": "number" + }, + "type": { + "const": "spacer" + } + }, + "required": [ + "type", + "height" + ], + "type": "object" + }, + { + "additionalProperties": false, + "description": "Native vector chart rendered as pure PDF path operators — bar / horizontal-bar / stacked-bar / line / area / scatter / pie / donut (pdfnative 1.7 charts v2: time and log axes, data labels, secondary axis, legends). Same body as add_chart.", + "properties": { + "align": { + "description": "Horizontal alignment within the content width. Default 'left'.", + "enum": [ + "left", + "center", + "right" + ], + "type": "string" + }, + "altText": { + "description": "Alt text for the tagged-PDF /Figure /Alt. Auto-generated when omitted.", + "maxLength": 500, + "type": "string" + }, + "axis": { + "additionalProperties": false, + "description": "Value-axis options (bar/line only).", + "properties": { + "grid": { + "description": "Draw horizontal gridlines.", + "type": "boolean" + }, + "scale": { + "description": "Value-axis scale. 'log' requires strictly positive values and is not available for stacked charts.", + "enum": [ + "linear", + "log" + ], + "type": "string" + }, + "ticks": { + "description": "Target tick count (nice 1/2/5×10ⁿ steps).", + "maximum": 20, + "minimum": 2, + "type": "integer" + }, + "yMax": { + "description": "Force the axis maximum (values are clamped to the plot band).", + "type": "number" + }, + "yMin": { + "description": "Force the axis minimum (values are clamped to the plot band).", + "type": "number" + } + }, + "type": "object" + }, + "axis2": { + "additionalProperties": false, + "description": "Secondary RIGHT value axis (drawn only when a series sets yAxis:'right').", + "properties": { + "scale": { + "enum": [ + "linear", + "log" + ], + "type": "string" + }, + "ticks": { + "maximum": 20, + "minimum": 2, + "type": "integer" + }, + "yMax": { + "type": "number" + }, + "yMin": { + "type": "number" + } + }, + "type": "object" + }, + "categories": { + "description": "Category / slice labels (x-axis). Defaults to 1-based indices when omitted.", + "items": { + "maxLength": 200, + "type": "string" + }, + "maxItems": 1000, + "type": "array" + }, + "chartType": { + "description": "Chart kind. 'pie'/'donut' use exactly one series; 'bar'/'barH'/'stackedBar'/'stackedBarH'/'line'/'area'/'scatter' support multiple series. 'scatter' requires xValues on every series and a positional xAxis.type ('linear' or 'time').", + "enum": [ + "bar", + "barH", + "stackedBar", + "stackedBarH", + "line", + "area", + "scatter", + "pie", + "donut" + ], + "type": "string" + }, + "colors": { + "description": "Palette override (per-series for bar/line, per-slice for pie/donut).", + "items": { + "description": "CSS-style hex colour, e.g. \"#3366cc\".", + "pattern": "^#?[0-9a-fA-F]{6}$", + "type": "string" + }, + "maxItems": 50, + "type": "array" + }, + "dataLabels": { + "description": "Per-point value labels: true for defaults, or an object to format them.", + "oneOf": [ + { + "type": "boolean" + }, + { + "additionalProperties": false, + "properties": { + "decimals": { + "maximum": 6, + "minimum": 0, + "type": "integer" + }, + "prefix": { + "maxLength": 16, + "type": "string" + }, + "suffix": { + "maxLength": 16, + "type": "string" + } + }, + "type": "object" + } + ] + }, + "height": { + "description": "Plot-area height in points. Default 240.", + "maximum": 2000, + "minimum": 50, + "type": "number" + }, + "labelRotation": { + "description": "Rotate category labels counter-clockwise by this many degrees (disables the automatic stride).", + "maximum": 90, + "minimum": 0, + "type": "number" + }, + "labelStride": { + "description": "Draw every Nth category label. Default: automatic (measured non-overlap); 1 draws every label.", + "maximum": 1000, + "minimum": 1, + "type": "integer" + }, + "legend": { + "description": "Legend placement. Defaults to 'bottom' for multi-series/pie, else 'none'.", + "enum": [ + "bottom", + "none" + ], + "type": "string" + }, + "markers": { + "description": "Draw point markers on line series. Default false.", + "type": "boolean" + }, + "series": { + "description": "Data series. Pie/donut charts use exactly one series (each value becomes a slice).", + "items": { + "additionalProperties": false, + "properties": { + "color": { + "description": "CSS-style hex colour, e.g. \"#3366cc\".", + "pattern": "^#?[0-9a-fA-F]{6}$", + "type": "string" + }, + "label": { + "description": "Series label (shown in the legend).", + "maxLength": 200, + "minLength": 1, + "type": "string" + }, + "values": { + "description": "Numeric values, one per category. Negative values are supported for bar/line.", + "items": { + "type": "number" + }, + "maxItems": 1000, + "minItems": 1, + "type": "array" + }, + "xValues": { + "description": "Per-point x positions (same length as values) for scatter charts and for line/area charts with xAxis.type 'linear' or 'time'.", + "items": { + "description": "Positional x value: a number (linear axis) or an ISO-8601 date / epoch milliseconds (time axis).", + "maxLength": 64, + "type": [ + "number", + "string" + ] + }, + "maxItems": 1000, + "minItems": 1, + "type": "array" + }, + "yAxis": { + "description": "Bind the series to the left (default) or the secondary right value axis (cartesian charts only; configure its range with 'axis2').", + "enum": [ + "left", + "right" + ], + "type": "string" + } + }, + "required": [ + "label", + "values" + ], + "type": "object" + }, + "maxItems": 50, + "minItems": 1, + "type": "array" + }, + "title": { + "description": "Chart title rendered above the plot.", + "maxLength": 200, + "type": "string" + }, + "type": { + "const": "chart" + }, + "width": { + "description": "Plot width in points (clamped to content width). Default 460.", + "maximum": 2000, + "minimum": 50, + "type": "number" + }, + "xAxis": { + "additionalProperties": false, + "description": "Horizontal axis. 'category' (default) positions points by index; 'linear' / 'time' position them by series xValues (line/area/scatter only). Time ticks are UTC-deterministic.", + "properties": { + "grid": { + "description": "Draw vertical gridlines.", + "type": "boolean" + }, + "max": { + "description": "Axis maximum (number, or ISO-8601 / epoch ms for time axes).", + "maxLength": 64, + "type": [ + "number", + "string" + ] + }, + "min": { + "description": "Axis minimum (number, or ISO-8601 / epoch ms for time axes).", + "maxLength": 64, + "type": [ + "number", + "string" + ] + }, + "ticks": { + "maximum": 20, + "minimum": 2, + "type": "integer" + }, + "type": { + "enum": [ + "category", + "linear", + "time" + ], + "type": "string" + } + }, + "type": "object" + } + }, + "required": [ + "type", + "chartType", + "series" + ], + "type": "object" + }, + { + "additionalProperties": false, + "description": "Inline smart table — same body as add_table (every row must have exactly as many cells as headers).", + "properties": { + "autoFitColumns": { + "description": "Auto-fit column widths to content. Output bytes then depend on text metrics (not byte-deterministic across content changes).", + "type": "boolean" + }, + "caption": { + "description": "Caption rendered above the table (tagged as /Caption under PDF/A).", + "maxLength": 200, + "type": "string" + }, + "cellBorders": { + "additionalProperties": false, + "description": "Per-cell vector borders (pure strokes, PDF/A-safe). Choose individual sides or `all`.", + "properties": { + "all": { + "description": "Draw all four edges (overrides the individual side flags).", + "type": "boolean" + }, + "bottom": { + "type": "boolean" + }, + "color": { + "description": "Stroke colour as a PDF operator string ('0.8 0.8 0.8') or hex. Default light grey.", + "type": "string" + }, + "left": { + "type": "boolean" + }, + "right": { + "type": "boolean" + }, + "style": { + "description": "Stroke style (default 'solid').", + "enum": [ + "solid", + "dashed", + "dotted" + ], + "type": "string" + }, + "top": { + "type": "boolean" + }, + "width": { + "description": "Stroke width in points (default 0.5).", + "maximum": 10, + "minimum": 0, + "type": "number" + } + }, + "type": "object" + }, + "cellPadding": { + "description": "Horizontal cell padding in points (default 3).", + "maximum": 50, + "minimum": 0, + "type": "number" + }, + "cellVAlign": { + "description": "Vertical alignment of cell content.", + "enum": [ + "top", + "middle", + "bottom" + ], + "type": "string" + }, + "clipCells": { + "description": "Clip cell contents to the column bounds (PDF clip operators). Recommended for PDF/A and visual safety.", + "type": "boolean" + }, + "headers": { + "description": "Column header labels. Must have the same length as each row in `rows`.", + "items": { + "maxLength": 200, + "minLength": 1, + "type": "string" + }, + "maxItems": 50, + "minItems": 1, + "type": "array" + }, + "minRowHeight": { + "description": "Minimum row height in points (default 12).", + "maximum": 200, + "minimum": 1, + "type": "number" + }, + "repeatHeader": { + "description": "Repeat the header row on every continuation page (default true).", + "type": "boolean" + }, + "rows": { + "description": "Data rows. Each row is an array of cell strings with the same length as `headers`.", + "items": { + "items": { + "maxLength": 500, + "type": "string" + }, + "maxItems": 50, + "minItems": 1, + "type": "array" + }, + "maxItems": 5000, + "minItems": 1, + "type": "array" + }, + "type": { + "const": "table" + }, + "wrap": { + "description": "Cell wrap policy: 'auto' (default) wraps only overflowing cells; 'always' wraps every cell; 'never' truncates.", + "enum": [ + "auto", + "always", + "never" + ], + "type": "string" + }, + "zebra": { + "description": "Alternate-row light tint (static fill, PDF/A-1b safe).", + "type": "boolean" + } + }, + "required": [ + "type", + "headers", + "rows" + ], + "type": "object" + }, + { + "additionalProperties": false, + "description": "Inline JPEG/PNG image. Without width/height the pixel size is used as points and clamped to the content width; with one dimension the aspect ratio is kept. The decoded bytes of all image blocks in one call are capped at 24 MiB (a watermark image has its own 8 MiB cap).", + "properties": { + "align": { + "default": "left", + "description": "Horizontal placement inside the content width.", + "enum": [ + "left", + "center", + "right" + ], + "type": "string" + }, + "alt": { + "description": "Accessible description (tagged /Figure /Alt). Always provide it for non-decorative content under PDF/A or PDF/UA.", + "maxLength": 500, + "type": "string" + }, + "height": { + "description": "Render height in points.", + "maximum": 1000, + "minimum": 10, + "type": "number" + }, + "imageBase64": { + "description": "Base64 image bytes. JPEG (baseline; 1, 3 or 4 components — CMYK raises PDFA_DEVICE_CMYK_IMAGE under PDF/A) or PNG (8-bit greyscale/RGB, non-interlaced; alpha-channel and palette PNGs are rejected with a remedy). No data: URI.", + "maxLength": 12000000, + "minLength": 4, + "type": "string" + }, + "mimeType": { + "description": "MIME type of the image. Must match the actual encoding of imageBase64 (magic bytes are checked).", + "enum": [ + "image/jpeg", + "image/png" + ], + "type": "string" + }, + "type": { + "const": "image" + }, + "width": { + "description": "Render width in points.", + "maximum": 800, + "minimum": 10, + "type": "number" + } + }, + "required": [ + "type", + "imageBase64", + "mimeType" + ], + "type": "object" + }, + { + "additionalProperties": false, + "description": "Clickable external link (/URI action). Only http:, https: and mailto: URLs are accepted.", + "properties": { + "color": { + "description": "Hex colour (#RGB or #RRGGBB).", + "pattern": "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$", + "type": "string" + }, + "fontSize": { + "description": "Default 10.", + "maximum": 48, + "minimum": 6, + "type": "number" + }, + "text": { + "maxLength": 500, + "minLength": 1, + "type": "string" + }, + "type": { + "const": "link" + }, + "url": { + "description": "http(s):// or mailto: URL.", + "maxLength": 2048, + "minLength": 1, + "type": "string" + } + }, + "required": [ + "type", + "text", + "url" + ], + "type": "object" + }, + { + "additionalProperties": false, + "description": "Printed table of contents generated from the document's heading blocks (internal /GoTo links with dot leaders). Pairs with outline:'auto' for the bookmark pane.", + "properties": { + "fontSize": { + "description": "Default 10.", + "maximum": 24, + "minimum": 6, + "type": "number" + }, + "indent": { + "description": "Points of indent per heading level (default 15).", + "maximum": 100, + "minimum": 0, + "type": "number" + }, + "maxLevel": { + "description": "Deepest heading level listed (default 3).", + "enum": [ + 1, + 2, + 3 + ], + "type": "integer" + }, + "title": { + "description": "Default 'Table of Contents'.", + "maxLength": 200, + "type": "string" + }, + "type": { + "const": "toc" + } + }, + "required": [ + "type" + ], + "type": "object" + }, + { + "additionalProperties": false, + "description": "Inline barcode — same body as add_barcode (pure vector, no /Alt available in the engine).", + "properties": { + "align": { + "default": "left", + "description": "Horizontal placement inside the content width.", + "enum": [ + "left", + "center", + "right" + ], + "type": "string" + }, + "data": { + "description": "Raw payload to encode — do NOT URL-encode. For QR/URL pass e.g. \"https://example.com\" verbatim. EAN-13 must be 12 or 13 digits (13th is auto-computed). Code 128 accepts ASCII alphanumerics.", + "maxLength": 4296, + "minLength": 1, + "type": "string" + }, + "ecLevel": { + "default": "M", + "description": "QR ONLY. Error correction level (L=7%, M=15%, Q=25%, H=30%). Ignored for code128/ean13/datamatrix/pdf417. Use H for printed media that may get smudged or partially covered (e.g. logo overlay).", + "enum": [ + "L", + "M", + "Q", + "H" + ], + "type": "string" + }, + "format": { + "description": "Barcode symbology to render.", + "enum": [ + "qr", + "code128", + "ean13", + "datamatrix", + "pdf417" + ], + "type": "string" + }, + "height": { + "default": 200, + "description": "Barcode height in PDF points (ignored for square symbologies like QR/Data Matrix).", + "maximum": 500, + "minimum": 30, + "type": "number" + }, + "type": { + "const": "barcode" + }, + "width": { + "default": 200, + "description": "Barcode width in PDF points.", + "maximum": 500, + "minimum": 30, + "type": "number" + } + }, + "required": [ + "type", + "format", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "description": "Vector drawing from an SVG path `d` string or SVG markup. Supported: <path> <rect> (rx/ry) <circle> <ellipse> <line> <polyline> <polygon> and <text>/<tspan> (x, y, font-size, fill, text-anchor, dx/dy); fill / stroke / stroke-width attributes; double-quoted attributes only. NOT supported (silently ignored): transform, <g>, <use>, <image>, <defs>/<clipPath>, gradients, opacity, CSS/style, dash patterns, text word-wrap. No external reference is ever fetched (no XML parser: entities other than & < > " ' &#n; are dropped). Pure path operators — PDF/A-safe at every level.", + "properties": { + "align": { + "default": "left", + "description": "Horizontal placement inside the content width.", + "enum": [ + "left", + "center", + "right" + ], + "type": "string" + }, + "alt": { + "description": "Accessible description (tagged /Figure /Alt). Always provide it for non-decorative content under PDF/A or PDF/UA.", + "maxLength": 500, + "type": "string" + }, + "data": { + "description": "Path `d` string or SVG markup (≤ 100 000 characters).", + "maxLength": 100000, + "minLength": 1, + "type": "string" + }, + "fill": { + "description": "Hex colour or 'none' (default black).", + "pattern": "^(?:none|#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}))$", + "type": "string" + }, + "height": { + "description": "Render height in points (default 200).", + "maximum": 1000, + "minimum": 10, + "type": "number" + }, + "stroke": { + "description": "Hex colour or 'none' (default none).", + "pattern": "^(?:none|#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}))$", + "type": "string" + }, + "strokeWidth": { + "description": "Stroke width in SVG user units (default 1).", + "maximum": 50, + "minimum": 0, + "type": "number" + }, + "type": { + "const": "svg" + }, + "viewBox": { + "description": "[minX, minY, width, height] — overrides the viewBox of the markup; required for a bare path string that is not 0-based.", + "items": { + "type": "number" + }, + "maxItems": 4, + "minItems": 4, + "type": "array" + }, + "width": { + "description": "Render width in points (default 200).", + "maximum": 800, + "minimum": 10, + "type": "number" + } + }, + "required": [ + "type", + "data" + ], + "type": "object" + }, + { + "additionalProperties": false, + "description": "Inline AcroForm field — same body as an add_form field. Under a PDF/A claim the widget appearance font is not embedded (PDFA_UNEMBEDDED_FORM_FONT; strict:true fails the call).", + "properties": { + "checked": { + "description": "Initial checked state for checkbox / radio fields.", + "type": "boolean" + }, + "fieldType": { + "description": "Type of form control to render. Radio fields sharing a name form one radio group.", + "enum": [ + "text", + "textarea", + "checkbox", + "radio", + "dropdown", + "listbox" + ], + "type": "string" + }, + "fontSize": { + "description": "Font size for text rendering inside the field.", + "maximum": 48, + "minimum": 6, + "type": "number" + }, + "height": { + "description": "Field height in points (default depends on the type).", + "maximum": 300, + "minimum": 10, + "type": "number" + }, + "label": { + "description": "Human-readable label shown above the field.", + "maxLength": 200, + "type": "string" + }, + "maxLength": { + "description": "Maximum character length for text/textarea fields.", + "maximum": 32767, + "minimum": 1, + "type": "integer" + }, + "name": { + "description": "Unique field name used as the PDF annotation identifier (/T).", + "maxLength": 100, + "minLength": 1, + "type": "string" + }, + "options": { + "description": "Choices for dropdown, listbox or radio fields.", + "items": { + "maxLength": 200, + "type": "string" + }, + "maxItems": 100, + "type": "array" + }, + "placeholder": { + "description": "Hint text shown while the field is empty.", + "maxLength": 200, + "type": "string" + }, + "readOnly": { + "description": "Prevent editing of this field.", + "type": "boolean" + }, + "required": { + "description": "Mark field as required.", + "type": "boolean" + }, + "type": { + "const": "formField" + }, + "value": { + "description": "Default value pre-filled in the field.", + "maxLength": 2000, + "type": "string" + }, + "width": { + "description": "Field width in points (default: full content width).", + "maximum": 500, + "minimum": 10, + "type": "number" + } + }, + "required": [ + "type", + "fieldType", + "name" + ], + "type": "object" + } +] - added
Input schema / properties / compressAdded value: +{ + "description": "FlateDecode the streams (smaller file, different bytes; PDF/A unaffected, XMP stays plain). Default false.", + "type": "boolean" +} - added
Input schema / properties / creationDateAdded value: +{ + "description": "ISO-8601 instant for /CreationDate (+ XMP). Pin it for byte-identical output across calls (same host TZ); omitted = wall clock, so every call differs.", + "format": "date-time", + "type": "string" +} - added
Input schema / properties / debugAdded value: +{ + "description": "Draw margin / block / cell guide rectangles (unmarked content — not for PDF/UA output). Geometry unchanged. Default false.", + "type": "boolean" +} - added
Input schema / properties / embedFontsAdded value: +{ + "default": false, + "description": "Embed Noto Sans Latin instead of the viewer base-14 Helvetica. REQUIRED for a valid PDF/A claim (ISO 19005 §6.2.11.4.1) and for strict=true; adds ~0.3 MiB.", + "type": "boolean" +} - added
Input schema / properties / encryptAdded value: +{ + "additionalProperties": false, + "description": "Encrypt at build time (AES-128 default / AES-256) and KEEP the AcroForm — unlike encrypt_pdf, which rebuilds the page tree. Exclusive with pdfA. Randomised output, never cached.", + "properties": { + "algorithm": { + "default": "aes128", + "description": "aes128 (V4/R4, widest compatibility) or aes256 (V5/R6).", + "enum": [ + "aes128", + "aes256" + ], + "type": "string" + }, + "ownerPassword": { + "description": "Owner password (full access).", + "maxLength": 4096, + "minLength": 1, + "type": "string" + }, + "permissions": { + "additionalProperties": false, + "description": "Permission flags; each defaults to allowed.", + "properties": { + "copy": { + "type": "boolean" + }, + "extractText": { + "type": "boolean" + }, + "modify": { + "type": "boolean" + }, + "print": { + "type": "boolean" + } + }, + "type": "object" + }, + "userPassword": { + "description": "Open password; omitted/empty = opens without a prompt.", + "maxLength": 4096, + "type": "string" + } + }, + "required": [ + "ownerPassword" + ], + "type": "object" +} - added
Input schema / properties / footerTemplateAdded value: +{ + "additionalProperties": false, + "description": "Running footer on every page. Replaces the default footer: footerText is then ignored and page numbers appear only via {page}/{pages}.", + "properties": { + "center": { + "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).", + "maxLength": 200, + "type": "string" + }, + "color": { + "description": "Hex colour.", + "pattern": "^#[0-9a-fA-F]{6}$", + "type": "string" + }, + "fontSize": { + "description": "Default 7.", + "maximum": 14, + "minimum": 6, + "type": "number" + }, + "left": { + "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).", + "maxLength": 200, + "type": "string" + }, + "right": { + "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).", + "maxLength": 200, + "type": "string" + } + }, + "type": "object" +} - added
Input schema / properties / headerTemplateAdded value: +{ + "additionalProperties": false, + "description": "Running header on every page (left / center / right zones); reserves 15 pt.", + "properties": { + "center": { + "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).", + "maxLength": 200, + "type": "string" + }, + "color": { + "description": "Hex colour.", + "pattern": "^#[0-9a-fA-F]{6}$", + "type": "string" + }, + "fontSize": { + "description": "Default 7.", + "maximum": 14, + "minimum": 6, + "type": "number" + }, + "left": { + "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).", + "maxLength": 200, + "type": "string" + }, + "right": { + "description": "Placeholders: {page} {pages} {title} {date} (build-day wall clock, not creationDate).", + "maxLength": 200, + "type": "string" + } + }, + "type": "object" +} - added
Input schema / properties / includeDiagnosticsAdded value: +{ + "default": false, + "description": "Return the PDF/A diagnostics raised while building as `diagnostics[]` (possibly empty).", + "type": "boolean" +} - added
Input schema / properties / marginsAdded value: +{ + "additionalProperties": false, + "description": "Margins in points, all four required (0–200). Default 45 / 36 / 35 / 36.", + "properties": { + "bottom": { + "maximum": 200, + "minimum": 0, + "type": "number" + }, + "left": { + "maximum": 200, + "minimum": 0, + "type": "number" + }, + "right": { + "maximum": 200, + "minimum": 0, + "type": "number" + }, + "top": { + "maximum": 200, + "minimum": 0, + "type": "number" + } + }, + "required": [ + "top", + "right", + "bottom", + "left" + ], + "type": "object" +} - added
Input schema / properties / metadataAdded value: +{ + "additionalProperties": false, + "description": "/Info (+ XMP under PDF/A): author, subject, keywords, /Trapped.", + "properties": { + "author": { + "maxLength": 500, + "type": "string" + }, + "keywords": { + "maxLength": 1000, + "type": "string" + }, + "subject": { + "maxLength": 1000, + "type": "string" + }, + "trapped": { + "description": "/Trapped print flag.", + "enum": [ + "True", + "False", + "Unknown" + ], + "type": "string" + } + }, + "type": "object" +} - changed
Input schema / properties / normalize / descriptionPrevious value: -"Optional Unicode normalization applied to all rendered text before shaping. 'NFC' (recommended) composes base + combining marks into precomposed code points for better glyph coverage; 'NFD'/'NFKC'/'NFKD' are also accepted. Omit for byte-stable output (no normalization)."New value: +"Unicode normalization before shaping ('NFC' recommended for glyph coverage; NFD/NFKC/NFKD accepted). Omit = none." - added
Input schema / properties / outputIntentAdded value: +{ + "additionalProperties": false, + "description": "Custom PDF/A OutputIntent: an RGB ICC profile + condition strings replacing the built-in sRGB intent (CMYK rejected).", + "properties": { + "iccProfileBase64": { + "description": "ICC profile bytes, base64 (RGB, ≤ 8 MiB).", + "maxLength": 11000000, + "minLength": 1, + "type": "string" + }, + "info": { + "maxLength": 500, + "type": "string" + }, + "outputCondition": { + "maxLength": 200, + "type": "string" + }, + "outputConditionIdentifier": { + "description": "e.g. \"sRGB IEC61966-2.1\".", + "maxLength": 200, + "minLength": 1, + "type": "string" + }, + "registryName": { + "description": "Default \"http://www.color.org\".", + "maxLength": 200, + "type": "string" + } + }, + "required": [ + "iccProfileBase64", + "outputConditionIdentifier" + ], + "type": "object" +} - added
Input schema / properties / pageSizeAdded value: +{ + "description": "Portrait page preset (points): A4 595.28×841.89 (default), Letter 612×792, Legal 612×1008, A3 841.89×1190.55, Tabloid 792×1224. print.* boxes must fit it.", + "enum": [ + "A4", + "Letter", + "Legal", + "A3", + "Tabloid" + ], + "type": "string" +} - changed
Input schema / properties / pdfA / descriptionPrevious value: -"Optional PDF/A conformance level (powered by pdfnative v1.2). Use 'pdfa1b' for archival of simple text+images, 'pdfa2b'/'pdfa2u' for richer content (2u guarantees Unicode mapping), 'pdfa3b' when embedding source attachments (Factur-X / ZUGFeRD). Mutually exclusive with PDF encryption. See docs/guides/PDFA.md."New value: +"PDF/A level: pdfa1b (simple text+images), pdfa2b/pdfa2u (richer; 2u = Unicode mapping), pdfa3b (attachments / Factur-X). Pair with embedFonts=true for a valid claim. Exclusive with encryption. See docs/guides/PDFA.md." - added
Input schema / properties / printAdded value: +{ + "additionalProperties": false, + "description": "Print production (ISO 32000-1 §14.11): page boxes, `bleed` shorthand (TrimBox = MediaBox inset), crop/registration marks outside the TrimBox, /UserUnit for large formats (PDF 1.7; not under pdfa1b). See docs/guides/PRINT.md.", + "properties": { + "artBox": { + "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.", + "items": { + "type": "number" + }, + "maxItems": 4, + "minItems": 4, + "type": "array" + }, + "bleed": { + "description": "Bleed in points (8.5 = 3 mm); sets TrimBox = MediaBox inset. Exclusive with trimBox.", + "exclusiveMinimum": 0, + "maximum": 200, + "type": "number" + }, + "bleedBox": { + "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.", + "items": { + "type": "number" + }, + "maxItems": 4, + "minItems": 4, + "type": "array" + }, + "cropBox": { + "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.", + "items": { + "type": "number" + }, + "maxItems": 4, + "minItems": 4, + "type": "array" + }, + "marks": { + "description": "Printer's marks (needs bleed or trimBox): true for defaults, or an object.", + "oneOf": [ + { + "type": "boolean" + }, + { + "additionalProperties": false, + "properties": { + "crop": { + "description": "Corner crop (trim) marks. Default true.", + "type": "boolean" + }, + "length": { + "description": "Mark length in points. Default 14.", + "maximum": 100, + "minimum": 1, + "type": "number" + }, + "offset": { + "description": "Gap between TrimBox and marks in points. Default 5.", + "maximum": 100, + "minimum": 0, + "type": "number" + }, + "registration": { + "description": "Edge-midpoint registration targets. Default true.", + "type": "boolean" + }, + "weight": { + "description": "Stroke width in points. Default 0.25.", + "maximum": 5, + "minimum": 0.05, + "type": "number" + } + }, + "type": "object" + } + ] + }, + "trimBox": { + "description": "[x0, y0, x1, y1] in points, origin bottom-left, inside the MediaBox.", + "items": { + "type": "number" + }, + "maxItems": 4, + "minItems": 4, + "type": "array" + }, + "userUnit": { + "description": "/UserUnit (multiples of 1/72 in) for pages over 14400 pt. Rejected under pdfa1b.", + "maximum": 75000, + "minimum": 1, + "type": "number" + } + }, + "type": "object" +} - added
Input schema / properties / strictAdded value: +{ + "default": false, + "description": "Fail with PDF_A_COMPLIANCE_VIOLATION instead of producing a non-conformant PDF/A file (e.g. PDFA_NO_FONT_ENTRIES without embedFonts). Pair with embedFonts=true.", + "type": "boolean" +} - added
Input schema / properties / viewerPreferences / properties / duplexAdded value: +{ + "description": "Print-dialog paper handling default (/Duplex): single-sided or double-sided flipping on the short/long edge.", + "enum": [ + "simplex", + "duplexFlipShortEdge", + "duplexFlipLongEdge" + ], + "type": "string" +} - added
Input schema / properties / viewerPreferences / properties / numCopiesAdded value: +{ + "description": "Default number of copies for the Print dialog (/NumCopies; viewers honour 2-5 per ISO 32000 Table 150).", + "maximum": 1000, + "minimum": 1, + "type": "integer" +} - added
Input schema / properties / viewerPreferences / properties / pickTrayByPDFSizeAdded value: +{ + "description": "Ask the printer to pick the input tray from the PDF page size (/PickTrayByPDFSize).", + "type": "boolean" +} - added
Input schema / properties / viewerPreferences / properties / printPageRangeAdded value: +{ + "description": "Default page ranges for the Print dialog (/PrintPageRange) as inclusive 1-based [first, last] pairs, e.g. [[1, 4], [7, 7]].", + "items": { + "items": { + "minimum": 1, + "type": "integer" + }, + "maxItems": 2, + "minItems": 2, + "type": "array" + }, + "maxItems": 100, + "type": "array" +} - changed
Input schema / properties / watermark / descriptionPrevious value: -"Optional semi-transparent text watermark rendered on every page (e.g. 'DRAFT', 'CONFIDENTIAL'). Text only in this version. opacity < 1.0 is rejected under pdfA='pdfa1b' (ISO 19005-1 forbids transparency)."New value: +"Optional semi-transparent watermark rendered centred on every page: `text` (e.g. 'DRAFT'), `image` (JPEG/PNG), or both combined. At least one of text / image is required. opacity < 1.0 (text or image, including the defaults) is rejected under pdfA='pdfa1b' (ISO 19005-1 forbids transparency)." - changed
Input schema / properties / watermark / properties / angle / descriptionPrevious value: -"Rotation in degrees (counterclockwise). Default -45."New value: +"Text rotation in degrees (counterclockwise). Default -45." - changed
Input schema / properties / watermark / properties / color / descriptionPrevious value: -"RGB colour as a [r, g, b] triple in the 0.0–1.0 range. Default light gray [0.75, 0.75, 0.75]."New value: +"Text RGB colour as a [r, g, b] triple in the 0.0–1.0 range. Default light gray [0.75, 0.75, 0.75]." - changed
Input schema / properties / watermark / properties / fontSize / descriptionPrevious value: -"Font size in points. Default 60, auto-fit to the page."New value: +"Text font size in points. Default 60, auto-fit to the page." - added
Input schema / properties / watermark / properties / imageAdded value: +{ + "additionalProperties": false, + "description": "Image watermark (JPEG or PNG) centred on every page, optionally combined with `text`. Bytes are validated against the JPEG/PNG magic numbers; mimeType must match.", + "properties": { + "height": { + "description": "Display height in points (default: from the image pixel size).", + "exclusiveMinimum": 0, + "maximum": 14400, + "type": "number" + }, + "imageBase64": { + "description": "Base64-encoded JPEG or 8-bit opaque PNG bytes (max 8 MiB decoded; alpha-channel, palette and interlaced PNGs are rejected with a remedy). Plain base64, no data: URI prefix.", + "maxLength": 12000000, + "minLength": 4, + "type": "string" + }, + "mimeType": { + "description": "'image/jpeg' or 'image/png' — must match the actual bytes.", + "enum": [ + "image/jpeg", + "image/png" + ], + "type": "string" + }, + "opacity": { + "description": "Image opacity 0.0–1.0. Default 0.10.", + "maximum": 1, + "minimum": 0, + "type": "number" + }, + "width": { + "description": "Display width in points (default: from the image pixel size).", + "exclusiveMinimum": 0, + "maximum": 14400, + "type": "number" + } + }, + "required": [ + "imageBase64", + "mimeType" + ], + "type": "object" +} - changed
Input schema / properties / watermark / properties / opacity / descriptionPrevious value: -"Opacity 0.0–1.0. Default 0.15."New value: +"Text opacity 0.0–1.0. Default 0.15. (Image opacity is image.opacity.)" - changed
Input schema / properties / watermark / properties / position / descriptionPrevious value: -"'background' (behind page content, default) or 'foreground' (above it)."New value: +"'background' (behind page content, default) or 'foreground' (above it). Applies to text and image alike." - changed
Input schema / properties / watermark / properties / text / descriptionPrevious value: -"Watermark text."New value: +"Watermark text. Optional when `image` is given." - removed
Input schema / properties / watermark / requiredRemoved value: -[ - "text" -] - changed
Output schema / descriptionPrevious value: -"Structured result of a PDF-producing tool. In base64 mode the PDF bytes are delivered out-of-band as an embedded `resource` content block (data: URI), NOT duplicated here, to keep responses token-frugal. In file mode `filePath` is the sandboxed absolute path."New value: +"Result of a PDF-producing tool. base64 mode: the PDF arrives as an embedded `resource` content block (not duplicated here); file mode: `filePath`." - added
Output schema / properties / diagnosticsAdded value: +{ + "description": "PDF/A diagnostics (when includeDiagnostics=true).", + "items": { + "additionalProperties": false, + "properties": { + "code": { + "type": "string" + }, + "message": { + "type": "string" + }, + "severity": { + "enum": [ + "warning" + ], + "type": "string" + } + }, + "required": [ + "code", + "message", + "severity" + ], + "type": "object" + }, + "type": "array" +} - changed
Output schema / properties / filePath / descriptionPrevious value: -"Absolute sandboxed file path (when mode='file')."New value: +"Sandboxed absolute path (file mode)." - added
Output schema / properties / summaryAdded value: +{ + "additionalProperties": true, + "description": "Tool-specific summary, when produced.", + "type": "object" +}
- Added
inspect_layout - Added
inspect_pdf - Added
merge_pdfs - Added
prepare_signature_placeholder - Added
read_form_fields - Added
sign_pdf - Changed
split_pdf8 fields changed- changed
Input schema / properties / encrypt / descriptionPrevious value: -"Re-encrypt the produced PDF with the PDF Standard Security Handler (AES-128 V4/R4 default, or AES-256 V5/R6). RC4 is never emitted. Requires a Web Crypto CSPRNG. Applied to every produced range."New value: +"Re-encrypt the output (Standard Security Handler; AES-128 default or AES-256; RC4 never emitted). Applied to every produced range." - changed
Input schema / properties / encrypt / properties / algorithm / descriptionPrevious value: -"Content cipher: aes128 (V4/R4, widest compatibility) or aes256 (V5/R6, strongest)."New value: +"aes128 (V4/R4, widest compatibility) or aes256 (V5/R6)." - changed
Input schema / properties / encrypt / properties / ownerPassword / descriptionPrevious value: -"Owner password (required, non-empty). Controls permissions and full access."New value: +"Owner password (full access)." - changed
Input schema / properties / encrypt / properties / permissions / descriptionPrevious value: -"Access permission flags (enforced by conforming readers). Each defaults to allowed when omitted."New value: +"Permission flags; each defaults to allowed." - changed
Input schema / properties / encrypt / properties / userPassword / descriptionPrevious value: -"User (open) password. Omitted or empty string means the document opens without a password prompt."New value: +"Open password; omitted/empty = opens without a prompt." - added
Input schema / properties / outputMode / descriptionAdded value: +"'base64' (default) returns the PDF inline; 'file' writes it inside the PDFNATIVE_MCP_OUTPUT_DIR sandbox (SECURITY_VIOLATION when the sandbox is not configured)." - changed
Input schema / properties / password / descriptionPrevious value: -"Password to open an encrypted source PDF (user or owner — both are tried). Omit for unencrypted documents. Never logged or echoed back."New value: +"Password (user or owner) of an encrypted source. Never logged or echoed." - changed
Output schema / properties / parts / items / properties / filePath / descriptionPrevious value: -"Absolute sandboxed file path (when mode='file')."New value: +"Sandboxed absolute path (file mode)."
- Added
timestamp_pdf - Added
update_metadata - Added
validate_pdf - Added
verify_pdf
14 tool updates
v1.6.0- Added
add_chart - Added
decrypt_pdf - Added
encrypt_pdf - Removed
extract_attachments - Removed
extract_pages - Changed
extract_text5 fields changed- added
Input schema / properties / includeRunsAdded value: +{ + "default": false, + "description": "When true, each page also carries `runs[]` — positioned text-showing operations `{ text, x, y, fontSize, fontName }` in device space (content-stream order). Useful for layout-aware extraction; larger responses.", + "type": "boolean" +} - added
Input schema / properties / maxTextLengthAdded value: +{ + "description": "Hard cap on total extracted characters across all pages (memory bound for adversarial input). Default 16000000. Exceeding it fails with OUTPUT_TOO_LARGE.", + "minimum": 1, + "type": "integer" +} - added
Input schema / properties / passwordAdded value: +{ + "description": "Password to open an encrypted source PDF (user or owner — both are tried). Omit for unencrypted documents. Never logged or echoed back.", + "maxLength": 4096, + "minLength": 1, + "type": "string" +} - changed
Output schema / properties / extractable / descriptionPrevious value: -"False when one or more requested pages had a non-empty content stream but yielded no extractable text (likely subset fonts without /ToUnicode)."New value: +"False when one or more requested pages produced text that is entirely U+FFFD replacement characters — a font with no usable /ToUnicode CMap or base encoding. Blank pages are still considered extractable." - added
Output schema / properties / pages / items / properties / runsAdded value: +{ + "description": "Positioned text runs (present only when includeRuns is true).", + "items": { + "additionalProperties": false, + "properties": { + "fontName": { + "type": "string" + }, + "fontSize": { + "type": "number" + }, + "text": { + "type": "string" + }, + "x": { + "type": "number" + }, + "y": { + "type": "number" + } + }, + "required": [ + "text", + "x", + "y", + "fontSize", + "fontName" + ], + "type": "object" + }, + "type": "array" +}
- Changed
generate_basic_pdf1 field changed- changed
Input schema / properties / blocks / items / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "level": { - "enum": [ - 1, - 2, - 3 - ], - "type": "integer" - }, - "text": { - "maxLength": 500, - "minLength": 1, - "type": "string" - }, - "type": { - "const": "heading" - } - }, - "required": [ - "type", - "text", - "level" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "text": { - "description": "Paragraph text. Embedded newlines ('\\n') are automatically split into separate paragraphs — no need to pre-split; never emit a literal newline expecting a soft line break.", - "maxLength": 50000, - "minLength": 1, - "type": "string" - }, - "type": { - "const": "paragraph" - } - }, - "required": [ - "type", - "text" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "items": { - "description": "List items. A string is a leaf; an object { text, items } nests a sub-list (bullets/numbers indent; numbered sub-lists restart at 1).", - "items": { - "oneOf": [ - { - "maxLength": 1000, - "minLength": 1, - "type": "string" - }, - { - "additionalProperties": false, - "properties": { - "items": { - "items": { - "oneOf": [ - { - "maxLength": 1000, - "minLength": 1, - "type": "string" - }, - { - "additionalProperties": false, - "properties": { - "items": { - "items": { - "oneOf": [ - { - "maxLength": 1000, - "minLength": 1, - "type": "string" - }, - { - "additionalProperties": false, - "properties": { - "items": { - "items": { - "oneOf": [ - { - "maxLength": 1000, - "minLength": 1, - "type": "string" - }, - { - "additionalProperties": false, - "properties": { - "items": { - "items": { - "oneOf": [ - { - "maxLength": 1000, - "minLength": 1, - "type": "string" - }, - { - "additionalProperties": false, - "properties": { - "items": { - "items": { - "oneOf": [ - { - "maxLength": 1000, - "minLength": 1, - "type": "string" - }, - { - "additionalProperties": false, - "properties": { - "text": { - "maxLength": 1000, - "minLength": 1, - "type": "string" - } - }, - "required": [ - "text" - ], - "type": "object" - } - ] - }, - "maxItems": 1000, - "minItems": 1, - "type": "array" - }, - "text": { - "maxLength": 1000, - "minLength": 1, - "type": "string" - } - }, - "required": [ - "text" - ], - "type": "object" - } - ] - }, - "maxItems": 1000, - "minItems": 1, - "type": "array" - }, - "text": { - "maxLength": 1000, - "minLength": 1, - "type": "string" - } - }, - "required": [ - "text" - ], - "type": "object" - } - ] - }, - "maxItems": 1000, - "minItems": 1, - "type": "array" - }, - "text": { - "maxLength": 1000, - "minLength": 1, - "type": "string" - } - }, - "required": [ - "text" - ], - "type": "object" - } - ] - }, - "maxItems": 1000, - "minItems": 1, - "type": "array" - }, - "text": { - "maxLength": 1000, - "minLength": 1, - "type": "string" - } - }, - "required": [ - "text" - ], - "type": "object" - } - ] - }, - "maxItems": 1000, - "minItems": 1, - "type": "array" - }, - "text": { - "maxLength": 1000, - "minLength": 1, - "type": "string" - } - }, - "required": [ - "text" - ], - "type": "object" - } - ] - }, - "maxItems": 1000, - "minItems": 1, - "type": "array" - }, - "style": { - "default": "bullet", - "enum": [ - "bullet", - "numbered" - ], - "type": "string" - }, - "type": { - "const": "list" - } - }, - "required": [ - "type", - "items" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "type": { - "const": "pageBreak" - } - }, - "required": [ - "type" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "height": { - "maximum": 500, - "minimum": 1, - "type": "number" - }, - "type": { - "const": "spacer" - } - }, - "required": [ - "type", - "height" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "level": { + "enum": [ + 1, + 2, + 3 + ], + "type": "integer" + }, + "text": { + "maxLength": 500, + "minLength": 1, + "type": "string" + }, + "type": { + "const": "heading" + } + }, + "required": [ + "type", + "text", + "level" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "text": { + "description": "Paragraph text. Embedded newlines ('\\n') are automatically split into separate paragraphs — no need to pre-split; never emit a literal newline expecting a soft line break.", + "maxLength": 50000, + "minLength": 1, + "type": "string" + }, + "type": { + "const": "paragraph" + } + }, + "required": [ + "type", + "text" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "items": { + "description": "List items. A string is a leaf; an object { text, items } nests a sub-list (bullets/numbers indent; numbered sub-lists restart at 1).", + "items": { + "oneOf": [ + { + "maxLength": 1000, + "minLength": 1, + "type": "string" + }, + { + "additionalProperties": false, + "properties": { + "items": { + "items": { + "oneOf": [ + { + "maxLength": 1000, + "minLength": 1, + "type": "string" + }, + { + "additionalProperties": false, + "properties": { + "items": { + "items": { + "oneOf": [ + { + "maxLength": 1000, + "minLength": 1, + "type": "string" + }, + { + "additionalProperties": false, + "properties": { + "items": { + "items": { + "oneOf": [ + { + "maxLength": 1000, + "minLength": 1, + "type": "string" + }, + { + "additionalProperties": false, + "properties": { + "items": { + "items": { + "oneOf": [ + { + "maxLength": 1000, + "minLength": 1, + "type": "string" + }, + { + "additionalProperties": false, + "properties": { + "items": { + "items": { + "oneOf": [ + { + "maxLength": 1000, + "minLength": 1, + "type": "string" + }, + { + "additionalProperties": false, + "properties": { + "text": { + "maxLength": 1000, + "minLength": 1, + "type": "string" + } + }, + "required": [ + "text" + ], + "type": "object" + } + ] + }, + "maxItems": 1000, + "minItems": 1, + "type": "array" + }, + "text": { + "maxLength": 1000, + "minLength": 1, + "type": "string" + } + }, + "required": [ + "text" + ], + "type": "object" + } + ] + }, + "maxItems": 1000, + "minItems": 1, + "type": "array" + }, + "text": { + "maxLength": 1000, + "minLength": 1, + "type": "string" + } + }, + "required": [ + "text" + ], + "type": "object" + } + ] + }, + "maxItems": 1000, + "minItems": 1, + "type": "array" + }, + "text": { + "maxLength": 1000, + "minLength": 1, + "type": "string" + } + }, + "required": [ + "text" + ], + "type": "object" + } + ] + }, + "maxItems": 1000, + "minItems": 1, + "type": "array" + }, + "text": { + "maxLength": 1000, + "minLength": 1, + "type": "string" + } + }, + "required": [ + "text" + ], + "type": "object" + } + ] + }, + "maxItems": 1000, + "minItems": 1, + "type": "array" + }, + "text": { + "maxLength": 1000, + "minLength": 1, + "type": "string" + } + }, + "required": [ + "text" + ], + "type": "object" + } + ] + }, + "maxItems": 1000, + "minItems": 1, + "type": "array" + }, + "style": { + "default": "bullet", + "enum": [ + "bullet", + "numbered" + ], + "type": "string" + }, + "type": { + "const": "list" + } + }, + "required": [ + "type", + "items" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "type": { + "const": "pageBreak" + } + }, + "required": [ + "type" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "height": { + "maximum": 500, + "minimum": 1, + "type": "number" + }, + "type": { + "const": "spacer" + } + }, + "required": [ + "type", + "height" + ], + "type": "object" + }, + { + "additionalProperties": false, + "description": "Native vector chart (pdfnative v1.6.0) — bar / horizontal-bar / line / pie / donut, rendered as pure PDF path operators.", + "properties": { + "align": { + "description": "Horizontal alignment within the content width. Default 'left'.", + "enum": [ + "left", + "center", + "right" + ], + "type": "string" + }, + "altText": { + "description": "Alt text for the tagged-PDF /Figure /Alt. Auto-generated when omitted.", + "maxLength": 500, + "type": "string" + }, + "axis": { + "additionalProperties": false, + "description": "Value-axis options (bar/line only).", + "properties": { + "grid": { + "description": "Draw horizontal gridlines.", + "type": "boolean" + }, + "ticks": { + "description": "Target tick count (nice 1/2/5×10ⁿ steps).", + "maximum": 20, + "minimum": 2, + "type": "integer" + }, + "yMax": { + "description": "Force the axis maximum (values are clamped to the plot band).", + "type": "number" + }, + "yMin": { + "description": "Force the axis minimum (values are clamped to the plot band).", + "type": "number" + } + }, + "type": "object" + }, + "categories": { + "description": "Category / slice labels (x-axis). Defaults to 1-based indices when omitted.", + "items": { + "maxLength": 200, + "type": "string" + }, + "maxItems": 1000, + "type": "array" + }, + "chartType": { + "description": "Chart kind. 'pie'/'donut' use exactly one series; 'bar'/'barH'/'line' support multiple series.", + "enum": [ + "bar", + "barH", + "line", + "pie", + "donut" + ], + "type": "string" + }, + "colors": { + "description": "Palette override (per-series for bar/line, per-slice for pie/donut).", + "items": { + "description": "CSS-style hex colour, e.g. \"#3366cc\".", + "pattern": "^#?[0-9a-fA-F]{6}$", + "type": "string" + }, + "maxItems": 50, + "type": "array" + }, + "height": { + "description": "Plot-area height in points. Default 240.", + "maximum": 2000, + "minimum": 50, + "type": "number" + }, + "legend": { + "description": "Legend placement. Defaults to 'bottom' for multi-series/pie, else 'none'.", + "enum": [ + "bottom", + "none" + ], + "type": "string" + }, + "markers": { + "description": "Draw point markers on line series. Default false.", + "type": "boolean" + }, + "series": { + "description": "Data series. Pie/donut charts use exactly one series (each value becomes a slice).", + "items": { + "additionalProperties": false, + "properties": { + "color": { + "description": "CSS-style hex colour, e.g. \"#3366cc\".", + "pattern": "^#?[0-9a-fA-F]{6}$", + "type": "string" + }, + "label": { + "description": "Series label (shown in the legend).", + "maxLength": 200, + "minLength": 1, + "type": "string" + }, + "values": { + "description": "Numeric values, one per category. Negative values are supported for bar/line.", + "items": { + "type": "number" + }, + "maxItems": 1000, + "minItems": 1, + "type": "array" + } + }, + "required": [ + "label", + "values" + ], + "type": "object" + }, + "maxItems": 50, + "minItems": 1, + "type": "array" + }, + "title": { + "description": "Chart title rendered above the plot.", + "maxLength": 200, + "type": "string" + }, + "type": { + "const": "chart" + }, + "width": { + "description": "Plot width in points (clamped to content width). Default 460.", + "maximum": 2000, + "minimum": 50, + "type": "number" + } + }, + "required": [ + "type", + "chartType", + "series" + ], + "type": "object" + } +]
- Removed
inspect_pdf - Removed
merge_pdfs - Removed
prepare_signature_placeholder - Removed
sign_pdf - Changed
split_pdf3 fields changed- added
Input schema / properties / encryptAdded value: +{ + "additionalProperties": false, + "description": "Re-encrypt the produced PDF with the PDF Standard Security Handler (AES-128 V4/R4 default, or AES-256 V5/R6). RC4 is never emitted. Requires a Web Crypto CSPRNG. Applied to every produced range.", + "properties": { + "algorithm": { + "default": "aes128", + "description": "Content cipher: aes128 (V4/R4, widest compatibility) or aes256 (V5/R6, strongest).", + "enum": [ + "aes128", + "aes256" + ], + "type": "string" + }, + "ownerPassword": { + "description": "Owner password (required, non-empty). Controls permissions and full access.", + "maxLength": 4096, + "minLength": 1, + "type": "string" + }, + "permissions": { + "additionalProperties": false, + "description": "Access permission flags (enforced by conforming readers). Each defaults to allowed when omitted.", + "properties": { + "copy": { + "type": "boolean" + }, + "extractText": { + "type": "boolean" + }, + "modify": { + "type": "boolean" + }, + "print": { + "type": "boolean" + } + }, + "type": "object" + }, + "userPassword": { + "description": "User (open) password. Omitted or empty string means the document opens without a password prompt.", + "maxLength": 4096, + "type": "string" + } + }, + "required": [ + "ownerPassword" + ], + "type": "object" +} - added
Input schema / properties / passwordAdded value: +{ + "description": "Password to open an encrypted source PDF (user or owner — both are tried). Omit for unencrypted documents. Never logged or echoed back.", + "maxLength": 4096, + "minLength": 1, + "type": "string" +} - changed
Input schema / properties / pdfBase64 / descriptionPrevious value: -"Base64-encoded source PDF. Must not be encrypted."New value: +"Base64-encoded source PDF. Pass `password` for an encrypted source."
- Removed
validate_pdf - Removed
verify_pdf
4 tool updates
v1.4.0- Changed
add_international_text1 field changed- changed
Input schema / properties / lang / oneOfPrevious value: -[ - { - "enum": [ - "ar", - "he", - "th", - "ja", - "zh", - "ko", - "el", - "hi", - "bn", - "ta", - "ru", - "ka", - "hy", - "tr", - "pl", - "vi", - "latin", - "te", - "si", - "bo", - "km", - "my", - "am", - "emoji" - ], - "type": "string" - }, - { - "items": { - "enum": [ - "ar", - "he", - "th", - "ja", - "zh", - "ko", - "el", - "hi", - "bn", - "ta", - "ru", - "ka", - "hy", - "tr", - "pl", - "vi", - "latin", - "te", - "si", - "bo", - "km", - "my", - "am", - "emoji" - ], - "type": "string" - }, - "maxItems": 24, - "minItems": 1, - "type": "array" - }, - { - "description": "Comma-separated list of supported codes.", - "maxLength": 80, - "minLength": 2, - "type": "string" - } -]New value: +[ + { + "enum": [ + "ar", + "he", + "th", + "ja", + "zh", + "ko", + "el", + "hi", + "bn", + "ta", + "ru", + "ka", + "hy", + "tr", + "pl", + "vi", + "latin", + "te", + "si", + "bo", + "km", + "my", + "am", + "emoji", + "math" + ], + "type": "string" + }, + { + "items": { + "enum": [ + "ar", + "he", + "th", + "ja", + "zh", + "ko", + "el", + "hi", + "bn", + "ta", + "ru", + "ka", + "hy", + "tr", + "pl", + "vi", + "latin", + "te", + "si", + "bo", + "km", + "my", + "am", + "emoji", + "math" + ], + "type": "string" + }, + "maxItems": 25, + "minItems": 1, + "type": "array" + }, + { + "description": "Comma-separated list of supported codes.", + "maxLength": 80, + "minLength": 2, + "type": "string" + } +]
- Added
annotate_pdf - Added
draft_governance_issue - Changed
inspect_pdf1 field changed- added
Output schema / properties / pageLabelsAdded value: +{ + "description": "Logical page-numbering ranges from the /PageLabels number tree (ISO 32000-1 §12.4.2), or absent when the document has none. Each range gives the 0-based first page, numbering style, optional prefix and start value.", + "items": { + "additionalProperties": false, + "properties": { + "prefix": { + "type": "string" + }, + "start": { + "type": "integer" + }, + "startPage": { + "minimum": 0, + "type": "integer" + }, + "style": { + "enum": [ + "decimal", + "roman", + "Roman", + "alpha", + "Alpha", + "none" + ], + "type": "string" + } + }, + "required": [ + "startPage" + ], + "type": "object" + }, + "type": "array" +}
6 tool updates
v1.2.2- Changed
add_international_text1 field changed- added
Input schema / properties / viewerPreferencesAdded value: +{ + "additionalProperties": false, + "description": "Reader presentation hints (catalog /PageLayout, /PageMode, /ViewerPreferences). PDF/A-safe; all optional.", + "properties": { + "centerWindow": { + "type": "boolean" + }, + "direction": { + "enum": [ + "l2r", + "r2l" + ], + "type": "string" + }, + "displayDocTitle": { + "type": "boolean" + }, + "fitWindow": { + "type": "boolean" + }, + "hideMenubar": { + "type": "boolean" + }, + "hideToolbar": { + "type": "boolean" + }, + "hideWindowUI": { + "type": "boolean" + }, + "nonFullScreenPageMode": { + "enum": [ + "useNone", + "useOutlines", + "useThumbs", + "useOC" + ], + "type": "string" + }, + "pageLayout": { + "enum": [ + "singlePage", + "oneColumn", + "twoColumnLeft", + "twoColumnRight", + "twoPageLeft", + "twoPageRight" + ], + "type": "string" + }, + "pageMode": { + "enum": [ + "useNone", + "useOutlines", + "useThumbs", + "fullScreen", + "useOC", + "useAttachments" + ], + "type": "string" + }, + "printScaling": { + "enum": [ + "none", + "appDefault" + ], + "type": "string" + } + }, + "type": "object" +}
- Changed
add_table3 fields changed- added
Input schema / properties / cellBordersAdded value: +{ + "additionalProperties": false, + "description": "Per-cell vector borders (pdfnative v1.4). Switches the backend to buildDocumentPDFBytes. Choose individual sides or `all`.", + "properties": { + "all": { + "description": "Draw all four edges (overrides the individual side flags).", + "type": "boolean" + }, + "bottom": { + "type": "boolean" + }, + "color": { + "description": "Stroke colour as a PDF operator string ('0.8 0.8 0.8') or hex. Default light grey.", + "type": "string" + }, + "left": { + "type": "boolean" + }, + "right": { + "type": "boolean" + }, + "style": { + "description": "Stroke style (default 'solid').", + "enum": [ + "solid", + "dashed", + "dotted" + ], + "type": "string" + }, + "top": { + "type": "boolean" + }, + "width": { + "description": "Stroke width in points (default 0.5).", + "maximum": 10, + "minimum": 0, + "type": "number" + } + }, + "type": "object" +} - added
Input schema / properties / cellVAlignAdded value: +{ + "description": "Vertical alignment of cell content (pdfnative v1.4). Switches the backend to buildDocumentPDFBytes.", + "enum": [ + "top", + "middle", + "bottom" + ], + "type": "string" +} - added
Input schema / properties / viewerPreferencesAdded value: +{ + "additionalProperties": false, + "description": "Reader presentation hints (catalog /PageLayout, /PageMode, /ViewerPreferences). PDF/A-safe; all optional.", + "properties": { + "centerWindow": { + "type": "boolean" + }, + "direction": { + "enum": [ + "l2r", + "r2l" + ], + "type": "string" + }, + "displayDocTitle": { + "type": "boolean" + }, + "fitWindow": { + "type": "boolean" + }, + "hideMenubar": { + "type": "boolean" + }, + "hideToolbar": { + "type": "boolean" + }, + "hideWindowUI": { + "type": "boolean" + }, + "nonFullScreenPageMode": { + "enum": [ + "useNone", + "useOutlines", + "useThumbs", + "useOC" + ], + "type": "string" + }, + "pageLayout": { + "enum": [ + "singlePage", + "oneColumn", + "twoColumnLeft", + "twoColumnRight", + "twoPageLeft", + "twoPageRight" + ], + "type": "string" + }, + "pageMode": { + "enum": [ + "useNone", + "useOutlines", + "useThumbs", + "fullScreen", + "useOC", + "useAttachments" + ], + "type": "string" + }, + "printScaling": { + "enum": [ + "none", + "appDefault" + ], + "type": "string" + } + }, + "type": "object" +}
- Added
extract_pages - Changed
generate_basic_pdf4 fields changed- changed
Input schema / properties / blocks / items / oneOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "level": { - "enum": [ - 1, - 2, - 3 - ], - "type": "integer" - }, - "text": { - "maxLength": 500, - "minLength": 1, - "type": "string" - }, - "type": { - "const": "heading" - } - }, - "required": [ - "type", - "text", - "level" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "text": { - "description": "Paragraph text. Embedded newlines ('\\n') are automatically split into separate paragraphs — no need to pre-split; never emit a literal newline expecting a soft line break.", - "maxLength": 50000, - "minLength": 1, - "type": "string" - }, - "type": { - "const": "paragraph" - } - }, - "required": [ - "type", - "text" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "items": { - "items": { - "maxLength": 1000, - "minLength": 1, - "type": "string" - }, - "maxItems": 1000, - "minItems": 1, - "type": "array" - }, - "style": { - "default": "bullet", - "enum": [ - "bullet", - "numbered" - ], - "type": "string" - }, - "type": { - "const": "list" - } - }, - "required": [ - "type", - "items" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "type": { - "const": "pageBreak" - } - }, - "required": [ - "type" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "height": { - "maximum": 500, - "minimum": 1, - "type": "number" - }, - "type": { - "const": "spacer" - } - }, - "required": [ - "type", - "height" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "level": { + "enum": [ + 1, + 2, + 3 + ], + "type": "integer" + }, + "text": { + "maxLength": 500, + "minLength": 1, + "type": "string" + }, + "type": { + "const": "heading" + } + }, + "required": [ + "type", + "text", + "level" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "text": { + "description": "Paragraph text. Embedded newlines ('\\n') are automatically split into separate paragraphs — no need to pre-split; never emit a literal newline expecting a soft line break.", + "maxLength": 50000, + "minLength": 1, + "type": "string" + }, + "type": { + "const": "paragraph" + } + }, + "required": [ + "type", + "text" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "items": { + "description": "List items. A string is a leaf; an object { text, items } nests a sub-list (bullets/numbers indent; numbered sub-lists restart at 1).", + "items": { + "oneOf": [ + { + "maxLength": 1000, + "minLength": 1, + "type": "string" + }, + { + "additionalProperties": false, + "properties": { + "items": { + "items": { + "oneOf": [ + { + "maxLength": 1000, + "minLength": 1, + "type": "string" + }, + { + "additionalProperties": false, + "properties": { + "items": { + "items": { + "oneOf": [ + { + "maxLength": 1000, + "minLength": 1, + "type": "string" + }, + { + "additionalProperties": false, + "properties": { + "items": { + "items": { + "oneOf": [ + { + "maxLength": 1000, + "minLength": 1, + "type": "string" + }, + { + "additionalProperties": false, + "properties": { + "items": { + "items": { + "oneOf": [ + { + "maxLength": 1000, + "minLength": 1, + "type": "string" + }, + { + "additionalProperties": false, + "properties": { + "items": { + "items": { + "oneOf": [ + { + "maxLength": 1000, + "minLength": 1, + "type": "string" + }, + { + "additionalProperties": false, + "properties": { + "text": { + "maxLength": 1000, + "minLength": 1, + "type": "string" + } + }, + "required": [ + "text" + ], + "type": "object" + } + ] + }, + "maxItems": 1000, + "minItems": 1, + "type": "array" + }, + "text": { + "maxLength": 1000, + "minLength": 1, + "type": "string" + } + }, + "required": [ + "text" + ], + "type": "object" + } + ] + }, + "maxItems": 1000, + "minItems": 1, + "type": "array" + }, + "text": { + "maxLength": 1000, + "minLength": 1, + "type": "string" + } + }, + "required": [ + "text" + ], + "type": "object" + } + ] + }, + "maxItems": 1000, + "minItems": 1, + "type": "array" + }, + "text": { + "maxLength": 1000, + "minLength": 1, + "type": "string" + } + }, + "required": [ + "text" + ], + "type": "object" + } + ] + }, + "maxItems": 1000, + "minItems": 1, + "type": "array" + }, + "text": { + "maxLength": 1000, + "minLength": 1, + "type": "string" + } + }, + "required": [ + "text" + ], + "type": "object" + } + ] + }, + "maxItems": 1000, + "minItems": 1, + "type": "array" + }, + "text": { + "maxLength": 1000, + "minLength": 1, + "type": "string" + } + }, + "required": [ + "text" + ], + "type": "object" + } + ] + }, + "maxItems": 1000, + "minItems": 1, + "type": "array" + }, + "style": { + "default": "bullet", + "enum": [ + "bullet", + "numbered" + ], + "type": "string" + }, + "type": { + "const": "list" + } + }, + "required": [ + "type", + "items" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "type": { + "const": "pageBreak" + } + }, + "required": [ + "type" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "height": { + "maximum": 500, + "minimum": 1, + "type": "number" + }, + "type": { + "const": "spacer" + } + }, + "required": [ + "type", + "height" + ], + "type": "object" + } +] - added
Input schema / properties / outlineAdded value: +{ + "description": "Document outline (bookmarks panel). Either 'auto' (derive a flat outline from heading blocks) or an explicit nested bookmark tree.", + "oneOf": [ + { + "enum": [ + "auto" + ], + "type": "string" + }, + { + "items": { + "additionalProperties": false, + "properties": { + "bold": { + "type": "boolean" + }, + "children": { + "items": { + "additionalProperties": false, + "properties": { + "bold": { + "type": "boolean" + }, + "children": { + "items": { + "additionalProperties": false, + "properties": { + "bold": { + "type": "boolean" + }, + "children": { + "items": { + "additionalProperties": false, + "properties": { + "bold": { + "type": "boolean" + }, + "children": { + "items": { + "additionalProperties": false, + "properties": { + "bold": { + "type": "boolean" + }, + "children": { + "items": { + "additionalProperties": false, + "properties": { + "bold": { + "type": "boolean" + }, + "color": { + "description": "Label colour as a hex string ('#1a73e8') or PDF operator string ('0 0 1').", + "type": "string" + }, + "italic": { + "type": "boolean" + }, + "open": { + "description": "Initial expansion state (default true). false renders the branch collapsed.", + "type": "boolean" + }, + "pageIndex": { + "description": "0-based destination page index.", + "minimum": 0, + "type": "integer" + }, + "title": { + "description": "Bookmark label.", + "maxLength": 500, + "minLength": 1, + "type": "string" + }, + "y": { + "description": "Destination Y coordinate in points (default: top of page).", + "type": "number" + } + }, + "required": [ + "title", + "pageIndex" + ], + "type": "object" + }, + "maxItems": 1000, + "type": "array" + }, + "color": { + "description": "Label colour as a hex string ('#1a73e8') or PDF operator string ('0 0 1').", + "type": "string" + }, + "italic": { + "type": "boolean" + }, + "open": { + "description": "Initial expansion state (default true). false renders the branch collapsed.", + "type": "boolean" + }, + "pageIndex": { + "description": "0-based destination page index.", + "minimum": 0, + "type": "integer" + }, + "title": { + "description": "Bookmark label.", + "maxLength": 500, + "minLength": 1, + "type": "string" + }, + "y": { + "description": "Destination Y coordinate in points (default: top of page).", + "type": "number" + } + }, + "required": [ + "title", + "pageIndex" + ], + "type": "object" + }, + "maxItems": 1000, + "type": "array" + }, + "color": { + "description": "Label colour as a hex string ('#1a73e8') or PDF operator string ('0 0 1').", + "type": "string" + }, + "italic": { + "type": "boolean" + }, + "open": { + "description": "Initial expansion state (default true). false renders the branch collapsed.", + "type": "boolean" + }, + "pageIndex": { + "description": "0-based destination page index.", + "minimum": 0, + "type": "integer" + }, + "title": { + "description": "Bookmark label.", + "maxLength": 500, + "minLength": 1, + "type": "string" + }, + "y": { + "description": "Destination Y coordinate in points (default: top of page).", + "type": "number" + } + }, + "required": [ + "title", + "pageIndex" + ], + "type": "object" + }, + "maxItems": 1000, + "type": "array" + }, + "color": { + "description": "Label colour as a hex string ('#1a73e8') or PDF operator string ('0 0 1').", + "type": "string" + }, + "italic": { + "type": "boolean" + }, + "open": { + "description": "Initial expansion state (default true). false renders the branch collapsed.", + "type": "boolean" + }, + "pageIndex": { + "description": "0-based destination page index.", + "minimum": 0, + "type": "integer" + }, + "title": { + "description": "Bookmark label.", + "maxLength": 500, + "minLength": 1, + "type": "string" + }, + "y": { + "description": "Destination Y coordinate in points (default: top of page).", + "type": "number" + } + }, + "required": [ + "title", + "pageIndex" + ], + "type": "object" + }, + "maxItems": 1000, + "type": "array" + }, + "color": { + "description": "Label colour as a hex string ('#1a73e8') or PDF operator string ('0 0 1').", + "type": "string" + }, + "italic": { + "type": "boolean" + }, + "open": { + "description": "Initial expansion state (default true). false renders the branch collapsed.", + "type": "boolean" + }, + "pageIndex": { + "description": "0-based destination page index.", + "minimum": 0, + "type": "integer" + }, + "title": { + "description": "Bookmark label.", + "maxLength": 500, + "minLength": 1, + "type": "string" + }, + "y": { + "description": "Destination Y coordinate in points (default: top of page).", + "type": "number" + } + }, + "required": [ + "title", + "pageIndex" + ], + "type": "object" + }, + "maxItems": 1000, + "type": "array" + }, + "color": { + "description": "Label colour as a hex string ('#1a73e8') or PDF operator string ('0 0 1').", + "type": "string" + }, + "italic": { + "type": "boolean" + }, + "open": { + "description": "Initial expansion state (default true). false renders the branch collapsed.", + "type": "boolean" + }, + "pageIndex": { + "description": "0-based destination page index.", + "minimum": 0, + "type": "integer" + }, + "title": { + "description": "Bookmark label.", + "maxLength": 500, + "minLength": 1, + "type": "string" + }, + "y": { + "description": "Destination Y coordinate in points (default: top of page).", + "type": "number" + } + }, + "required": [ + "title", + "pageIndex" + ], + "type": "object" + }, + "maxItems": 1000, + "minItems": 1, + "type": "array" + } + ] +} - added
Input schema / properties / pageLabelsAdded value: +{ + "description": "Page-label ranges (the visible page numbers in the viewer, e.g. roman front-matter then decimal body). startPage values must be unique and strictly increasing.", + "items": { + "additionalProperties": false, + "properties": { + "prefix": { + "description": "Optional label prefix (e.g. 'A-').", + "maxLength": 64, + "type": "string" + }, + "start": { + "description": "First numeric value in the range (default 1).", + "minimum": 1, + "type": "integer" + }, + "startPage": { + "description": "0-based index of the first page in this range.", + "minimum": 0, + "type": "integer" + }, + "style": { + "description": "Numbering style. 'none' (or omitted with a prefix) yields prefix-only labels.", + "enum": [ + "decimal", + "roman", + "Roman", + "alpha", + "Alpha", + "none" + ], + "type": "string" + } + }, + "required": [ + "startPage" + ], + "type": "object" + }, + "maxItems": 1000, + "minItems": 1, + "type": "array" +} - added
Input schema / properties / viewerPreferencesAdded value: +{ + "additionalProperties": false, + "description": "Reader presentation hints (catalog /PageLayout, /PageMode, /ViewerPreferences). PDF/A-safe; all optional.", + "properties": { + "centerWindow": { + "type": "boolean" + }, + "direction": { + "enum": [ + "l2r", + "r2l" + ], + "type": "string" + }, + "displayDocTitle": { + "type": "boolean" + }, + "fitWindow": { + "type": "boolean" + }, + "hideMenubar": { + "type": "boolean" + }, + "hideToolbar": { + "type": "boolean" + }, + "hideWindowUI": { + "type": "boolean" + }, + "nonFullScreenPageMode": { + "enum": [ + "useNone", + "useOutlines", + "useThumbs", + "useOC" + ], + "type": "string" + }, + "pageLayout": { + "enum": [ + "singlePage", + "oneColumn", + "twoColumnLeft", + "twoColumnRight", + "twoPageLeft", + "twoPageRight" + ], + "type": "string" + }, + "pageMode": { + "enum": [ + "useNone", + "useOutlines", + "useThumbs", + "fullScreen", + "useOC", + "useAttachments" + ], + "type": "string" + }, + "printScaling": { + "enum": [ + "none", + "appDefault" + ], + "type": "string" + } + }, + "type": "object" +}
- Added
merge_pdfs - Added
split_pdf
14 tool updates
v1.2.0- Changed
add_attachment2 fields changed- added
Output schema / descriptionAdded value: +"Structured result of a PDF-producing tool. In base64 mode the PDF bytes are delivered out-of-band as an embedded `resource` content block (data: URI), NOT duplicated here, to keep responses token-frugal. In file mode `filePath` is the sandboxed absolute path." - removed
Output schema / properties / base64Removed value: -{ - "description": "Base64-encoded PDF bytes (when mode='base64').", - "type": "string" -}
- Changed
add_barcode2 fields changed- added
Output schema / descriptionAdded value: +"Structured result of a PDF-producing tool. In base64 mode the PDF bytes are delivered out-of-band as an embedded `resource` content block (data: URI), NOT duplicated here, to keep responses token-frugal. In file mode `filePath` is the sandboxed absolute path." - removed
Output schema / properties / base64Removed value: -{ - "description": "Base64-encoded PDF bytes (when mode='base64').", - "type": "string" -}
- Changed
add_form2 fields changed- added
Output schema / descriptionAdded value: +"Structured result of a PDF-producing tool. In base64 mode the PDF bytes are delivered out-of-band as an embedded `resource` content block (data: URI), NOT duplicated here, to keep responses token-frugal. In file mode `filePath` is the sandboxed absolute path." - removed
Output schema / properties / base64Removed value: -{ - "description": "Base64-encoded PDF bytes (when mode='base64').", - "type": "string" -}
- Changed
add_international_text3 fields changed- added
Input schema / properties / normalizeAdded value: +{ + "description": "Unicode normalization form applied before shaping. Defaults to 'NFC' (recommended for international scripts: composes decomposed sequences for the widest glyph coverage). Override with 'NFD'/'NFKC'/'NFKD' only for specialised needs.", + "enum": [ + "NFC", + "NFD", + "NFKC", + "NFKD" + ], + "type": "string" +} - added
Output schema / descriptionAdded value: +"Structured result of a PDF-producing tool. In base64 mode the PDF bytes are delivered out-of-band as an embedded `resource` content block (data: URI), NOT duplicated here, to keep responses token-frugal. In file mode `filePath` is the sandboxed absolute path." - removed
Output schema / properties / base64Removed value: -{ - "description": "Base64-encoded PDF bytes (when mode='base64').", - "type": "string" -}
- Changed
add_table3 fields changed- added
Input schema / properties / watermarkAdded value: +{ + "additionalProperties": false, + "description": "Optional semi-transparent text watermark rendered on every page (e.g. 'DRAFT', 'CONFIDENTIAL'). Text only in this version. opacity < 1.0 is rejected under pdfA='pdfa1b' (ISO 19005-1 forbids transparency).", + "properties": { + "angle": { + "description": "Rotation in degrees (counterclockwise). Default -45.", + "maximum": 360, + "minimum": -360, + "type": "number" + }, + "color": { + "description": "RGB colour as a [r, g, b] triple in the 0.0–1.0 range. Default light gray [0.75, 0.75, 0.75].", + "items": { + "maximum": 1, + "minimum": 0, + "type": "number" + }, + "maxItems": 3, + "minItems": 3, + "type": "array" + }, + "fontSize": { + "description": "Font size in points. Default 60, auto-fit to the page.", + "maximum": 300, + "minimum": 6, + "type": "number" + }, + "opacity": { + "description": "Opacity 0.0–1.0. Default 0.15.", + "maximum": 1, + "minimum": 0, + "type": "number" + }, + "position": { + "default": "background", + "description": "'background' (behind page content, default) or 'foreground' (above it).", + "enum": [ + "background", + "foreground" + ], + "type": "string" + }, + "text": { + "description": "Watermark text.", + "maxLength": 100, + "minLength": 1, + "type": "string" + } + }, + "required": [ + "text" + ], + "type": "object" +} - added
Output schema / descriptionAdded value: +"Structured result of a PDF-producing tool. In base64 mode the PDF bytes are delivered out-of-band as an embedded `resource` content block (data: URI), NOT duplicated here, to keep responses token-frugal. In file mode `filePath` is the sandboxed absolute path." - removed
Output schema / properties / base64Removed value: -{ - "description": "Base64-encoded PDF bytes (when mode='base64').", - "type": "string" -}
- Changed
embed_image2 fields changed- added
Output schema / descriptionAdded value: +"Structured result of a PDF-producing tool. In base64 mode the PDF bytes are delivered out-of-band as an embedded `resource` content block (data: URI), NOT duplicated here, to keep responses token-frugal. In file mode `filePath` is the sandboxed absolute path." - removed
Output schema / properties / base64Removed value: -{ - "description": "Base64-encoded PDF bytes (when mode='base64').", - "type": "string" -}
- Added
extract_attachments - Changed
extract_text2 fields changed- added
Input schema / properties / fieldsAdded value: +{ + "description": "Optional dot-path projection applied to the structured result (e.g. ['fullText'] or ['extractable']). Composes after verbosity. Unknown paths are omitted.", + "items": { + "minLength": 1, + "type": "string" + }, + "maxItems": 16, + "type": "array" +} - added
Input schema / properties / verbosityAdded value: +{ + "default": "full", + "description": "Response verbosity. 'full' (default) returns the per-page pages[] array and fullText; 'summary' returns a token-frugal { pageCount, extractedPageCount, extractable, charCount } and drops the text payloads.", + "enum": [ + "summary", + "full" + ], + "type": "string" +}
- Changed
generate_basic_pdf4 fields changed- added
Input schema / properties / normalizeAdded value: +{ + "description": "Optional Unicode normalization applied to all rendered text before shaping. 'NFC' (recommended) composes base + combining marks into precomposed code points for better glyph coverage; 'NFD'/'NFKC'/'NFKD' are also accepted. Omit for byte-stable output (no normalization).", + "enum": [ + "NFC", + "NFD", + "NFKC", + "NFKD" + ], + "type": "string" +} - added
Input schema / properties / watermarkAdded value: +{ + "additionalProperties": false, + "description": "Optional semi-transparent text watermark rendered on every page (e.g. 'DRAFT', 'CONFIDENTIAL'). Text only in this version. opacity < 1.0 is rejected under pdfA='pdfa1b' (ISO 19005-1 forbids transparency).", + "properties": { + "angle": { + "description": "Rotation in degrees (counterclockwise). Default -45.", + "maximum": 360, + "minimum": -360, + "type": "number" + }, + "color": { + "description": "RGB colour as a [r, g, b] triple in the 0.0–1.0 range. Default light gray [0.75, 0.75, 0.75].", + "items": { + "maximum": 1, + "minimum": 0, + "type": "number" + }, + "maxItems": 3, + "minItems": 3, + "type": "array" + }, + "fontSize": { + "description": "Font size in points. Default 60, auto-fit to the page.", + "maximum": 300, + "minimum": 6, + "type": "number" + }, + "opacity": { + "description": "Opacity 0.0–1.0. Default 0.15.", + "maximum": 1, + "minimum": 0, + "type": "number" + }, + "position": { + "default": "background", + "description": "'background' (behind page content, default) or 'foreground' (above it).", + "enum": [ + "background", + "foreground" + ], + "type": "string" + }, + "text": { + "description": "Watermark text.", + "maxLength": 100, + "minLength": 1, + "type": "string" + } + }, + "required": [ + "text" + ], + "type": "object" +} - added
Output schema / descriptionAdded value: +"Structured result of a PDF-producing tool. In base64 mode the PDF bytes are delivered out-of-band as an embedded `resource` content block (data: URI), NOT duplicated here, to keep responses token-frugal. In file mode `filePath` is the sandboxed absolute path." - removed
Output schema / properties / base64Removed value: -{ - "description": "Base64-encoded PDF bytes (when mode='base64').", - "type": "string" -}
- Changed
inspect_pdf2 fields changed- added
Input schema / properties / fieldsAdded value: +{ + "description": "Optional dot-path projection applied to the structured result (e.g. ['pageCount','signatureCount']). Composes after verbosity. Unknown paths are omitted.", + "items": { + "minLength": 1, + "type": "string" + }, + "maxItems": 16, + "type": "array" +} - added
Input schema / properties / verbosityAdded value: +{ + "default": "full", + "description": "Response verbosity. 'full' (default) returns every field; 'summary' returns a token-frugal scalar subset (version, pageCount, encryption, pdfA, signatureCount, hasSignaturePlaceholder, attachmentCount) — drops the attachments[], info and perPage arrays.", + "enum": [ + "summary", + "full" + ], + "type": "string" +}
- Changed
prepare_signature_placeholder2 fields changed- added
Output schema / descriptionAdded value: +"Structured result of a PDF-producing tool. In base64 mode the PDF bytes are delivered out-of-band as an embedded `resource` content block (data: URI), NOT duplicated here, to keep responses token-frugal. In file mode `filePath` is the sandboxed absolute path." - removed
Output schema / properties / base64Removed value: -{ - "description": "Base64-encoded PDF bytes (when mode='base64').", - "type": "string" -}
- Changed
sign_pdf2 fields changed- added
Output schema / descriptionAdded value: +"Structured result of a PDF-producing tool. In base64 mode the PDF bytes are delivered out-of-band as an embedded `resource` content block (data: URI), NOT duplicated here, to keep responses token-frugal. In file mode `filePath` is the sandboxed absolute path." - removed
Output schema / properties / base64Removed value: -{ - "description": "Base64-encoded PDF bytes (when mode='base64').", - "type": "string" -}
- Changed
validate_pdf2 fields changed- added
Input schema / properties / fieldsAdded value: +{ + "description": "Optional dot-path projection applied to the structured result (e.g. ['valid']). Composes after verbosity. Unknown paths are omitted.", + "items": { + "minLength": 1, + "type": "string" + }, + "maxItems": 16, + "type": "array" +} - added
Input schema / properties / verbosityAdded value: +{ + "default": "full", + "description": "Response verbosity. 'full' (default) returns errors[] and warnings[]; 'summary' returns a token-frugal verdict { standard, valid, errorCount, warningCount, summary } and drops the message arrays.", + "enum": [ + "summary", + "full" + ], + "type": "string" +}
- Changed
verify_pdf2 fields changed- added
Input schema / properties / fieldsAdded value: +{ + "description": "Optional dot-path projection applied to the structured result (e.g. ['allValid'] or ['signatures.valid']). Composes after verbosity. Unknown paths are omitted.", + "items": { + "minLength": 1, + "type": "string" + }, + "maxItems": 16, + "type": "array" +} - added
Input schema / properties / verbosityAdded value: +{ + "default": "full", + "description": "Response verbosity. 'full' (default) returns the per-signature signatures[] array; 'summary' returns a token-frugal verdict { signatureCount, allValid, invalid, summary } and drops signatures[].", + "enum": [ + "summary", + "full" + ], + "type": "string" +}
13 tool updates
v1.1.0- First observed
add_attachment - First observed
add_barcode - First observed
add_form - First observed
add_international_text - First observed
add_table - First observed
embed_image - First observed
extract_text - First observed
generate_basic_pdf - First observed
inspect_pdf - First observed
prepare_signature_placeholder - First observed
sign_pdf - First observed
validate_pdf - First observed
verify_pdf
TDQS
Scored across 28 tools
Each tool has a distinctly scoped purpose, and the descriptions explicitly disambiguate related paths ('use the dedicated tools only for a standalone artefact', 'Need ONE document? Use extract_pages. Need several documents? Use split_pdf', 'sign_pdf auto-injects the placeholder'). The multiple add_*/generate_* tools remain easy to separate because the doc-generator tells the agent which to choose.
All tool names are lowercase snake_case with a clear verb+object convention: add_barcode, extract_text, sign_pdf, encrypt_pdf, fill_form, split_pdf. The shared add_*/extract_*/generate_* style makes the operation families predictable even across 28 tools.
28 tools is above the reasonable ceiling for this set; generate_basic_pdf already supports table, image, barcode, form, and chart blocks, so the standalone add_table/embed_image/add_table/add_barcode/add_rt/add_ort/add_rt dedicated tools are redundant additions to the same body. prepare_signature_placeholder is also optional, and draft_governance_issue sits outside the PDF domain, contributing unnecessary surface.
The server covers document creation, inspection, text/attachment extraction, forms, signatures, LTV, encryption/decryption, merging/splitting, and layout probing. Obvious gaps are operations like attaching files to an exexistig PDF, removing or editing existing content, and page deletion in-space, but most real workflow have no dead ends.
Maintenance
Related MCP Connectors
Generate and read PDFs for AI agents: a generate_pdf and a read_pdf tool, priced per document.
Compliant PDFs (PDF/A-2A + PDF/UA-1) from markdown or a compact DSL - fast, no headless browser.
Turn HTML or templates into branded invoice & document PDFs from your agent. One call, no install.
Document API for AI-native software: render PDFs, e-sign, PAdES-seal, and verify.
Related MCP Servers
- AlicenseAqualityCmaintenanceGenerate professional PDFs from Claude, Cursor, and other AI tools. Create invoices, contracts, reports, and certificates from templates or inline HTML markup.730 npm1MIT
- AlicenseNot gradedqualityDmaintenanceLocal document intelligence for AI agents — extract text, detect tables, read metadata, analyze structure, search keywords, and detect language from PDF and DOCX files. No cloud API required, no API key needed.MIT
- FlicenseNot gradedqualityAmaintenanceEnables AI agents to perform comprehensive PDF operations locally, including compression, text extraction, PII redaction, page organization, splitting, merging, watermarking, creation, and form filling, all without cloud uploads.15 npm-
- AlicenseAqualityBmaintenanceEnables AI agents to inspect PDFs, merge or extract pages, and clean text entirely offline through the Model Context Protocol, with no uploads, API keys, or network calls.450 npmMIT