Gofact

io.github.kOlapsisPublished by GitHub account kOlapsisv1.2.0Updated Oct 27, 2026

Creates compliant French e-invoices locally: Factur-X PDF/A-3 with EN 16931 CII XML, legal numbering

Overview

AI-generated overview

Local MCP server that lets an assistant create compliant French Factur-X e-invoices from HTML and JSON, and optionally submit them to a PDP.

What you can do
  • Manage issuing organizations: list, inspect, initialize and update them, each with its own identity, numbering registry and audit log
  • Look up clients and read the invoice template
  • Preview the next legal invoice number and list existing invoices
  • Create invoices from invoice data, producing a Factur-X PDF/A-3 with embedded EN 16931 CII XML after business-rule checks
  • Submit an invoice to a French e-invoicing platform and check its status
When to use it
Useful for French freelancers or small businesses that must issue Factur-X e-invoices and want to generate them conversationally from an MCP client such as Claude Desktop, Claude Code or LM Studio, with legal numbering and EN 16931 compliance handled locally.
Requirements
Runs as a local binary over stdio; a Blink browser (Chrome, Edge, Brave or Chromium) is needed for HTML to PDF rendering, and sandboxed snap or flatpak builds are skipped. Seller identity, SIRET/SIREN, VAT number, address, IBAN and PDP credentials come from environment variables or a .env file; GOFACT_SELLER_NAME is required unless the invoice data carries a seller block. PDP submission needs SUPERPDP_CLIENT_ID, SUPERPDP_CLIENT_SECRET and SUPERPDP_BASE.
Before you install
The .env file holds real business identity, IBAN and PDP secrets (SUPERPDP_CLIENT_SECRET) and must not be committed. send_invoice is the only destructive tool: it submits the invoice to an external PDP and requires explicit confirmation, and the PDP requires the seller to match the authenticated account. Invoice numbering is a locked legal sequence, and organizations stored in local directories contain real customer data.

Installation

In SourceWeft

  1. Open Gofact in the dashboard and add it to a workspace.
  2. Enable the server for the chats that should use its tools.

Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.

Other MCP clients

Follow the launch instructions in the repository.

README

gofact

🇫🇷 Version française

Small Go binary that turns a print-ready HTML invoice into Factur-X: a compliant PDF/A-3 with the CII EN 16931 XML embedded, and optionally submits it to a French e-invoicing platform (PDP — plateforme de dématérialisation partenaire).

Built for the invoicing of a French freelancer or small business (the French e-invoicing reform), and also shipped as a Claude Code plugin with the creer-facture skill.

Pipeline

JSON  ──EN 16931 rules──▶  rejected if non-compliant (before producing anything)      ──gofact──────────▶  factur-x.xml (CII EN 16931)HTML  ──headless Chrome─▶  PDF          (identical to Ctrl+P output, backgrounds included)PDF + XML ──pure Go─────▶  Factur-X     (PDF/A-3 + VERBATIM embedding of the XML)Factur-X  ──self-check──▶  re-read      (structure + integrity of the embedded XML)

Verbatim embedding — important. The XML is embedded byte for byte. An assembler that re-serializes it through its own model loses extended fields, in particular the PDP electronic routing addresses (BT-34/BT-49). gofact never touches the XML it has produced.

System dependencies

A browser, and that's it.

  • Chrome, Edge, Brave or Chromium — HTML → PDF rendering

Auto-detected on Linux, macOS and Windows (where Edge is preinstalled, so nothing to do). Sandboxed packages — snap, flatpak — are skipped: they cannot read the temporary files gofact hands them. To point at a specific executable: GOFACT_CHROME or -chrome.

The PDF/A-3 assembly is done in Go (pdfcpu): no Ghostscript, no Java, no first-run download. The sRGB ICC profile is embedded in the binary.

Compliance

Two checks, at two different moments:

  • EN 16931 business rules, applied on the model before producing anything. gofact refuses to issue an invoice it knows to be non-compliant, reporting the rule identifier (BR-50, BR-CO-15…) and the field to fix.
  • PDF self-check, after writing: the file is re-read, the Factur-X structures are verified (/AF, /OutputIntents, XMP, /EmbeddedFiles) and the embedded XML is compared byte for byte with the one that was generated.

Deep PDF/A-3b compliance is verified by veraPDF, via Mustang, in continuous integration — never on the user's machine:

sh
GOFACT_ORACLE_HTML=facture.html go test -tags=ci ./internal/facturx

Build

sh
go build -o gofact .go test ./...

Configuration

No identity and no secret is hard-coded. The invoice issuer, the payment IBAN and the PDP credentials come from the environment.

sh
cp .env.example .env    # then fill in your own values

gofact loads, in order and without ever overwriting an already-defined variable: the file passed to -env, otherwise ./.env, then $XDG_CONFIG_HOME/gofact/.env (~/.config/gofact/.env by default). The .env is git-ignored — never commit it.

VariablePurpose
GOFACT_SELLER_NAMESeller name. Required unless the JSON carries a seller block.
GOFACT_SELLER_SIRET / GOFACT_SELLER_SIRENFrench legal identifier (BT-30). The SIREN is derived from the SIRET.
GOFACT_SELLER_VAT_NUMBERIntra-community VAT number (BT-31). Empty under the 293 B franchise ⇒ BT-32 = SIREN.
GOFACT_SELLER_EMAILSeller e-mail.
GOFACT_SELLER_ADDRESS / _POSTAL_CODE / _CITY / _COUNTRYPostal address (country defaults to FR).
GOFACT_SELLER_ELECTRONIC_ADDRESS / _SCHEMEPeppol routing BT-34. Empty ⇒ SIREN + scheme 0225.
GOFACT_PAYEE_IBANPayment IBAN (BT-84). Empty ⇒ omitted from the invoice.
GOFACT_VAT_EXEMPTION_MENTION / _CODEDefault exemption mention and code (293 B).
SUPERPDP_CLIENT_ID / SUPERPDP_CLIENT_SECRET / SUPERPDP_BASEPDP credentials (secrets), for -send only.

With no seller configured, gofact fails explicitly rather than issuing an incomplete invoice. Every value can still be overridden per invoice via the JSON.

MCP server — talk to your AI to invoice

gofact mcp exposes invoicing as a local MCP server (stdio): from Claude Desktop, Claude Code, LM Studio or any MCP client, saying "make me an invoice for ACME, 2 days at €600" is enough. The AI is the interface; gofact guarantees the numbering (continuous legal sequence, locked and transactional allocation), EN 16931 compliance and archiving — locally.

sh
# Register in Claude Code, for example:claude mcp add gofact -- /path/to/gofact mcp

Tools: list_organizations, get_organization, init_organization, update_organization, search_client, get_invoice_template, preview_next_number, list_invoices, create_invoice, send_invoice (the only destructive tool — PDP submission, explicit confirmation required), get_invoice_status. Prompt: nouvelle-facture.

An organization (issuing entity) = a self-contained directory: identity in its .env, numerotation.json registry, journal.ndjson audit log, invoice template frozen at first issuance, and the invoices themselves. CLI management: gofact org list | init | show. No secret ever leaves a tool response.

Usage (CLI)

sh
# Simplest form: -data and -out derived from the HTML file namegofact -html "2026011 - Client.html"#   → reads "2026011 - Client.json", writes "2026011 - Client.pdf"
# Explicit paths + XML dump for debugginggofact -html f.html -data f.json -out f.pdf -xml f.xml
# Options-env <path>       # explicit .env file-validate=false   # skip the self-check of the produced PDF-chrome <path>    # force the Chrome executable-q                # quiet (errors only)

Exit code 0 if the Factur-X is generated (and compliant when -validate).

Sending to a PDP (SuperPDP)

gofact submits the Factur-X PDF to SuperPDP (OAuth2 client credentials).

sh
# generate then submit in one commandgofact -html f.html -send -poll# submit an already-generated PDFgofact send -pdf f.pdf -poll

The PDP requires that the invoice seller = the company of the authenticated account (legal identifier BT-30) and an electronic routing address (BT-34/BT-49, scheme 0225) for both the issuer and the recipient. See electronic_address below. -poll shows the lifecycle (fr:200 submitted → fr:201 issued → fr:202 received).

JSON format (sidecar)

All amounts are in cents (integers). The seller, the IBAN, the VAT regime and the French legal mentions have default values (environment) — the JSON only carries what varies.

json
{  "number": "2026011",  "type": "invoice",  "issue_date": "2026-06-29",  "buyer_reference": "D2026004",  "buyer": {    "name": "ACME SAS",    "siret": "55208131700015",    "email": "[email protected]",    "address": "1 rue de la Paix",    "postal_code": "75002",    "city": "Paris",    "country_code": "FR"  },  "lines": [    { "name": "Développement", "unit": "day", "quantity": "2.00",      "unit_price_ht_cents": 60000, "amount_ht_cents": 120000 }  ]}

Optional fields: due_date (defaults to "on receipt" = issue date), delivery_date (defaults to issue date), currency (defaults to EUR), vat (defaults to 293 B exemption; set {"exempt": false, "rate_pct": "20.00"} for standard VAT), seller, iban, title (the invoice subject, recorded in the registry), notes.

Notes: the three French legal mentions — late-payment penalties (PMD), recovery fee (PMT), discount (AAB) — are always emitted (BR-FR-05). notes adds to them: a note without subject_code goes out as general information (AAI); a note carrying PMD, PMT or AAB replaces the default mention with that code. No spec can drop them: generation refuses.

PDP routing: seller/buyer accept electronic_address (BT-34/BT-49) and electronic_address_scheme (e.g. "0225"). A PDP routes on these addresses, not on the postal address. Without a declared address, each party is routed on its SIREN (derived from the SIRET) with scheme 0225; the e-mail (EM) is only used when no legal identifier is known — it is not in the directory, and send_invoice then refuses the deposit. Example (seller override):

json
"seller": {  "name": "Studio Exemple", "siren": "123456789",  "electronic_address": "123456789", "electronic_address_scheme": "0225"}

Installation

Precompiled binary (GitHub release, no toolchain required):

sh
curl -fsSL https://raw.githubusercontent.com/kolapsis/gofact/main/install.sh | shgofact install -yes    # registers the MCP server in the detected clients

gofact install detects Claude Desktop, Claude Code, LM Studio and Cursor, shows what it intends to write (dry-run by default), backs up every file before modifying it and never overwrites a diverging entry without -force. Windows: install.ps1.

Package managers — the cask and the manifest live in this repository, hence the explicit URLs (Homebrew's short brew tap form requires a homebrew-* repository name; Homebrew core and the main Scoop bucket both gate on a popularity threshold gofact has not reached):

sh
brew tap kOlapsis/gofact https://github.com/kOlapsis/gofactbrew install kOlapsis/gofact/gofact
powershell
scoop bucket add gofact https://github.com/kOlapsis/gofactscoop install gofact

Claude Code plugin — the repository is also a plugin: creer-facture skill

  • declared MCP server:
/plugin marketplace add kolapsis/gofact/plugin install gofact@gofact

From source: go build -o gofact .

Organizations live in local directories (identity, registry, invoices) — never versioned here: they contain real data. GOFACT_INVOICES_DIR is still honored for compatibility with the historical skill.

Known limitations

  • Rendering relies on a Blink browser; sandboxed packages (snap, flatpak) are ignored because they cannot read outside $HOME.
  • Single VAT rate. Multi-rate is not supported.
  • Currency ≠ EUR: the VAT counter-value in EUR (BT-111) must be provided upstream (VATEur field of the model); not exposed in the JSON yet.
  • Only one PDP implemented (SuperPDP).

License

GNU AGPL v3 or later — see LICENSE.

Copyright (C) 2026 Benjamin Touchard.

gofact is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of merchantability or fitness for a particular purpose.

Source: README.md at commit 6319619

Tools

0
SourceWeft has not started this package in its sandbox yet, so its tools are not known.

Version history

1
  1. v1.2.0LatestSep 16, 2026

Score

50% of the applicable checks met

How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.

  • Reached in the last 30 days25 pts

    Keep the endpoint answering the MCP handshake; SourceWeft probes it every 30 days.

  • Auth declared10 pts

    Declare the credential headers in the registry entry, or keep the endpoint answering the probe so its auth can be classified.

  • Tools listed15 pts

    Answer tools/list without a credential, or ship a package that starts in a sandbox without one.

  • DescriptionRequired15 pts
  • Logo10 pts
  • Documentation15 pts
  • License10 pts