@attestwire/mcp
v1.2.2
Published
stdio bridge to the Attestwire MCP server — fourteen e-invoicing tools, including reviewed invoice repair, Peppol recipient lookup and live VIES verification: validate invoice data, a UBL 2.1 / UN-CEFACT CII invoice file, or a Factur-X / ZUGFeRD PDF, agai
Maintainers
Readme
@attestwire/mcp
European e-invoicing compliance as MCP tools — EN 16931, XRechnung, Peppol BIS 3.0 and Factur-X. Ask what a rule means, validate a real invoice, emit invoice XML, check whether VIES is up, look up a French company against the 2026-2027 mandate.
Six of the fourteen tools need no API key at all. Connect with no credential and they work immediately — start there, add a key later.
npx -y @attestwire/mcpAt a glance
| | |
|---|---|
| Tools | 14 — 6 keyless, 7 keyed and metered, 1 keyed and free |
| Hosted at | https://api.attestwire.com/mcp — streamable HTTP, stateless, no session id |
| This package | npx -y @attestwire/mcp — a stdio bridge to that endpoint, for clients that cannot speak remote HTTP |
| Deterministic | The compliance tools are a rule engine, not a model. The same document against the same ruleset returns the same verdicts, in the same order, every time — no sampling, no temperature, nothing generated. The ruleset is pinned per engine release; GET https://api.attestwire.com/v1/versions names the one that is live. |
| Rules | EN 16931 plus the national CIUS: XRechnung (UBL and CII), Peppol BIS 3.0. 321 rule ids explained in plain English — every rule id the validator can report. |
| Reads / writes | UBL 2.1 Invoice, UBL 2.1 CreditNote, UN/CEFACT CII CrossIndustryInvoice, in both directions. Also reads a Factur-X / ZUGFeRD PDF; never writes one. |
| Auth | Optional Authorization: Bearer aw_live_... — a bearer API key, not OAuth |
| Free tier | 100 documents/month, no card. issue_api_key mints a key from inside the session — but minting does not authenticate the connection it was minted on: save it, configure it, reconnect (§3). |
| Paid plans | Solo €9/mo for 1,000 documents, Starter €29/mo for 5,000, Scale €99/mo for 50,000, or €290 and €990 a year for Starter and Scale billed yearly. get_upgrade_link returns the checkout link; a human opens it and pays. Every metered result reports the documents left and the reset date, and the call that crosses 80% carries a one-time notice naming the next plan. Plans and quotas. |
| Runtime | Zero dependencies, Node ≥ 20, MIT |
The disclaimer, up front, because it is the thing people get wrong: this is a
pre-flight, not a clearing house. It reads a Factur-X or ZUGFeRD PDF —
CII XML inside a PDF/A-3 container — and never builds one: no container, no
factur-x.xml attachment, no /AFRelationship. And a document that passes here
can still be rejected by KoSIT or by a receiving platform: rules that constrain
the XML itself do not run on a file this server read. Nothing here is legal or
tax advice. The four limits are spelled out in full
below.
Quickstart
1. Connect
If your client speaks streamable HTTP — Claude Code, Claude Desktop custom connectors, Cursor — point it at the hosted endpoint and skip this package entirely:
claude mcp add --transport http attestwire https://api.attestwire.com/mcpIf your client can only spawn a local process, this package is a stdio bridge to
that same endpoint. Paste into claude_desktop_config.json, .cursor/mcp.json,
or whatever your client calls its MCP config:
{
"mcpServers": {
"attestwire": {
"command": "npx",
"args": ["-y", "@attestwire/mcp"]
}
}
}No env block, no key, nothing to sign up for. See
most people do not need this package
for which of the two to pick.
2. Make a call, with no credential
Ask the agent, in these words or your own:
Use the attestwire MCP server: explain rule BR-DE-15.
explain_rule is keyless, so this answers on a fresh connection — the rule's
requirement, the business term it constrains, a fix and an example. Five other
tools work the same way with no key: check_vies_status,
check_french_readiness, list_approved_platforms, issue_api_key and
send_feedback.
That is the whole first run. Everything below is either the key (§3), the full tool list, or the limits.
3. Add a key — two stages, and the second one is not optional
Authentication is supplied when the client connects: this bridge reads
ATTESTWIRE_API_KEY once, at process start, and sends it as an
Authorization: Bearer header; a client on the remote HTTP transport sends the
header from its own config. Minting a key does not authenticate the connection
it was minted on — nothing a tool returns changes a live session's credential,
and there is no automatic reauthentication to wait for.
So it is two stages, not one call:
Stage one — get a key.
- Mint it. Ask the agent to call
issue_api_keywith your email address, or fill in the browser form at attestwire.com/#keyform — same endpoint, same instant key. It is free, there is no signup flow and no card. - Save it. The key is shown once and cannot be recovered — only its SHA-256 hash is stored. Put it in a password manager or a secret store, not in the chat you are typing into. The browser form is the better route when you would rather a one-time secret never entered a transcript at all.
Stage two — make the connection carry it.
Configure it.
ATTESTWIRE_API_KEYin theenvblock for this stdio bridge:{ "mcpServers": { "attestwire": { "command": "npx", "args": ["-y", "@attestwire/mcp"], "env": { "ATTESTWIRE_API_KEY": "aw_live_..." } } } }Or an
Authorization: Bearer aw_live_...header if your client speaks remote HTTP.addover an existing name is the step people skip, so remove first:claude mcp remove attestwire claude mcp add --transport http attestwire https://api.attestwire.com/mcp \ --header "Authorization: Bearer aw_live_..."Restart or reconnect the MCP server. Editing the config of a running client changes nothing until it reconnects.
Verify with one metered call —
validate_invoiceon any invoice.
Eight of the fourteen tools need a key: seven metered checks plus
get_upgrade_link, which is keyed but free. Completed checks use one document;
unavailable live checks are uncharged. The live check tools send the relevant
identifier to VIES or OpenPeppol. Evidence is returned to the caller, not stored.
See the preflight documentation.
Do not mint twice: the limit is one free key per email address, so a second call
answers 409 rather than issuing a replacement. If a metered call still fails
after the reconnect, the problem is the config, not the key.
| Variable | |
|---|---|
| ATTESTWIRE_API_KEY | Optional. Needed by validate_invoice, validate_invoice_xml, generate_invoice, diagnose_invoice, lookup_peppol_participant, verify_vat_vies, get_recipient_profile and get_upgrade_link; the other six tools ignore it. |
| ATTESTWIRE_MCP_URL | Optional endpoint override. Defaults to https://api.attestwire.com/mcp. |
Tools
You can hand these tools a JSON invoice model, an XML invoice file, or
a Factur-X / ZUGFeRD PDF. Both of the syntaxes EN 16931 is written in are
read and written: UBL 2.1 Invoice, UBL 2.1 CreditNote and UN/CEFACT CII
CrossIndustryInvoice, which carries invoices and credit notes alike. A PDF is
read too, for the XML attached inside it; nothing here writes one.
See what this does not do.
| Tool | Key? | |
|---|---|---|
| explain_rule | free | One rule id (BR-DE-15, BR-CO-15, PEPPOL-EN16931-R010…) in plain English: what it requires, the business term it constrains, a fix and an example. 321 rules explained at time of writing — every rule id the validator can report; the live number is in the tool's own description. |
| check_vies_status | free | Is VIES (EU VAT number validation) up? Overall or per member state, with latency and 24h/7d uptime. Tells a bad VAT number apart from a down endpoint. |
| check_french_readiness | free | Look up a French company by SIREN, SIRET or name in INSEE SIRENE open data. |
| list_approved_platforms | free | The DGFiP-approved French platforms (Plateformes Agréées, ex-PDP). |
| issue_api_key | free | Mint a free key — 100 documents/month, no signup flow, no card. Minting alone does not authenticate the connection: save, configure, reconnect (§3). |
| send_feedback | free | Tell the people who build this what the user was trying to do when no tool here does it, or a result looked wrong or confusing. The goal in the agent's words, never invoice data; identifiers are scrubbed before storage, and nobody can reply to it. |
| validate_invoice | key · 1 doc | Check a JSON invoice object against EN 16931 plus the national CIUS. Every failure comes back as a teaching error: rule id, business term, what the rule requires, a concrete fix, and the XPath the rule would have landed on. |
| validate_invoice_xml | key · 1 doc | Check an invoice file the user already has — a UBL 2.1 Invoice, a UBL 2.1 CreditNote, a UN/CEFACT CII CrossIndustryInvoice (invoice or credit note alike), or a Factur-X / ZUGFeRD PDF. Same teaching errors, plus which syntax it read, the document's BT-24/BT-23, and everything in the file that did not reach the invoice model. A PDF's attachment and XMP metadata are checked too, as findings that never fail it; PDF/A conformance and whether the page agrees with the XML are not. Send XML as text and a PDF base64-encoded; a credit note is not refused. |
| generate_invoice | key · 1 doc | Emit compliant XML from a JSON invoice object. The profile chooses the syntax: xrechnung-cii and facturx-en16931 come back as CII, everything else as UBL 2.1. invoiceTypeCode 381 emits a credit note in either syntax. Refuses an invalid invoice rather than emitting XML that passes nothing. |
| diagnose_invoice | key · 1 doc | Diagnose JSON/XML and provider rejection text/SVRL; apply explicitly reviewed revisions and revalidate. |
| lookup_peppol_participant | key · 1 doc | Check exact recipient and advertised document support through OpenPeppol. Unavailable results are uncharged; registration does not prove delivery. |
| verify_vat_vies | key · 1 doc | Dated VIES observation: valid, invalid, or unavailable. Unavailable results are uncharged. |
| get_recipient_profile | key · 1 doc | From the buyer's country and one identifier (VAT id, Leitweg-ID, SIREN/SIRET, KBO number, GLN or Peppol id): how to invoice them — channel, format, and the fields the invoice needs — checked against VIES, OpenPeppol and the French register. Uncharged when the identifier fails its own check digits or every source is unavailable. |
| get_upgrade_link | key · free | A checkout link (Paddle-hosted) for a paid plan (see the table above). Returns a link; a human still has to open it. |
Four honest limits, stated up front
- Reads a Factur-X or ZUGFeRD PDF now; still never writes one. Factur-X
and ZUGFeRD are CII XML inside a PDF/A-3 container.
validate_invoice_xmlreads one — send the file's bytes base64-encoded inpdf_base64, capped at 1 MB (about 750 KB of PDF); a larger file goes toPOST /v1/validateover the HTTP API instead. It checks the attachment and the XMP metadata too, as findings that never fail the result; PDF/A conformance itself, and whether the drawn page agrees with the XML, are not checked. No tool here builds a PDF — no container, nofactur-x.xmlattachment, no/AFRelationship— though the HTTP API does, on every plan (POST /v1/generate?format=pdfwith profilefacturx-en16931), watermarked as a preview on the free plan. Afacturx-en16931result from these tools is the payload, not a Factur-X document. - The two CII profiles are not equally evidenced, and neither is checked per
call. The generator's
xrechnung-ciifixture documents are run through the official KoSIT validator on release and accepted. Thefacturx-en16931ones are not: that profile's BT-24 is the core EN 16931 one, which matches no XRechnung scenario, so KoSIT answers "no scenario matched" rather than passing or failing them — and an absence of a verdict is not a pass. Neither case says anything about the document you generate: nothing is sent to KoSIT at call time. - Credit notes yes; debit notes no, and one business term does not survive
one. A credit note is a first-class document in both syntaxes now:
invoiceTypeCode: "381"emits a UBLCreditNoteor a CII document withram:TypeCode381, the reader picks the document type off the root element, and the whole rule set runs on it unchanged. What is still refused isubl:DebitNote, for which EN 16931 has no binding at all. And BT-11, the project reference, has no element inUBL-CreditNote-2.1.xsd, so no conformant UBL credit note can carry one: it is dropped and reported rather than emitted somewhere it does not belong. Reading a file is also a pre-flight, not a verdict from the receiver:validate_invoice_xmlchecks the model it read, not the XML a receiving platform judges, so a file that passes can still be rejected. check_french_readinesscannot confirm that a company has registered with an approved platform — that lives only in the CAPTCHA-protected DGFiP annuaire, which has no open API. The tool says so in every response.
explain_rule has a write-up for every rule id the validator can report. That
is not every rule of the official schematrons: the validator does not implement
all of them (the engine README lists what is excluded), and a rule it does not
implement has nothing to explain here.
Most people do not need this package
Attestwire is a remote MCP server at https://api.attestwire.com/mcp. Any
client that speaks streamable HTTP should point at it directly — that is the
claude mcp add --transport http line in the quickstart.
This package exists for clients that can only spawn a local stdio process. It moves JSON-RPC messages between stdio and HTTPS and does nothing else: no schema validation, no caching, no interpretation. New tools appear without updating it.
Notes
- The key is never a tool argument on a metered tool — it is read from the
connection.
get_upgrade_linkis the one exception: it accepts an optionalkey, so a key minted a minute ago can be upgraded before it has been configured anywhere. Prefer the header even there, because an argument is written into the agent's transcript. - Zero runtime dependencies. Node ≥ 20.
- Diagnostics go to stderr; stdout carries protocol messages only.
--help,--version.- Free tier is 100 documents/month; Solo €9/mo for 1,000 documents,
Starter €29/mo for 5,000, Scale €99/mo for 50,000 (€290 and €990 a year
for Starter and Scale if billed yearly).
validate_invoice,validate_invoice_xml,generate_invoiceanddiagnose_invoicecost one document each;lookup_peppol_participantandverify_vat_viescost one per conclusive result and nothing when the outside service is unavailable; nothing else costs anything. Each metered result ends with the documents left, the plan and the reset date, and the call that crosses 80% of the allowance carries a one-time notice naming the next plan. A file that cannot be read at all — a PDF with no invoice XML attached, aubl:DebitNote, malformed bytes — never reaches the rules and costs nothing.
Trademark
"Attestwire"™ and the Attestwire logo are trademarks of this project's owner. The MIT licence covers this package's code and grants no trademark rights. You may say your product uses or is built on it; you may not name or brand a product or service "Attestwire", or imply that we endorse yours.
MIT · attestwire.com · docs · changelog · [email protected]
