Skip to main content
Glama
Nizoka

pdfnative-mcp

Add embedded file attachment (PDF/A-3, Factur-X)

add_attachment
Idempotent

Embed machine-readable attachments into PDF/A-3 documents, enabling Factur-X/ZUGFeRD e-invoices and any XML sidecar up to 8 MiB per file for automated processing.

Instructions

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.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
debugNoDraw margin / block / cell guide rectangles (unmarked content — not for PDF/UA output). Geometry unchanged. Default false.
printNoPrint 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.
titleYesDocument title (also written to the /Info dictionary).
blocksNoOptional 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.
strictNoFail 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.
marginsNoMargins in points, all four required (0–200). Default 45 / 36 / 35 / 36.
compressNoFlateDecode the streams (smaller file, different bytes; PDF/A unaffected, XMP stays plain). Default false.
metadataNo/Info (+ XMP under PDF/A): author, subject, keywords, /Trapped.
pageSizeNoPortrait 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.
embedFontsNoEmbed 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.
footerTextNoOptional footer text rendered on every page.
outputModeNo'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
outputPathNoRequired when outputMode='file'. Relative path inside the sandbox; must end with .pdf (no absolute paths, no '..').
attachmentsYesOne 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.
creationDateNoISO-8601 instant for /CreationDate (+ XMP). Pin it for byte-identical output across calls (same host TZ); omitted = wall clock, so every call differs.
outputIntentNoCustom PDF/A OutputIntent: an RGB ICC profile + condition strings replacing the built-in sRGB intent (CMYK rejected).
footerTemplateNoRunning footer on every page. Replaces the default footer: footerText is then ignored and page numbers appear only via {page}/{pages}.
headerTemplateNoRunning header on every page (left / center / right zones); reserves 15 pt.
includeDiagnosticsNoReturn the PDF/A diagnostics raised while building as `diagnostics[]` (possibly empty).

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
modeYes
summaryNoTool-specific summary, when produced.
filePathNoSandboxed absolute path (file mode).
sizeBytesYes
diagnosticsNoPDF/A diagnostics (when includeDiagnostics=true).

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed19 schema fields changed
    • addedInput schema / properties / compress
      Added value: +{
      +  "description": "FlateDecode the streams (smaller file, different bytes; PDF/A unaffected, XMP stays plain). Default false.",
      +  "type": "boolean"
      +}
    • addedInput schema / properties / creationDate
      Added 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"
      +}
    • addedInput schema / properties / debug
      Added value: +{
      +  "description": "Draw margin / block / cell guide rectangles (unmarked content — not for PDF/UA output). Geometry unchanged. Default false.",
      +  "type": "boolean"
      +}
    • addedInput schema / properties / embedFonts
      Added 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"
      +}
    • addedInput schema / properties / footerTemplate
      Added 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"
      +}
    • addedInput schema / properties / headerTemplate
      Added 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"
      +}
    • addedInput schema / properties / includeDiagnostics
      Added value: +{
      +  "default": false,
      +  "description": "Return the PDF/A diagnostics raised while building as `diagnostics[]` (possibly empty).",
      +  "type": "boolean"
      +}
    • addedInput schema / properties / margins
      Added 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"
      +}
    • addedInput schema / properties / metadata
      Added 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"
      +}
    • addedInput schema / properties / outputIntent
      Added 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"
      +}
    • addedInput schema / properties / outputMode / description
      Added 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)."
    • addedInput schema / properties / outputPath / description
      Added value: +"Required when outputMode='file'. Relative path inside the sandbox; must end with .pdf (no absolute paths, no '..')."
    • addedInput schema / properties / pageSize
      Added 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"
      +}
    • addedInput schema / properties / print
      Added 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"
      +}
    • addedInput schema / properties / strict
      Added 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"
      +}
    • changedOutput schema / description
      Previous 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`."
    • addedOutput schema / properties / diagnostics
      Added 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"
      +}
    • changedOutput schema / properties / filePath / description
      Previous value: -"Absolute sandboxed file path (when mode='file')."New value: +"Sandboxed absolute path (file mode)."
    • addedOutput schema / properties / summary
      Added value: +{
      +  "additionalProperties": true,
      +  "description": "Tool-specific summary, when produced.",
      +  "type": "object"
      +}
  2. Changed2 schema fields changedv1.2.0
    • addedOutput schema / description
      Added 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."
    • removedOutput schema / properties / base64
      Removed value: -{
      -  "description": "Base64-encoded PDF bytes (when mode='base64').",
      -  "type": "string"
      -}
  3. First observedv1.1.0

TDQS

A4.5/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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.