ZUGFeRD / XRechnung
MCP Validation Server
MCP server for automated validation of e-invoices in the ZUGFeRD, Factur-X and XRechnung formats. Returns structured JSON results with concrete fix suggestions.
1. Overview
The server provides three tools and one resource that AI agents can call through the Model Context Protocol.
| Scenario | Tool / Resource |
|---|---|
| Check an invoice before sending | validate_invoice |
| Read XML data from a ZUGFeRD PDF | extract_xml |
| Check whether PDF and XML match | check_consistency |
| Query available formats and rule sets | validation://rules |
2. Architecture & Data Flow
Flow for validate_invoice
3. Validation Engines
Every request is checked by two engines at once. The results are consolidated, deduplicated and returned.
| Engine | Version | Covered formats |
|---|---|---|
| Mustang Project | v2.22.0 | ZUGFeRD 1.0–2.4, Factur-X 1.0, XRechnung (general) |
| KoSIT validation tool | v1.6.2 | XRechnung 3.0.2 (CII + UBL), EN 16931 CII/UBL (plain), Factur-X 1.07.3 / 1.08 (all profiles) |
errors list. Duplicates (same rule ID + message) are removed automatically. KoSIT errors are only included when a matching validation scenario was detected — for unknown GuidelineIDs, Mustang runs alone.
4. Installation & Configuration
# Register for free:
https://zugferd-validator.de/portal
npm install -g zugferd-mcp-client
// mcp_config.json (path varies by client) { "mcpServers": { "zugferd": { "command": "zugferd-mcp-client", "env": { "ZUGFERD_API_KEY": "zv_your_key_here" } } } }
Direct REST API
The API can also be called directly, without the MCP client:
# Example: validation via curl curl -X POST https://api.zugferd-validator.de/v1/validate \ -H "Content-Type: application/json" \ -H "X-Api-Key: zv_your_key_here" \ -d '{"file_content":"<base64>","file_type":"xml"}'
Environment variables (MCP client)
| Variable | Description | Default |
|---|---|---|
ZUGFERD_API_KEY | API key from the portal | – (required) |
ZUGFERD_API_URL | API base URL | https://api.zugferd-validator.de |
5. Tools
Validates an e-invoice (ZUGFeRD/Factur-X PDF or XRechnung XML) against EN 16931 and the German extensions. Returns structured errors, warnings and fix suggestions.
Input schema
data:application/pdf;base64,…) are removed automatically.
"pdf" for ZUGFeRD/Factur-X PDFs · "xml" for plain XRechnung/CII XML files
rule_id: "PROFILE_MISMATCH" is generated.Values:
minimum · basic_wl · basic · en16931 · extended · xrechnung
Output schema
{
"valid": true,
"format": "ZUGFeRD 2.x",
"profile": "EN16931",
"summary": "No issues found",
"errors": [],
"warnings": [],
"notices": [],
"metadata": {
"invoice_number": "RE-2026-001",
"issue_date": "2026-04-01",
"seller": "Musterfirma GmbH",
"buyer": "Beispiel AG",
"total_amount": "1190.00",
"currency": "EUR"
}
}
{
"valid": false,
"format": "ZUGFeRD 2.x",
"profile": "EN16931",
"summary": "2 errors, 1 warning found",
"errors": [
{
"severity": "error",
"rule_id": "BR-DE-15",
"field": "BT-10",
"message": "The buyer reference / routing ID (BT-10) must be provided.",
"fix_suggestion": "Add the buyer reference / routing ID (BT-10) in 'ram:ApplicableHeaderTradeAgreement/ram:BuyerReference'.",
"xpath": "//ram:ApplicableHeaderTradeAgreement/ram:BuyerReference"
}
],
"warnings": [
{
"severity": "warning",
"rule_id": "BR-CL-10",
"field": "BT-81",
"message": "The payment means code must come from UNTDID 4461.",
"fix_suggestion": "Use e.g. '58' for SEPA credit transfer or '59' for SEPA direct debit.",
"xpath": "//ram:SpecifiedTradeSettlementPaymentMeans/ram:TypeCode"
}
]
}
Output fields
| Field | Type | Required | Description |
|---|---|---|---|
valid | boolean | Yes | true when not a single error was found |
format | string | No | Detected format, e.g. "ZUGFeRD 2.x", "CII EN16931", "XRechnung 3.0" — null when no XML can be extracted |
profile | string | No | Detected profile in uppercase, e.g. "EN16931", "XRECHNUNG" — null when no XML can be extracted |
summary | string | Yes | Human-readable summary, e.g. "2 errors, 1 warning found" |
errors | array | Yes | Validation errors — these make the invoice invalid |
warnings | array | Yes | Warnings — the invoice can still be valid |
notices | array | No | Informational notices with no impact on validity |
metadata | object | No | Extracted invoice data — present for PDFs when the embedded XML was read successfully, and always for file_type: "xml" |
Extracts the embedded XML document from a ZUGFeRD/Factur-X PDF. Returns the full XML content as a string, together with the detected format and profile.
Input
Output
{
"xml_content": "<?xml version='1.0' encoding='UTF-8'?>\n<rsm:CrossIndustryInvoice ...>...</rsm:CrossIndustryInvoice>",
"format": "ZUGFeRD 2.x",
"profile": "EN16931"
}
xml_content can be passed directly (after Base64 encoding) to validate_invoice with file_type: "xml".Checks whether the human-readable data in the PDF (invoice number, date, total amount) matches the machine data stored in the XML attachment. Reveals tampering or data-entry errors.
Input
Output
{
"consistent": true,
"discrepancies": []
}
{
"consistent": false,
"discrepancies": [
{
"field": "total_amount",
"pdf_value": "1190.00",
"xml_value": "1180.00",
"message": "The total amount in the PDF ('1190.00') differs from the one in the XML ('1180.00')."
}
]
}
Checked fields & tolerances
| Field | Detection pattern in the PDF | Tolerance |
|---|---|---|
invoice_number | Rechnungsnummer:, Rechnung Nr., Invoice No. | Case, spaces and hyphens ignored |
issue_date | Rechnungsdatum:, Datum:, Invoice Date: | None — date formats are normalized to ISO 8601 |
total_amount | Gesamtbetrag:, Rechnungsbetrag:, Total: | ±0.01 EUR (rounding differences) |
Builds a valid e-invoice from structured data — either as a ZUGFeRD PDF (PDF/A-3 with embedded EN 16931 CII XML) or as plain XRechnung XML (CII with the XRechnung 3.0 CIUS and routing ID for B2G). Multiple line items, all VAT categories (S/Z/E/AE), allowances/charges, payment details. REST: POST /v1/create. Stateless — nothing is stored. Amounts in cents, date as YYYY-MM-DD.
Input (excerpt)
zugferd (PDF) or xrechnung (XML)invoice: credit_note (credit note / cancellation), corrected, self_billed, prepayment (down payment), partial (partial invoice). Raw override via type_code.{ number, date } — for cancellations/corrections (BT-25/26)xrechnungfalse.Output
{
"format": "zugferd",
"profile": "EN16931",
"pdf_base64": "JVBERi0xLjc…",
"xml": "<?xml version=\"1.0\"…",
"branding": "free_footer"
}
validate_invoice on the returned pdf_base64 or xml — or set self_check: true for a single round trip. Branding (footer on the Check tier / white-label from the Automate tier) is determined server-side from the tier. Separate weekly quota: Check 1, Automate 20, Scale unlimited.zv_test_…, via GET /v1/keys/me): for free integration without using the live quota. Created invoices carry a tiled "DEMO" watermark on every page plus an XML marker — fully testable, but worthless as a real invoice. 100/day, 3/minute; counted separately from the live quota.6. Resource: validation_rules
Returns the server's current rule set: supported formats, profiles and the validation engine in use.
URI: validation://rules
{
"supported_formats": [
"ZUGFeRD 1.0", "ZUGFeRD 2.0", "ZUGFeRD 2.1", "ZUGFeRD 2.2",
"ZUGFeRD 2.3", "ZUGFeRD 2.x / Factur-X 1.0x",
"XRechnung 1.2", "XRechnung 2.0", "XRechnung 2.3", "XRechnung 3.0"
],
"supported_profiles": [
"minimum", "basic_wl", "basic", "en16931", "extended", "xrechnung"
],
"validation_engines": [
"Mustang Project v2.22.0",
"KoSIT Validierungstool v1.6.2 (XRechnung 3.0.2 + EN 16931 CII)"
],
"last_updated": "2026-04-08"
}
7. Error Handling
On failure, all tools return a JSON object with an error field. There is never unstructured error output.
{
"error": "Short error category",
"details": "Detailed description with a concrete hint on how to fix it."
}
| error | Trigger |
|---|---|
"Fehlender Parameter" | Required field not provided |
"Ungültiger Parameter" | Wrong value for file_type |
"Ungültiger Base64-Input" | No valid Base64 string provided |
"Validierungsfehler" | Mustang CLI could not start (e.g. Java missing) or timed out after 30s |
"XML-Extraktion fehlgeschlagen" | No XML file found in the PDF attachment (for extract / consistency). For validate, a notice with rule_id: "NO_EMBEDDED_XML" is returned instead and valid: true is set |
"PDF-Lesefehler" | The PDF cannot be read |
"XML-Parsing-Fehler" | The extracted XML is not valid XML |
"Interner Fehler" | Unexpected runtime error |
"error": "Validierungsfehler" is returned. A KoSIT timeout is silently ignored — Mustang results are kept.8. Common Data Types
ValidationIssue
Used in the errors, warnings and notices arrays of validate_invoice.
| Field | Type | Required | Description |
|---|---|---|---|
severity | "error" | "warning" | "notice" | Yes | Severity of the finding |
rule_id | string | Yes | Rule ID, e.g. "BR-DE-1", "BR-CL-10". Value "UNKNOWN" for XSD schema violations (KoSIT) or when no rule ID can be determined |
field | string | No | Affected BT field, e.g. "BT-10" |
message | string | Yes | Error message in German |
fix_suggestion | string | No | Concrete fix hint with an XML example |
xpath | string | No | XPath to the affected XML element |
InvoiceMetadata
Optional field in the result of validate_invoice (only for file_type: "xml").
| Field | Type | Description |
|---|---|---|
invoice_number | string? | Invoice number (BT-1) |
issue_date | string? | Invoice date, ISO 8601, e.g. "2026-04-01" |
seller | string? | Seller name (BT-27) |
buyer | string? | Buyer name (BT-44) |
total_amount | string? | Total amount as a decimal string, e.g. "1190.00" |
currency | string? | ISO 4217 currency code, e.g. "EUR" |
9. Supported Formats & Profiles
Formats
| Format | Standard | Note |
|---|---|---|
| ZUGFeRD 1.0 | ZUGFeRD 1.0 / GEFEG | Older version, limited profile support |
| ZUGFeRD 2.0 | FeRD 2.0 | First CII-based version |
| ZUGFeRD 2.1 | Factur-X 1.0 (FR) | Technically identical to Factur-X 1.0 |
| ZUGFeRD 2.2 | Factur-X 1.0.05 | Minor corrections |
| ZUGFeRD 2.3 | Factur-X 1.0.06 | Version before 2.4 |
| ZUGFeRD 2.x / Factur-X 1.0x | EN 16931 + D16B | Current main version (2026) — the API returns "ZUGFeRD 2.x" |
| XRechnung 1.2 | XRechnung 1.2 | Older XRechnung version |
| XRechnung 2.x | XRechnung 2.0–2.3 | Various intermediate versions |
| XRechnung 3.0 | XRechnung 3.0 | Current XRechnung version |
Profiles (ZUGFeRD/Factur-X)
| Profile ID | Display name | Typical use |
|---|---|---|
minimum | MINIMUM | Simple machine processing |
basic_wl | BASIC-WL | Without line-item detail |
basic | BASIC | Standard invoices |
en16931 | EN 16931 (COMFORT) | Public authorities, PEPPOL |
extended | EXTENDED | Complex B2B processes |
xrechnung | XRECHNUNG | German public administration |
10. Rule Set & Fix Suggestions
The server contains a database of fix suggestions for 63 rule categories. Errors from both validation engines (Mustang + KoSIT) are consolidated — when a known rule ID is found, the fix suggestion is attached automatically.
BR-DE rules 26 rules
German extensions — mandatory for XRechnung-compliant invoices.
| Rule ID | Field | Short description |
|---|---|---|
BR-DE-1 | BG-16 | PAYMENT INSTRUCTIONS (BG-16) missing |
BR-DE-2 | BG-6 | SELLER CONTACT (BG-6) |
BR-DE-3 | BT-37 | Seller city (BT-37) |
BR-DE-4 | BT-38 | Seller post code (BT-38) |
BR-DE-5 | BT-41 | Seller contact point (BT-41) |
BR-DE-6 | BT-42 | Seller phone number (BT-42) |
BR-DE-7 | BT-43 | Seller email (BT-43) |
BR-DE-8 | BT-52 | Buyer city (BT-52) |
BR-DE-9 | BT-53 | Buyer post code (BT-53) |
BR-DE-10 | BT-77 | Deliver-to city (BT-77) |
BR-DE-11 | BT-78 | Deliver-to post code (BT-78) |
BR-DE-12 | – | Removed in the current XRechnung release |
BR-DE-13 | – | Removed in the current XRechnung release |
BR-DE-14 | BT-119 | VAT rate (BT-119) |
BR-DE-15 | BT-10 | Buyer reference / routing ID (BT-10) |
BR-DE-16 | BT-31 | Seller VAT ID / tax number |
BR-DE-17 | BT-3 | Invalid invoice type code (BT-3) |
BR-DE-18 | BT-20 | Payment discount terms (BT-20) in the wrong format |
BR-DE-19 | – | Removed in the current XRechnung release |
BR-DE-20 | – | Removed in the current XRechnung release |
BR-DE-21 | BT-24 | Specification identifier (BT-24) not XRechnung-compliant |
BR-DE-22 | – | Attachment file names not unique |
BR-DE-23 | – | Removed in the current XRechnung release |
BR-DE-24 | – | Removed in the current XRechnung release |
BR-DE-25 | – | Removed in the current XRechnung release |
BR-DE-26 | BT-3 | Correction invoice without a reference invoice (BG-3) |
EN 16931 core rules (BR-*) 10 rules
| Rule ID | Field | Short description |
|---|---|---|
BR-1 | BT-24 | Specification identifier (BT-24) |
BR-2 | BT-1 | Invoice number (BT-1) |
BR-3 | BT-2 | Invoice issue date (BT-2) |
BR-4 | BT-3 | Invoice type code (BT-3) |
BR-5 | BT-5 | Currency code (BT-5) |
BR-6 | BT-27 | Seller name (BT-27) |
BR-7 | BT-44 | Buyer name (BT-44) |
BR-8 | BG-5 | Seller postal address (BG-5) |
BR-9 | BG-5 | Seller country code (BT-40) |
BR-10 | BG-8 | Buyer postal address (BG-8) |
Calculation rules (BR-CO-*) & code-list rules (BR-CL-*) 8 rules
| Rule ID | Short description |
|---|---|
BR-CO-3 | Tax point date and tax point date code are mutually exclusive |
BR-CO-9 | Seller VAT ID without a country prefix |
BR-CO-10 | Sum of net line amounts does not match |
BR-CO-13 | Total amount excluding VAT calculated incorrectly |
BR-CL-10 | Invalid schemeID (not from ISO 6523) |
BR-CL-16 | Invalid payment means code (not from UNTDID 4461) |
BR-CL-17 | Invalid VAT category at line level |
BR-CL-18 | Invalid VAT category at document level |
Tax category rules (BR-S/Z/E/AE-*) 4 rules
| Rule ID | Short description |
|---|---|
BR-S-1 | Tax amount given for the standard rate (S) |
BR-Z-1 | Tax amount for the zero rate (Z) = 0 |
BR-E-1 | Tax amount for tax exemption (E) = 0 |
BR-AE-1 | Tax amount for reverse charge (AE) = 0 |
11. Usage Examples
Example 1: Validate an XRechnung XML
{
"tool": "validate_invoice",
"arguments": {
"file_content": "PD94bWwgdmVyc2lvbj0iMS4wIj8+...",
"file_type": "xml",
"profile": "xrechnung"
}
}
{
"valid": true,
"format": "XRechnung 3.0",
"profile": "XRECHNUNG",
"summary": "No issues found",
"errors": [],
"warnings": [],
"metadata": {
"invoice_number": "INV-2026-0042",
"issue_date": "2026-04-07",
"seller": "Tech GmbH",
"buyer": "Bundesbehörde X",
"total_amount": "5950.00",
"currency": "EUR"
}
}
Example 2: Faulty invoice with a fix suggestion
{
"tool": "validate_invoice",
"arguments": {
"file_content": "JVBERi0xLjQK...",
"file_type": "pdf"
}
}
{
"valid": false,
"format": "ZUGFeRD 2.x",
"profile": "EN16931",
"summary": "1 error found",
"errors": [{
"severity": "error",
"rule_id": "BR-DE-23",
"field": "BT-10",
"message": "The buyer reference (BT-10) must be provided for XRechnung.",
"fix_suggestion": "Add 'ram:BuyerReference', e.g. '04011000-1234-34' for public authorities.",
"xpath": "//ram:ApplicableHeaderTradeAgreement/ram:BuyerReference"
}],
"warnings": []
}
Example 3: Extract and validate XML
// Step 1 — extract the XML from the PDF { "tool": "extract_xml", "arguments": { "pdf_content": "JVBERi0x..." } } // Step 2 — validate the extracted XML (passed Base64-encoded) { "tool": "validate_invoice", "arguments": { "file_content": "<base64 of xml_content>", "file_type": "xml" } }
Example 4: Consistency check
{
"tool": "check_consistency",
"arguments": { "pdf_content": "JVBERi0xLjQK..." }
}
{
"consistent": false,
"discrepancies": [{
"field": "total_amount",
"pdf_value": "1190.00",
"xml_value": "1180.00",
"message": "The total amount in the PDF ('1190.00') differs from the one in the XML ('1180.00')."
}]
}
Example 5: Plain PDF without embedded XML
A regular PDF invoice without a ZUGFeRD/Factur-X attachment returns valid: true with an informational notice — not an error, but a hint that no structured data could be checked.
{
"tool": "validate_invoice",
"arguments": {
"file_content": "JVBERi0xLjQK...",
"file_type": "pdf"
}
}
{
"valid": true,
"format": null,
"profile": null,
"summary": "2 notices found",
"errors": [],
"warnings": [],
"notices": [
{
"severity": "notice",
"rule_id": "UNKNOWN",
"message": "XML could not be extracted"
},
{
"severity": "notice",
"rule_id": "NO_EMBEDDED_XML",
"message": "Kein eingebettetes XML gefunden. Die PDF ist möglicherweise keine ZUGFeRD/Factur-X Rechnung."
}
]
}
12. Limits & Known Constraints
| Constraint | Details |
|---|---|
| Timeout | Mustang CLI is aborted server-side after 30 seconds. Very large or corrupt files can trigger this timeout. |
| Rate limit | Validation: Check 20/week · Automate 500/week · Scale unlimited. Creation (separate quota): Check 1/week · Automate 20/week · Scale unlimited. Sandbox creation: 100/day, max. 3/minute. On exceeding the limit: HTTP 429. |
| PDF OCR | check_consistency only evaluates machine-readable PDF text. Scanned PDFs without an OCR layer are not supported. |
| Metadata for PDFs | validate_invoice also extracts metadata for PDFs, provided an embedded XML is present and readable. For plain PDFs without XML, this field is missing. |
| Consistency check | Only three fields are compared (number, date, amount). Addresses, tax numbers and line-item details are not reconciled. |
| Unknown rule IDs | If a rule ID is missing from the fix-suggestions DB, fix_suggestion stays empty. The message is still returned. |
| File size | No explicit size limit, but very large PDFs (>50 MB) can lead to a timeout. |
13. Changelog
June 2026 — Invoice creation
- New tool
create_invoice/POST /v1/create: build valid e-invoices from structured data — as a ZUGFeRD PDF (PDF/A-3) or plain XRechnung XML (with routing ID for B2G). - Multiple line items, all VAT categories (S/Z/E/AE), allowances/charges, payment details, due date.
- Document types: invoice, credit note/cancellation, correction, self-billing, down-payment and partial invoice — with a reference to the original invoice.
- Tier-dependent branding (footer on the Check tier / white-label from the Automate tier with an optional logo); separate weekly quota, kept apart from validation.
- Sandbox/test keys (
zv_test_…): free integration with a "DEMO" watermark, without using up the live quota.
April 2026 — Initial release
- Validation against EN 16931 (
validate_invoice) for ZUGFeRD/Factur-X PDF and XRechnung XML, with concrete fix suggestions. - XML extraction (
extract_xml) and PDF↔XML consistency check (check_consistency). - MCP client for Claude & other AI agents; Mustang and KoSIT engines.