InvoiceIn
OfficialInvoiceIn turns any received European e-invoice (XML or hybrid PDF) into canonical EN 16931 JSON, a validation verdict with fix hints, or a human/accounting rendering — via five read-only, stateless tools.
read_invoice— parse and validate in one call: canonical EN 16931 JSON (document, seller, buyer, lines, tax_breakdown, totals, payment), validation report, timings.validate_invoice— verdict only: valid flag, error/warning counts, rule sets with versions, per-rule id/severity/hint/field/who, detected source and document header.invoice_to_html— self-contained printable HTML (inline CSS, no external assets) with labels in en/de/pl/it/fr.invoice_to_csv— flat CSV,level=lines(one row per line item) ordocuments; a FatturaPA lot yields rows for every invoice.invoice_to_datev— DATEV Buchungsstapel EXTF 700 (cp1252) for German bookkeeping, SKR03/04,creditor_account, one booking row per VAT-rate group.Accepts: XML in UBL 2.1, CII D16B, XRechnung, Peppol BIS 3, FatturaPA 1.2, KSeF FA(2)/FA(3), or ZUGFeRD/Factur-X hybrid PDF (embedded XML), up to 25 MB, as
file_base64(orpathover stdio).Checks: XSD, EN 16931 1.3.16, XRechnung 3.0.2, Peppol BIS 3, FNFE CTC-FR, CIUS-RO, PINT AE (UAE), FatturaPA, KSeF, plus arithmetic cross-checks.
Does not: OCR (plain/scanned PDFs are rejected), validate in the html/csv/datev tools, transmit anything, or store data; read_invoice returns only the first invoice of a FatturaPA lot (with a note); results are informational, not legal advice.
Cost: one invoice credit per call; anonymous quota 20/day per IP; all tools read-only, idempotent, non-destructive, closed-world.
Allows exporting processed invoice data to DATEV Buchungsstapel (EXTF 700, cp1252), with configuration options for SKR 03/04 and creditor account.
InvoiceIn — examples
Any European or UAE (PINT AE) e-invoice a business receives → one canonical EN 16931 JSON, a validation report with plain-language fix hints, a PDF, CSV or DATEV export. One stateless endpoint, nothing stored.
Accepts: XRechnung (UBL and CII), EN 16931 UBL 2.1 Invoice/CreditNote, Peppol BIS Billing 3, CII D16B, ZUGFeRD 1.0 / 2.x and Factur-X hybrid PDFs, Italy's FatturaPA 1.2, Poland's KSeF FA(2)/FA(3), Romania's RO e-Factura (CIUS-RO), the UAE's PINT AE (Billing and Self-Billing).
Validated against: EN 16931 validation artefacts 1.3.16, XRechnung 3.0.2 (KoSIT Schematron 2.6.0), Peppol BIS Billing 3, FNFE CTC-FR 1.4.0.04 (the BR-FR rules; runs when seller and buyer are both established in France), CIUS-RO 1.0.1, OpenPeppol's PINT AE 1.0.4 for the UAE (free check page: https://invoicein.peculiar.systems/uae), the UBL, CII, FatturaPA and KSeF schemas — plus arithmetic cross-checks on every format and market conventions no Schematron reads (German Skonto terms in free text, the Polish KSeF number). The live list with versions is at GET /v1/formats.
Product page: https://invoicein.peculiar.systems (EN · DE · PL · IT · FR)
API reference (interactive): https://invoicein-api.peculiar.systems/docs
OpenAPI: https://invoicein-api.peculiar.systems/openapi.json
Postman: public collection · published docs — or import
postman/InvoiceIn.postman_collection.json. Every request already carries a real XRechnung in its body, so Send works with no setupMCP server:
https://invoicein-api.peculiar.systems/mcp(streamable HTTP) — on the official registry asio.github.peculiar-systems/invoiceinand on Smithery
This repository holds runnable examples, sample invoices you can test with, and the MCP registry manifest. The service itself is not open source.
Nothing you send is stored: the document is parsed in memory and the response is built from it. Privacy (full policy) · Terms
The bridge in bridge/ is a transparent proxy, not a second implementation: it mirrors whatever tools/list returns from the hosted server, so the two can never drift. The five tools and their annotations — all read-only, non-destructive, idempotent, closed-world — are in bridge/tools.json, checked by tests/. A static analyser reading the bridge source alone sees one dispatch callback and no tools; that is the proxy, not the tool surface.
60 seconds
curl -X POST "https://invoicein-api.peculiar.systems/v1/invoice?include=validation&lang=en" \
-H "X-Api-Key: $INVOICEIN_KEY" \
-F file=@samples/factur-x-en16931.pdfNo key yet? Leave the header out: 20 invoices a day per IP, same output. A trial key (100 invoices, 30 days, no card) comes from the product page.
The response (full example):
{
"ok": true,
"source": { "syntax": "UBL", "format": "peppol-bis3", "profile": "Peppol BIS Billing 3.0", "container": "xml" },
"invoice": { // canonical EN 16931, field names carry BT/BG numbers in /v1/schema
"document": { "id": "Snippet1", "issue_date": "2017-11-13", "type_code": "380", "currency": "EUR", "due_date": "2017-12-01", ... },
"seller": { "name": "SupplierOfficialName Ltd", "vat_id": "GB1232434", "electronic_address": { "value": "9482348239847239874", "scheme": "0088" }, ... },
"buyer": { ... },
"lines": [ { "id": "1", "quantity": 7, "unit": "DAY", "net_amount": 2800, "tax": { "category": "S", "rate": 25 }, "item": { "name": "item name" } }, ... ],
"tax_breakdown": [ { "taxable_amount": 1325, "tax_amount": 331.25, "category": "S", "rate": 25 } ],
"totals": { "line_net": 1300, "charges": 25, "net": 1325, "tax": 331.25, "gross": 1656.25, "due": 1656.25 },
"payment": { "means_code": "30", "remittance_info": "Snippet1", "credit_transfers": [ { "iban": "IBAN32423940", "account_name": "AccountName", "bic": "BIC324098" } ] }
},
"validation": { "valid": true, "errors": 0, "warnings": 0,
"rule_sets": [ { "id": "XSD:ubl-invoice" }, { "id": "EN16931-UBL", "version": "EN 16931 validation artefacts 1.3.16" }, { "id": "Peppol-UBL" } ],
"issues": [] },
"timings_ms": { "detect": 0.5, "map": 14.4, "validate": 86.0, "total": 100.8 },
"credits": { "mode": "key", "remaining": 99 }
}When something is wrong, every failed rule carries a hint in the requested language (example, KSeF FA(3) in Polish):
{ "id": "XSD-UNEXPECTED-ELEMENT", "severity": "error", "rule_set": "XSD:fa3",
"message": "Element '{http://crd.gov.pl/wzor/2025/06/25/13775/}Adnotacje': This element is not expected. Expected is one of ( {http://crd.gov.pl/wzor/2025/06/25/1 …",
"hint": "XML zawiera element, którego schemat nie dopuszcza w tym miejscu. Nazwa elementu jest błędna, element należy do innego profilu/wersji (np. UBL 2.0 lub ZUGFeRD EXTENDED), jest zdublowany albo jest własnym rozszerzeniem. Usuń go lub zmień jego nazwę.",
"who": "sender", "location": "/*/*[4]/*[8]", "line": 43 }Related MCP server: InvoiceXML
Endpoints
Call | Returns |
| everything in one JSON (extras base64/inline) |
| canonical JSON only |
| validation report only |
| human-readable rendering, labels in the five languages |
| flat CSV |
| DATEV Buchungsstapel (EXTF 700, cp1252) |
| formats + rule versions · explain a rule id · field guide |
| which format each country's mandate asks for, and what we validate it with |
| EU VAT number: format offline, then live VIES, with a dated receipt |
| is a counterparty published on Peppol, and what can it receive |
Body: multipart field file, or the raw XML/PDF. Send a real User-Agent (Cloudflare rejects the default Python-urllib one with error 1010). Auth: X-Api-Key or Authorization: Bearer. One invoice = one credit whatever outputs you request; a file that carries several invoices (a FatturaPA lot) costs one per invoice. Remaining credits come back in X-Credits-Remaining.
Examples in this repo
examples/curl.sh— every endpoint onceexamples/node.mjs—fetch+FormData, no dependenciesexamples/python.py— standard library onlyexamples/n8n-workflow.json— mailbox attachment → InvoiceIn → JSON, importable into n8nmcp/server.json— manifest for the MCP registry;mcp/clients.md— Claude Desktop / Cursor configbridge/invoicein_mcp_bridge.py— local stdio MCP server that mirrors the hosted server's tools one-to-one and forwards every call (for clients without remote support;Dockerfilebuilds it;bridge/tools.jsonis the offline copy of the tool definitions)
Sample invoices
File | What it is | Source / licence |
| the same XRechnung 3.0 invoice in both syntaxes | KoSIT XRechnung testsuite, Apache-2.0 |
| Peppol BIS Billing 3 base example | OpenPeppol, Apache-2.0 |
| Factur-X hybrid PDF, EN 16931 profile | ZUGFeRD corpus (FNFE-MPE examples), Apache-2.0 |
| KSeF FA(3) official example no. 1 | Polish Ministry of Finance, public |
| FatturaPA 1.2 official example FPR01 | Agenzia delle Entrate, public |
Both XRechnung files produce the same canonical JSON (only the syntax-specific extensions block differs) — that is the point of the canonical model.
What it does not do
No OCR (a PDF without embedded XML is rejected with pdf-no-xml). Not a Peppol access point, not a French PDP, not a UAE Accredited Service Provider, not a KSeF or SdI client: it reads what you already received and never transmits an invoice anywhere. Factur-X/ZUGFeRD profiles below EN 16931 (MINIMUM, BASIC WL, BASIC) get schema and arithmetic checks only, because the EN 16931 rules would only produce noise there. Validation results are informational, not legal advice.
Licence
The examples in this repository are MIT. Sample invoices keep the licences listed above.
Available Tools
5 toolsinvoice_to_csvExport invoice as CSVARead-onlyIdempotentInspect
Export one European e-invoice as a flat CSV table for a spreadsheet or a database import. Document columns: invoice id, type, issue and due date, currency, seller and buyer name / VAT id / country, buyer and order reference, net / tax / gross / due totals, IBAN, BIC, remittance info, detected format and profile; with level=lines each row adds line id, item name, seller item id, quantity, unit, unit price, net amount, VAT category and rate, note. Use invoice_to_datev for DATEV bookkeeping and read_invoice for the full JSON. Input: XML (UBL, CII, XRechnung, Peppol BIS 3, FatturaPA, KSeF FA(2)/FA(3)) or a ZUGFeRD/Factur-X hybrid PDF up to 25 MB; plain or scanned PDFs without embedded XML are rejected (no OCR). A FatturaPA lot yields rows for every invoice in it. Returns the CSV as one text string: comma-separated, header row first, LF line endings, decimal point; an unreadable file returns a tool error with the reason. Costs one invoice credit per call; without an API key the anonymous quota is 20 invoices per day per IP. Nothing is stored.
| Name | Required | Description | Default |
|---|---|---|---|
| path | No | Absolute path of the invoice file on the machine running the server, used instead of file_base64. Only honoured over stdio (`python -m invoicein.mcp_server`); the hosted server at invoicein-api.peculiar.systems ignores it and answers with an error asking for file_base64. | |
| level | No | 'lines' (default) = one row per line item with the document columns repeated on every row; 'documents' = one row per invoice with the document columns only. | lines |
| file_base64 | No | Invoice file content, base64-encoded (standard alphabet). Accepted content: XML in UBL 2.1, CII D16B, XRechnung, Peppol BIS Billing 3, FatturaPA 1.2 or KSeF FA(2)/FA(3) syntax, or a ZUGFeRD 1.0/2.x or Factur-X hybrid PDF (the embedded XML is used). Max 25 MB decoded. Required unless `path` is given. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description is highly transparent: it states that nothing is stored, calls cost one credit, anonymous quota is 20 per day per IP, unreadable files return an error, and scanned PDFs without embedded XML are rejected. This aligns with the readOnly, idempotent, and non-destructive annotations and adds operational detail beyond 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 dense but each sentence adds relevant information: purpose, output schema, input formats, level behavior, error handling, quota, and storage. No filler or redundancy is present, and the most important usage distinctions 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?
The description covers all necessary invocation details: input sources, format constraints, parameter effects, output representation, error conditions, quota, and persistence guarantees. Taken with the schema, it gives an agent everything needed to call the tool correctly in varied deployments.
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?
Although the schema already covers parameters well, the description enriches them by detailing accepted input formats, max size, path behavior on stdio vs. hosted server, and the exact meaning of the 'lines' and 'documents' levels. It also explains what the output CSV columns will contain, tying parameter choices to output structure.
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 tool exports a European e-invoice as a CSV table, with explicit document and line columns. It also distinguishes itself from invoice_to_datev and read_invoice, making its purpose unambiguous even among siblings.
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 concrete guidance on when to use the tool, including accepted XML formats, hybrid PDF handling, the level parameter, and explicit alternatives for DATEV and full JSON output. It also covers error behavior, quotas, and the path vs. base64 modes, so an agent knows exactly how to invoke it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
invoice_to_datevExport invoice as DATEV BuchungsstapelARead-onlyIdempotentInspect
Convert one received (purchase) e-invoice into a DATEV Buchungsstapel import file (EXTF format 700) for German bookkeeping in DATEV Kanzlei-Rechnungswesen or Unternehmen online. Use it only for incoming invoices booked on the German side; use invoice_to_csv for a generic table, read_invoice for the raw data, validate_invoice for rule checks (this tool does not validate). Input: XML (UBL, CII, XRechnung, Peppol BIS 3, FatturaPA, KSeF FA(2)/FA(3)) or a ZUGFeRD/Factur-X hybrid PDF up to 25 MB; plain or scanned PDFs without embedded XML are rejected (no OCR). Returns the file content as one text string, decoded from cp1252: the EXTF header line, the DATEV column header, then one booking row per VAT-rate group with the gross amount and S/H flag (H for credit notes), the expense account chosen by rate under the selected SKR (e.g. SKR03 3400 for 19 %, 3300 for 7 %, 3200 for 0 %, 3120 intra-EU, 3425 reverse charge), the creditor account as Gegenkonto, document and due date, invoice number in Belegfeld 1, seller name as Buchungstext and the seller VAT id on intra-EU / reverse-charge rows. Save it as cp1252 with CRLF before importing; the account mapping is a default to confirm with the tax advisor. An unreadable file returns a tool error with the reason. Costs one invoice credit per call; without an API key the anonymous quota is 20 invoices per day per IP. Nothing is stored.
| Name | Required | Description | Default |
|---|---|---|---|
| skr | No | German standard chart of accounts that selects the expense accounts: '03' = SKR03 (default), '04' = SKR04. | 03 |
| path | No | Absolute path of the invoice file on the machine running the server, used instead of file_base64. Only honoured over stdio (`python -m invoicein.mcp_server`); the hosted server at invoicein-api.peculiar.systems ignores it and answers with an error asking for file_base64. | |
| file_base64 | No | Invoice file content, base64-encoded (standard alphabet). Accepted content: XML in UBL 2.1, CII D16B, XRechnung, Peppol BIS Billing 3, FatturaPA 1.2 or KSeF FA(2)/FA(3) syntax, or a ZUGFeRD 1.0/2.x or Factur-X hybrid PDF (the embedded XML is used). Max 25 MB decoded. Required unless `path` is given. | |
| creditor_account | No | Creditor account (Kreditor, written as Gegenkonto) the invoice is posted against: 4–9 digits as configured in the DATEV client, e.g. '70000' (default). Use the supplier's creditor number. | 70000 |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (readOnly, idempotent, non-destructive), the description discloses side effects: one invoice credit per call, anonymous quota of 20 per day per IP, nothing stored, error behavior for unreadable files, and the need to save as cp1252 with CRLF.
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-organized: purpose, usage, input details, output format, and operational notes. It front-loads the primary function and alternatives, and the length is justified by the complexity of the output format and constraints.
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 covers the full return content (header line, column header, booking rows with specific fields), input acceptance rules, error handling, cost, quota, storage, and default account mapping, leaving no gaps for the agent to call it successfully.
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?
Each parameter (skr, path, file_base64, creditor_account) is explained in detail beyond the schema, including defaults, accepted formats, size limits, and when the path parameter is ignored, fully complementing the 100% schema coverage.
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 tool converts a received purchase e-invoice to a DATEV Buchungsstapel (EXTF 700) and explicitly distinguishes it from sibling tools (invoice_to_csv, read_invoice, validate_invoice) by noting it does not validate and is specific to German bookkeeping.
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 provides explicit usage conditions ('Use it only for incoming invoices booked on the German side') and names alternatives for other cases, giving the agent clear guidance on when to select this tool over siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
invoice_to_htmlRender invoice as HTMLARead-onlyIdempotentInspect
Render one European e-invoice as a self-contained, printable HTML page: header, seller and buyer, line items, VAT breakdown, totals and payment details in one layout regardless of the source syntax, labels in lang. Use it to show an invoice to a person or to print it to PDF from a browser; it does not validate (use validate_invoice) and is not an accounting export (use invoice_to_csv or invoice_to_datev). Input: XML (UBL, CII, XRechnung, Peppol BIS 3, FatturaPA, KSeF FA(2)/FA(3)) or a ZUGFeRD/Factur-X hybrid PDF up to 25 MB; plain or scanned PDFs without embedded XML are rejected (no OCR). Returns the HTML document as one text string with inline CSS and no external assets; an unreadable file returns a tool error with the reason. Costs one invoice credit per call; without an API key the anonymous quota is 20 invoices per day per IP. Nothing is stored.
| Name | Required | Description | Default |
|---|---|---|---|
| lang | No | Language of the fix hints in the validation report and of the labels in HTML output. Default en. | en |
| path | No | Absolute path of the invoice file on the machine running the server, used instead of file_base64. Only honoured over stdio (`python -m invoicein.mcp_server`); the hosted server at invoicein-api.peculiar.systems ignores it and answers with an error asking for file_base64. | |
| file_base64 | No | Invoice file content, base64-encoded (standard alphabet). Accepted content: XML in UBL 2.1, CII D16B, XRechnung, Peppol BIS Billing 3, FatturaPA 1.2 or KSeF FA(2)/FA(3) syntax, or a ZUGFeRD 1.0/2.x or Factur-X hybrid PDF (the embedded XML is used). Max 25 MB decoded. Required unless `path` is given. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly and idempotent; description adds side-effect transparency: returns HTML string with inline CSS, errors on unreadable files, costs one credit per call, has anonymous quota, and stores nothing.
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?
Single paragraph, well-structured with clear sections (purpose, usage, input, output, cost), every sentence adds value; front-loaded with the primary purpose.
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 complexity of input formats and side effects, the description covers all essential aspects: input formats, size limit, output format, error behavior, cost, quota, and storage policy.
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 descriptions; description adds no new parameter semantics beyond the schema, so baseline 3 applies.
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 a specific verb (render) and resource (European e-invoice) with explicit output (HTML page), and clearly differentiates from sibling tools (not validate, not accounting export).
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 states when to use (show or print to PDF), what it does not do (validate, accounting export) with references to sibling tools, and describes input constraints (XML formats, hybrid PDF, 25MB limit).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_invoiceRead invoiceARead-onlyIdempotentInspect
Parse one European e-invoice into canonical EN 16931 JSON and validate it against the official rule sets in the same call. Use it when you need the invoice content (seller, buyer, lines, totals, payment) together with the verdict; use validate_invoice for a verdict-only answer, invoice_to_html / invoice_to_csv / invoice_to_datev for renderings. Input: XML (UBL, CII, XRechnung, Peppol BIS 3, FatturaPA, KSeF FA(2)/FA(3)) or a ZUGFeRD/Factur-X hybrid PDF up to 25 MB; plain or scanned PDFs without embedded XML are rejected (no OCR). Returns the parsed invoice, the validation report with fix hints in lang, and timings; an unreadable file returns ok=false with error.code/message/hint instead of raising. A FatturaPA lot returns only its first invoice, with a note. Costs one invoice credit per call; without an API key the anonymous quota is 20 invoices per day per IP. Nothing is stored.
| Name | Required | Description | Default |
|---|---|---|---|
| lang | No | Language of the fix hints in the validation report and of the labels in HTML output. Default en. | en |
| path | No | Absolute path of the invoice file on the machine running the server, used instead of file_base64. Only honoured over stdio (`python -m invoicein.mcp_server`); the hosted server at invoicein-api.peculiar.systems ignores it and answers with an error asking for file_base64. | |
| file_base64 | No | Invoice file content, base64-encoded (standard alphabet). Accepted content: XML in UBL 2.1, CII D16B, XRechnung, Peppol BIS Billing 3, FatturaPA 1.2 or KSeF FA(2)/FA(3) syntax, or a ZUGFeRD 1.0/2.x or Factur-X hybrid PDF (the embedded XML is used). Max 25 MB decoded. Required unless `path` is given. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | False when the file could not be read; then only `error` is set |
| note | No | Set when the file is a lot of several invoices: only the first is returned |
| error | No | Present when ok is false: code, message, hint |
| source | No | Detected syntax, format, profile and container |
| invoice | No | Canonical EN 16931 JSON: document, seller, buyer, lines, tax_breakdown, totals, payment, attachments, extensions; field names carry BT/BG numbers in /v1/schema |
| timings_ms | No | Processing time per stage: detect, map, validate, total |
| validation | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnly, idempotent, and non-destructive behavior. The description adds significant behavioral context beyond these: cost per call, anonymous quota limits, no storage guarantee, path handling differences between stdio and hosted server, and handling of FatturaPA lots (returns only first invoice with a note). These details give the agent a complete picture of side effects and constraints.
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 structured and efficient. Each sentence adds a distinct piece of information: purpose, usage alternatives, input details, output details, FatturaPA special case, cost/quota, and storage. There is no redundancy, and the most critical information (purpose and when to use) is front-loaded in the first two sentences. A slightly more compact wording could be possible, but nothing is extraneous.
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 (multiple input formats, validation, detailed output, error handling, cost, quota, storage), the description covers all relevant aspects. It specifies accepted formats, file size limits, path vs base64 input, output components (parsed invoice, validation report, timings), and error behavior. The existence of an output schema (not shown but present) means return values do not need to be explained in the description.
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% (3/3 parameters have detailed descriptions explaining purpose, defaults, and constraints). The description itself does not add parameter-level information beyond what the schema already provides. Since schema coverage is high, the baseline score of 3 applies, and no additional parameter clarification is needed.
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 tool's core function: 'Parse one European e-invoice into canonical EN 16931 JSON and validate it against the official rule sets.' It also distinguishes itself from sibling tools by explicitly mentioning alternatives (validate_invoice for verdict-only, invoice_to_html/csv/datev for renderings), making the tool's unique purpose unambiguous.
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 guidance on when to use this tool ('Use it when you need the invoice content together with the verdict') and when not to (suggests alternatives). It also details input methods (path vs file_base64), constraints (max 25 MB, accepted formats), and error behavior (returns ok=false instead of raising), covering all practical usage aspects.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
validate_invoiceValidate invoiceARead-onlyIdempotentInspect
Validate one European e-invoice against the official rule sets (XSD, EN 16931, XRechnung, Peppol BIS, FatturaPA, KSeF, arithmetic) and return the verdict without the invoice body. Use it for pass/fail and the list of errors and warnings; use read_invoice when you also need lines, totals and payment data. Input: XML (UBL, CII, XRechnung, Peppol BIS 3, FatturaPA, KSeF FA(2)/FA(3)) or a ZUGFeRD/Factur-X hybrid PDF up to 25 MB; plain or scanned PDFs without embedded XML are rejected (no OCR). Returns the validation report (valid flag, counts, rule sets with versions, failed rules with rule id, severity, fix hint in lang, affected field and who must act), the detected source and the document header; an unreadable file returns ok=false with error.code/message/hint instead of raising. Costs one invoice credit per call; without an API key the anonymous quota is 20 invoices per day per IP. Nothing is stored.
| Name | Required | Description | Default |
|---|---|---|---|
| lang | No | Language of the fix hints in the validation report and of the labels in HTML output. Default en. | en |
| path | No | Absolute path of the invoice file on the machine running the server, used instead of file_base64. Only honoured over stdio (`python -m invoicein.mcp_server`); the hosted server at invoicein-api.peculiar.systems ignores it and answers with an error asking for file_base64. | |
| file_base64 | No | Invoice file content, base64-encoded (standard alphabet). Accepted content: XML in UBL 2.1, CII D16B, XRechnung, Peppol BIS Billing 3, FatturaPA 1.2 or KSeF FA(2)/FA(3) syntax, or a ZUGFeRD 1.0/2.x or Factur-X hybrid PDF (the embedded XML is used). Max 25 MB decoded. Required unless `path` is given. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | Yes | False when the file could not be read; then only `error` is set |
| error | No | Present when ok is false: code, message, hint |
| source | No | Detected syntax, format, profile and container |
| document | No | Invoice header: id, issue_date, type_code, currency, due_date … |
| validation | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already indicate read-only, idempotent behavior, and the description complements them with concrete behavioral details: nothing is stored, unreadable files return an error object rather than throwing, and hybrid PDFs use embedded XML. 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?
The description is dense but every sentence adds necessary operational context—validation scope, input formats, output summary, error behavior, and cost. No filler or redundant phrasing 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 tool's complexity, the description covers accepted input syntaxes, output report components, language parameter, file delivery methods, error handling, and resource implications. It is sufficiently complete for an agent to invoke and interpret results 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?
All three parameters are fully described in the schema. lang has an enum and default, path explains its platform-specific usage, and file_base64 details accepted content, size limits, and the fallback relationship to path. Schema coverage is 100%.
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 action—validating a European e-invoice against named rule sets—and explicitly states that the result is the verdict without the invoice body. It also contrasts with read_invoice, making the tool's purpose unambiguous.
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 explains when to use this tool versus read_invoice, lists accepted input formats, notes path vs. base64 behavior, and provides cost, quota, and storage details. This gives an agent direct guidance for selection and invocation.
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.
5 tool updates
v0.1.1- Changed
invoice_to_csv6 fields changed- added
Input schema / properties / file_base64 / defaultAdded value: +"" - added
Input schema / properties / file_base64 / descriptionAdded value: +"Invoice file content, base64-encoded (standard alphabet). Accepted content: XML in UBL 2.1, CII D16B, XRechnung, Peppol BIS Billing 3, FatturaPA 1.2 or KSeF FA(2)/FA(3) syntax, or a ZUGFeRD 1.0/2.x or Factur-X hybrid PDF (the embedded XML is used). Max 25 MB decoded. Required unless `path` is given." - added
Input schema / properties / level / descriptionAdded value: +"'lines' (default) = one row per line item with the document columns repeated on every row; 'documents' = one row per invoice with the document columns only." - added
Input schema / properties / level / enumAdded value: +[ + "lines", + "documents" +] - added
Input schema / properties / pathAdded value: +{ + "default": "", + "description": "Absolute path of the invoice file on the machine running the server, used instead of file_base64. Only honoured over stdio (`python -m invoicein.mcp_server`); the hosted server at invoicein-api.peculiar.systems ignores it and answers with an error asking for file_base64.", + "title": "Path", + "type": "string" +} - removed
Input schema / requiredRemoved value: -[ - "file_base64" -]
- Changed
invoice_to_datev8 fields changed- added
Input schema / properties / creditor_account / descriptionAdded value: +"Creditor account (Kreditor, written as Gegenkonto) the invoice is posted against: 4–9 digits as configured in the DATEV client, e.g. '70000' (default). Use the supplier's creditor number." - added
Input schema / properties / creditor_account / patternAdded value: +"^[0-9]{4,9}$" - added
Input schema / properties / file_base64 / defaultAdded value: +"" - added
Input schema / properties / file_base64 / descriptionAdded value: +"Invoice file content, base64-encoded (standard alphabet). Accepted content: XML in UBL 2.1, CII D16B, XRechnung, Peppol BIS Billing 3, FatturaPA 1.2 or KSeF FA(2)/FA(3) syntax, or a ZUGFeRD 1.0/2.x or Factur-X hybrid PDF (the embedded XML is used). Max 25 MB decoded. Required unless `path` is given." - added
Input schema / properties / pathAdded value: +{ + "default": "", + "description": "Absolute path of the invoice file on the machine running the server, used instead of file_base64. Only honoured over stdio (`python -m invoicein.mcp_server`); the hosted server at invoicein-api.peculiar.systems ignores it and answers with an error asking for file_base64.", + "title": "Path", + "type": "string" +} - added
Input schema / properties / skr / descriptionAdded value: +"German standard chart of accounts that selects the expense accounts: '03' = SKR03 (default), '04' = SKR04." - added
Input schema / properties / skr / enumAdded value: +[ + "03", + "04" +] - removed
Input schema / requiredRemoved value: -[ - "file_base64" -]
- Changed
invoice_to_html6 fields changed- added
Input schema / properties / file_base64 / defaultAdded value: +"" - added
Input schema / properties / file_base64 / descriptionAdded value: +"Invoice file content, base64-encoded (standard alphabet). Accepted content: XML in UBL 2.1, CII D16B, XRechnung, Peppol BIS Billing 3, FatturaPA 1.2 or KSeF FA(2)/FA(3) syntax, or a ZUGFeRD 1.0/2.x or Factur-X hybrid PDF (the embedded XML is used). Max 25 MB decoded. Required unless `path` is given." - added
Input schema / properties / lang / descriptionAdded value: +"Language of the fix hints in the validation report and of the labels in HTML output. Default en." - added
Input schema / properties / lang / enumAdded value: +[ + "en", + "de", + "pl", + "it", + "fr" +] - added
Input schema / properties / pathAdded value: +{ + "default": "", + "description": "Absolute path of the invoice file on the machine running the server, used instead of file_base64. Only honoured over stdio (`python -m invoicein.mcp_server`); the hosted server at invoicein-api.peculiar.systems ignores it and answers with an error asking for file_base64.", + "title": "Path", + "type": "string" +} - removed
Input schema / requiredRemoved value: -[ - "file_base64" -]
- Changed
read_invoice18 fields changed- added
Input schema / properties / file_base64 / defaultAdded value: +"" - added
Input schema / properties / file_base64 / descriptionAdded value: +"Invoice file content, base64-encoded (standard alphabet). Accepted content: XML in UBL 2.1, CII D16B, XRechnung, Peppol BIS Billing 3, FatturaPA 1.2 or KSeF FA(2)/FA(3) syntax, or a ZUGFeRD 1.0/2.x or Factur-X hybrid PDF (the embedded XML is used). Max 25 MB decoded. Required unless `path` is given." - added
Input schema / properties / lang / descriptionAdded value: +"Language of the fix hints in the validation report and of the labels in HTML output. Default en." - added
Input schema / properties / lang / enumAdded value: +[ + "en", + "de", + "pl", + "it", + "fr" +] - added
Input schema / properties / pathAdded value: +{ + "default": "", + "description": "Absolute path of the invoice file on the machine running the server, used instead of file_base64. Only honoured over stdio (`python -m invoicein.mcp_server`); the hosted server at invoicein-api.peculiar.systems ignores it and answers with an error asking for file_base64.", + "title": "Path", + "type": "string" +} - removed
Input schema / requiredRemoved value: -[ - "file_base64" -] - added
Output schema / $defsAdded value: +{ + "Issue": { + "additionalProperties": true, + "properties": { + "field": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Affected canonical field with its EN 16931 BT/BG number", + "title": "Field" + }, + "hint": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Plain-language explanation of what the sender must fix, in the requested language", + "title": "Hint" + }, + "id": { + "description": "Rule id, e.g. BR-CO-15, BR-DE-2, PEPPOL-EN16931-R040, XSD-UNEXPECTED-ELEMENT", + "title": "Id", + "type": "string" + }, + "message": { + "description": "The rule's own message", + "title": "Message", + "type": "string" + }, + "severity": { + "description": "error, warning or info", + "title": "Severity", + "type": "string" + }, + "who": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Who has to act: sender or receiver", + "title": "Who" + } + }, + "required": [ + "id", + "severity", + "message" + ], + "title": "Issue", + "type": "object" + }, + "SourceInfo": { + "additionalProperties": true, + "properties": { + "container": { + "description": "xml or pdf", + "title": "Container", + "type": "string" + }, + "format": { + "description": "Detected format: xrechnung-ubl, xrechnung-cii, ubl, cii, peppol-bis3, zugferd, facturx, fatturapa, ksef-fa3, ksef-fa2", + "title": "Format", + "type": "string" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Profile or specification, e.g. 'EN 16931', 'XRechnung 3.0', 'FA (3)'", + "title": "Profile" + }, + "syntax": { + "description": "UBL, CII, FatturaPA or FA3", + "title": "Syntax", + "type": "string" + } + }, + "required": [ + "syntax", + "format", + "container" + ], + "title": "SourceInfo", + "type": "object" + }, + "Validation": { + "additionalProperties": true, + "properties": { + "errors": { + "description": "Number of failed rules with severity error", + "title": "Errors", + "type": "integer" + }, + "issues": { + "description": "Failed rules, each with a fix hint", + "items": { + "$ref": "#/$defs/Issue" + }, + "title": "Issues", + "type": "array" + }, + "notes": { + "description": "Informational notes about the validation run", + "items": { + "type": "string" + }, + "title": "Notes", + "type": "array" + }, + "rule_sets": { + "description": "Rule sets applied, with versions (XSD, EN 16931, XRechnung, Peppol, FatturaPA, KSeF, arithmetic)", + "items": { + "additionalProperties": true, + "type": "object" + }, + "title": "Rule Sets", + "type": "array" + }, + "valid": { + "description": "True when no rule of severity error failed", + "title": "Valid", + "type": "boolean" + }, + "warnings": { + "description": "Number of failed rules with severity warning", + "title": "Warnings", + "type": "integer" + } + }, + "required": [ + "valid", + "errors", + "warnings", + "rule_sets", + "issues" + ], + "title": "Validation", + "type": "object" + } +} - added
Output schema / additionalPropertiesAdded value: +true - added
Output schema / properties / errorAdded value: +{ + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Present when ok is false: code, message, hint", + "title": "Error" +} - added
Output schema / properties / invoiceAdded value: +{ + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Canonical EN 16931 JSON: document, seller, buyer, lines, tax_breakdown, totals, payment, attachments, extensions; field names carry BT/BG numbers in /v1/schema", + "title": "Invoice" +} - added
Output schema / properties / noteAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Set when the file is a lot of several invoices: only the first is returned", + "title": "Note" +} - added
Output schema / properties / okAdded value: +{ + "description": "False when the file could not be read; then only `error` is set", + "title": "Ok", + "type": "boolean" +} - removed
Output schema / properties / resultRemoved value: -{ - "title": "Result", - "type": "string" -} - added
Output schema / properties / sourceAdded value: +{ + "anyOf": [ + { + "$ref": "#/$defs/SourceInfo" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Detected syntax, format, profile and container" +} - added
Output schema / properties / timings_msAdded value: +{ + "anyOf": [ + { + "additionalProperties": { + "type": "number" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Processing time per stage: detect, map, validate, total", + "title": "Timings Ms" +} - added
Output schema / properties / validationAdded value: +{ + "anyOf": [ + { + "$ref": "#/$defs/Validation" + }, + { + "type": "null" + } + ], + "default": null +} - changed
Output schema / requiredPrevious value: -[ - "result" -]New value: +[ + "ok" +] - changed
Output schema / titlePrevious value: -"read_invoiceOutput"New value: +"ReadResult"
- Changed
validate_invoice16 fields changed- added
Input schema / properties / file_base64 / defaultAdded value: +"" - added
Input schema / properties / file_base64 / descriptionAdded value: +"Invoice file content, base64-encoded (standard alphabet). Accepted content: XML in UBL 2.1, CII D16B, XRechnung, Peppol BIS Billing 3, FatturaPA 1.2 or KSeF FA(2)/FA(3) syntax, or a ZUGFeRD 1.0/2.x or Factur-X hybrid PDF (the embedded XML is used). Max 25 MB decoded. Required unless `path` is given." - added
Input schema / properties / lang / descriptionAdded value: +"Language of the fix hints in the validation report and of the labels in HTML output. Default en." - added
Input schema / properties / lang / enumAdded value: +[ + "en", + "de", + "pl", + "it", + "fr" +] - added
Input schema / properties / pathAdded value: +{ + "default": "", + "description": "Absolute path of the invoice file on the machine running the server, used instead of file_base64. Only honoured over stdio (`python -m invoicein.mcp_server`); the hosted server at invoicein-api.peculiar.systems ignores it and answers with an error asking for file_base64.", + "title": "Path", + "type": "string" +} - removed
Input schema / requiredRemoved value: -[ - "file_base64" -] - added
Output schema / $defsAdded value: +{ + "Issue": { + "additionalProperties": true, + "properties": { + "field": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Affected canonical field with its EN 16931 BT/BG number", + "title": "Field" + }, + "hint": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Plain-language explanation of what the sender must fix, in the requested language", + "title": "Hint" + }, + "id": { + "description": "Rule id, e.g. BR-CO-15, BR-DE-2, PEPPOL-EN16931-R040, XSD-UNEXPECTED-ELEMENT", + "title": "Id", + "type": "string" + }, + "message": { + "description": "The rule's own message", + "title": "Message", + "type": "string" + }, + "severity": { + "description": "error, warning or info", + "title": "Severity", + "type": "string" + }, + "who": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Who has to act: sender or receiver", + "title": "Who" + } + }, + "required": [ + "id", + "severity", + "message" + ], + "title": "Issue", + "type": "object" + }, + "SourceInfo": { + "additionalProperties": true, + "properties": { + "container": { + "description": "xml or pdf", + "title": "Container", + "type": "string" + }, + "format": { + "description": "Detected format: xrechnung-ubl, xrechnung-cii, ubl, cii, peppol-bis3, zugferd, facturx, fatturapa, ksef-fa3, ksef-fa2", + "title": "Format", + "type": "string" + }, + "profile": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Profile or specification, e.g. 'EN 16931', 'XRechnung 3.0', 'FA (3)'", + "title": "Profile" + }, + "syntax": { + "description": "UBL, CII, FatturaPA or FA3", + "title": "Syntax", + "type": "string" + } + }, + "required": [ + "syntax", + "format", + "container" + ], + "title": "SourceInfo", + "type": "object" + }, + "Validation": { + "additionalProperties": true, + "properties": { + "errors": { + "description": "Number of failed rules with severity error", + "title": "Errors", + "type": "integer" + }, + "issues": { + "description": "Failed rules, each with a fix hint", + "items": { + "$ref": "#/$defs/Issue" + }, + "title": "Issues", + "type": "array" + }, + "notes": { + "description": "Informational notes about the validation run", + "items": { + "type": "string" + }, + "title": "Notes", + "type": "array" + }, + "rule_sets": { + "description": "Rule sets applied, with versions (XSD, EN 16931, XRechnung, Peppol, FatturaPA, KSeF, arithmetic)", + "items": { + "additionalProperties": true, + "type": "object" + }, + "title": "Rule Sets", + "type": "array" + }, + "valid": { + "description": "True when no rule of severity error failed", + "title": "Valid", + "type": "boolean" + }, + "warnings": { + "description": "Number of failed rules with severity warning", + "title": "Warnings", + "type": "integer" + } + }, + "required": [ + "valid", + "errors", + "warnings", + "rule_sets", + "issues" + ], + "title": "Validation", + "type": "object" + } +} - added
Output schema / additionalPropertiesAdded value: +true - added
Output schema / properties / documentAdded value: +{ + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Invoice header: id, issue_date, type_code, currency, due_date …", + "title": "Document" +} - added
Output schema / properties / errorAdded value: +{ + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Present when ok is false: code, message, hint", + "title": "Error" +} - added
Output schema / properties / okAdded value: +{ + "description": "False when the file could not be read; then only `error` is set", + "title": "Ok", + "type": "boolean" +} - removed
Output schema / properties / resultRemoved value: -{ - "title": "Result", - "type": "string" -} - added
Output schema / properties / sourceAdded value: +{ + "anyOf": [ + { + "$ref": "#/$defs/SourceInfo" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Detected syntax, format, profile and container" +} - added
Output schema / properties / validationAdded value: +{ + "anyOf": [ + { + "$ref": "#/$defs/Validation" + }, + { + "type": "null" + } + ], + "default": null +} - changed
Output schema / requiredPrevious value: -[ - "result" -]New value: +[ + "ok" +] - changed
Output schema / titlePrevious value: -"validate_invoiceOutput"New value: +"ValidateResult"
5 tool updates
v0.1.0- First observed
invoice_to_csv - First observed
invoice_to_datev - First observed
invoice_to_html - First observed
read_invoice - First observed
validate_invoice
TDQS
Scored across 5 tools
Each tool has a clearly distinct purpose (HTML rendering, JSON parsing, validation, CSV export, DATEV export). However, read_invoice and validate_invoice both involve validation and could be confused from names alone, though descriptions clarify the difference.
The naming pattern is inconsistent: three tools use noun_to_format (invoice_to_html, invoice_to_csv, invoice_to_datev) while two use verb_noun (read_invoice, validate_invoice). This mixed convention makes the tool names less predictable.
Five tools is a well-scoped set for the stated domain of European e-invoice processing, covering the main output formats and validation needs without unnecessary bloat.
The tool surface covers the core lifecycle: reading, validating, and converting to HTML, CSV, and DATEV. No significant gaps are apparent for the domain, especially since HTML can be used for PDF rendering.
Maintenance
Related MCP Connectors
Validate, generate & convert EU e-invoices (UBL, CII, XRechnung, Factur-X) — EN 16931 pre-validated.
Generate Factur-X PDFs, CII and UBL XML invoices from your AI assistant. Validate EN 16931 rules, extract invoice data, and get actionable error explanations. Try sample invoices free, no signup or API key required. Processing your own documents requires a free or paid key.
EN 16931: validate invoice data, UBL/CII or PDF; emit XRechnung/Peppol XML, never a PDF.
Create, validate, convert & extract compliant e-invoices (UBL, Factur-X, ZUGFeRD, XRechnung)
Related MCP Servers
- AlicenseAqualityDmaintenanceMCP server for DACH e-invoicing. Create XRechnung (UBL) and ZUGFeRD 2.3 (Factur-X CII) invoices, validate against EN 16931 rules, extract data from XML, and convert between UBL, CII and JSON formats.630 npm2MIT

InvoiceXMLofficial
AlicenseNot gradedqualityCmaintenanceInvoiceXML brings e-invoice compliance to your AI agent. Create, validate, convert, render, and extract structured invoices across UBL (Peppol BIS Billing 3.0, used worldwide), CII, Factur-X, ZUGFeRD, and XRechnung, all checked against the EN 16931 standard and official Schematron rules. Ask your assistant to generate a compliant invoice, validate one for errors, or convert between formats, with n5MIT- AlicenseAqualityDmaintenanceValidates EU electronic invoices (Peppol, XRechnung, FatturaPA, etc.) and explains validation error codes, enabling AI coding agents to check invoice validity and get fixes before rejection.338 npmMIT
- AlicenseAqualityDmaintenanceValidates electronic invoices (XRechnung, ZUGFeRD, Factur-X, Peppol BIS, etc.) against authority-pinned rules and explains failures.2151 npmMIT