{
  "markdown": "# @attestwire/mcp\n\nEuropean e-invoicing compliance as MCP tools — EN 16931, XRechnung, Peppol BIS\n3.0 and Factur-X. Ask what a rule means, validate a real invoice, emit invoice\nXML, check whether VIES is up, look up a French company against the 2026-2027\nmandate.\n\n**Five of the nine tools need no API key at all.** Connect with no credential\nand they work immediately — start there, add a key later.\n\n```sh\nnpx -y @attestwire/mcp\n```\n\n## At a glance\n\n| | |\n|---|---|\n| **Tools** | **9** — 5 keyless, 3 keyed and metered, 1 keyed and free |\n| **Hosted at** | `https://api.attestwire.com/mcp` — streamable HTTP, stateless, no session id |\n| **This package** | `npx -y @attestwire/mcp` — a stdio bridge to that endpoint, for clients that cannot speak remote HTTP |\n| **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. |\n| **Rules** | EN 16931 plus the national CIUS: XRechnung (UBL and CII), Peppol BIS 3.0. 270 rule ids explained in plain English — most, not all, of what the validator checks. |\n| **Reads / writes** | UBL 2.1 `Invoice`, UBL 2.1 `CreditNote`, UN/CEFACT CII `CrossIndustryInvoice`, in both directions |\n| **Auth** | Optional `Authorization: Bearer aw_live_...` — a bearer API key, **not** OAuth |\n| **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](#3-add-a-key--two-stages-and-the-second-one-is-not-optional)). |\n| **Runtime** | Zero dependencies, Node ≥ 20, MIT |\n\n**The disclaimer, up front, because it is the thing people get wrong:** this is a\n**pre-flight, not a clearing house**. It handles **XML and never PDF** — a\nFactur-X or ZUGFeRD file is CII XML inside a PDF/A-3 container, and this server\nneither opens that container nor builds one. And a document that passes here can\nstill be rejected by KoSIT or by a receiving platform: rules that constrain the\nXML itself do not run on a file this server read. Nothing here is legal or tax\nadvice. The four limits are spelled out in full\n[below](#four-honest-limits-stated-up-front).\n\n## Quickstart\n\n### 1. Connect\n\nIf your client speaks streamable HTTP — Claude Code, Claude Desktop custom\nconnectors, Cursor — point it at the hosted endpoint and skip this package\nentirely:\n\n```sh\nclaude mcp add --transport http attestwire https://api.attestwire.com/mcp\n```\n\nIf your client can only spawn a local process, this package is a stdio bridge to\nthat same endpoint. Paste into `claude_desktop_config.json`, `.cursor/mcp.json`,\nor whatever your client calls its MCP config:\n\n```json\n{\n  \"mcpServers\": {\n    \"attestwire\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@attestwire/mcp\"]\n    }\n  }\n}\n```\n\nNo `env` block, no key, nothing to sign up for. See\n[most people do not need this package](#most-people-do-not-need-this-package)\nfor which of the two to pick.\n\n### 2. Make a call, with no credential\n\nAsk the agent, in these words or your own:\n\n> Use the attestwire MCP server: explain rule BR-DE-15.\n\n`explain_rule` is keyless, so this answers on a fresh connection — the rule's\nrequirement, the business term it constrains, a fix and an example. Four other\ntools work the same way with no key: `check_vies_status`,\n`check_french_readiness`, `list_approved_platforms` and `issue_api_key`.\n\nThat is the whole first run. Everything below is either the key (§3), the full\ntool list, or the limits.\n\n### 3. Add a key — two stages, and the second one is not optional\n\nAuthentication is supplied **when the client connects**: this bridge reads\n`ATTESTWIRE_API_KEY` once, at process start, and sends it as an\n`Authorization: Bearer` header; a client on the remote HTTP transport sends the\nheader from its own config. **Minting a key does not authenticate the connection\nit was minted on** — nothing a tool returns changes a live session's credential,\nand there is no automatic reauthentication to wait for.\n\nSo it is two stages, not one call:\n\n**Stage one — get a key.**\n\n1. **Mint it.** Ask the agent to call `issue_api_key` with your email address,\n   or fill in the browser form at\n   [attestwire.com/#keyform](https://attestwire.com/#keyform) — same endpoint,\n   same instant key. It is free, there is no signup flow and no card.\n2. **Save it.** **The key is shown once and cannot be recovered** — only its\n   SHA-256 hash is stored. Put it in a password manager or a secret store, not\n   in the chat you are typing into. The browser form is the better route when\n   you would rather a one-time secret never entered a transcript at all.\n\n**Stage two — make the connection carry it.**\n\n3. **Configure it.** `ATTESTWIRE_API_KEY` in the `env` block for this stdio\n   bridge:\n\n   ```json\n   {\n     \"mcpServers\": {\n       \"attestwire\": {\n         \"command\": \"npx\",\n         \"args\": [\"-y\", \"@attestwire/mcp\"],\n         \"env\": { \"ATTESTWIRE_API_KEY\": \"aw_live_...\" }\n       }\n     }\n   }\n   ```\n\n   Or an `Authorization: Bearer aw_live_...` header if your client speaks remote\n   HTTP. `add` over an existing name is the step people skip, so remove first:\n\n   ```sh\n   claude mcp remove attestwire\n   claude mcp add --transport http attestwire https://api.attestwire.com/mcp \\\n     --header \"Authorization: Bearer aw_live_...\"\n   ```\n\n4. **Restart or reconnect** the MCP server. Editing the config of a running\n   client changes nothing until it reconnects.\n5. **Verify** with one metered call — `validate_invoice` on any invoice.\n\n**Four of the nine tools need a key**, not three: the three document tools —\n`validate_invoice`, `validate_invoice_xml` and `generate_invoice`, which are the\nmetered ones — plus `get_upgrade_link`, which is keyed but free, because it has\nto know *which* key it is quoting an upgrade for. Called without one, the three\ndocument tools return an error naming `issue_api_key` as the remedy and spelling\nout these steps.\n\nDo not mint twice: the limit is one free key per email address, so a second call\nanswers `409` rather than issuing a replacement. If a metered call still fails\nafter the reconnect, the problem is the config, not the key.\n\n| Variable | |\n|---|---|\n| `ATTESTWIRE_API_KEY` | Optional. Needed by `validate_invoice`, `validate_invoice_xml`, `generate_invoice` and `get_upgrade_link`; the other five tools ignore it. |\n| `ATTESTWIRE_MCP_URL` | Optional endpoint override. Defaults to `https://api.attestwire.com/mcp`. |\n\n## Tools\n\nYou can hand these tools a **JSON invoice model** or an **XML invoice file**.\nBoth of the syntaxes EN 16931 is written in are read and written: UBL 2.1\n`Invoice`, UBL 2.1 `CreditNote` and UN/CEFACT CII `CrossIndustryInvoice`, which\ncarries invoices and credit notes alike. What is *not* read or written is a PDF.\nSee [what this does not do](#four-honest-limits-stated-up-front).\n\n| Tool | Key? | |\n|---|---|---|\n| `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. 270 rules explained at time of writing — most, not all, of what the validator checks; the live number is in the tool's own description. |\n| `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. |\n| `check_french_readiness` | free | Look up a French company by SIREN, SIRET or name in INSEE SIRENE open data. |\n| `list_approved_platforms` | free | The DGFiP-approved French platforms (Plateformes Agréées, ex-PDP). |\n| `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). |\n| `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. |\n| `validate_invoice_xml` | key · 1 doc | Check an invoice **file** the user already has — a UBL 2.1 `Invoice`, a UBL 2.1 `CreditNote`, or a UN/CEFACT CII `CrossIndustryInvoice` (invoice or credit note alike). 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. Send the file as-is: the reader and the document type are both chosen from the root element. A credit note is not refused. Not a PDF reader. |\n| `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. |\n| `get_upgrade_link` | key · free | A checkout link (Paddle-hosted) for a paid plan. Returns a link; a human still has to open it. |\n\n### Four honest limits, stated up front\n\n* **XML, never PDF — in either direction.** Factur-X and ZUGFeRD are CII XML\n  inside a PDF/A-3 container. These tools handle the XML. They do **not** parse\n  a Factur-X or ZUGFeRD PDF, and they do **not** build one: no container, no\n  `factur-x.xml` attachment, no `/AFRelationship`. If you have a PDF, extract\n  the XML from it first. If you need a PDF, pass our XML to a Factur-X\n  packaging library. A `facturx-en16931` result is the payload, not a Factur-X\n  document.\n* **The two CII profiles are not equally evidenced, and neither is checked per\n  call.** The generator's `xrechnung-cii` *fixture* documents are run through\n  the official KoSIT validator on release and accepted. The `facturx-en16931`\n  ones are not: that profile's BT-24 is the core EN 16931 one, which matches no\n  XRechnung scenario, so KoSIT answers \"no scenario matched\" rather than passing\n  or failing them — and an absence of a verdict is not a pass. Neither case says\n  anything about the document *you* generate: nothing is sent to KoSIT at call\n  time.\n* **Credit notes yes; debit notes no, and one business term does not survive\n  one.** A credit note is a first-class document in both syntaxes now:\n  `invoiceTypeCode: \"381\"` emits a UBL `CreditNote` or a CII document with\n  `ram:TypeCode` 381, the reader picks the document type off the root element,\n  and the whole rule set runs on it unchanged. What is still refused is\n  `ubl:DebitNote`, for which EN 16931 has no binding at all. And BT-11, the\n  project reference, has no element in `UBL-CreditNote-2.1.xsd`, so no\n  conformant UBL credit note can carry one: it is dropped and reported rather\n  than emitted somewhere it does not belong. Reading a file is also a\n  pre-flight, not a verdict from the receiver: `validate_invoice_xml` checks the\n  model it read, not the XML a receiving platform judges, so a file that passes\n  can still be rejected.\n* `check_french_readiness` **cannot** confirm that a company has registered with\n  an approved platform — that lives only in the CAPTCHA-protected DGFiP\n  annuaire, which has no open API. The tool says so in every response.\n\nOne smaller gap, for completeness: the 25 arithmetic and decimal-precision rules\nthe validator fires (`BR-45`/`46`/`48`, `BR-CO-18`, `BR-DEC-19`/`20`/`23`, and\nthe per-category `-01` and `-09` families) have no plain-English write-up yet.\n`BR-12`–`BR-15` were on that list until `@attestwire/en16931` 0.6.0 and are not\nany more: a document read from XML can omit a total it is required to state, so\nthe four presence rules became reachable and now have harvested write-ups like\nany other rule. None of them can be tripped by anything a caller\nsends: they constrain the library's own computed arithmetic, which is what they\nare for. `explain_rule` says so for those ids and links\n[the rule reference](https://attestwire.com/rules/), which does cover them.\n\n## Most people do not need this package\n\nAttestwire is a **remote** MCP server at `https://api.attestwire.com/mcp`. Any\nclient that speaks streamable HTTP should point at it directly — that is the\n`claude mcp add --transport http` line in the quickstart.\n\nThis package exists for clients that can only spawn a local stdio process. It\nmoves JSON-RPC messages between stdio and HTTPS and does nothing else: no schema\nvalidation, no caching, no interpretation. New tools appear without updating it.\n\n## Notes\n\n* The key is never a tool argument on a metered tool — it is read from the\n  connection. `get_upgrade_link` is the one exception: it accepts an optional\n  `key`, so a key minted a minute ago can be upgraded before it has been\n  configured anywhere. Prefer the header even there, because an argument is\n  written into the agent's transcript.\n* Zero runtime dependencies. Node ≥ 20.\n* Diagnostics go to **stderr**; stdout carries protocol messages only.\n* `--help`, `--version`.\n* Free tier is 100 documents/month. `validate_invoice`, `validate_invoice_xml`\n  and `generate_invoice` cost one document each; nothing else costs anything.\n  A file that cannot be read at all — a PDF, a `ubl:DebitNote`, malformed bytes\n  — never reaches the rules and costs nothing.\n\nMIT · [attestwire.com](https://attestwire.com) ·\n[docs](https://api.attestwire.com/docs#mcp) ·\n[changelog](./CHANGELOG.md) · hello@attestwire.com",
  "bytes": 13546,
  "sha": "c51774e0928e0a92991a415664cf2c25256ee30fe22704e0519fc2d25f35e325",
  "repo_slug": "",
  "fonte": "npm",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_com_attestwire_en16931_1834dac2/readme"
}