Poland Invoice MCP
README.md
# Poland Invoice MCP 🇵🇱 — How can my AI agent issue a KSeF structured e-invoice (faktura ustrukturyzowana) in Poland?
<!-- install-cta -->
## Use it in 60 seconds
Paste this into your MCP client config (Claude Desktop, Cursor, Windsurf, or any MCP-capable agent):
```json
{
"mcpServers": {
"poland-invoice": {
"type": "http",
"url": "https://inv-pl.wishpool.app/mcp"
}
}
}
```
Nothing to install. Credentials, when you need them, travel as HTTP headers on each request and are never stored — see the [threat model](https://mcp.wishpool.app/trust).
### Or run it yourself
Would you rather not send production credentials to a server you do not control? Deploy this identical code to your own account and point your agent at your own URL:
[](https://vercel.com/new/clone?repository-url=https://github.com/junter1989k-ai/poland-invoice-mcp)
```bash
git clone https://github.com/junter1989k-ai/poland-invoice-mcp && cd poland-invoice-mcp && npx vercel --prod
```
MIT-licensed. Self-hosting removes us from the picture entirely, at no cost and with no loss of function.
---
Remote MCP server that lets any AI agent issue **Poland structured e-invoices** (faktura ustrukturyzowana, schema **FA(3)**) through **KSeF 2.0** — *Krajowy System e-Faktur*, the Ministry of Finance **national government e-invoice API**. It builds the FA(3) XML, runs the encrypted KSeF online-session flow, and returns the assigned **KSeF number**. Stateless, bring-your-own credentials, never stores anything.
**Live endpoint:** `https://inv-pl.wishpool.app/mcp` · Registry: `app.wishpool/poland-invoice-mcp`
## Quick start
```json
{
"mcpServers": {
"poland-invoice": {
"type": "http",
"url": "https://inv-pl.wishpool.app/mcp",
"headers": {
"x-ksef-token": "your-ksef-authorization-token",
"x-ksef-nip": "1234567890",
"x-ksef-mode": "production"
}
}
}
}
```
Self-mint your `x-ksef-token` in the Ministry of Finance taxpayer portal ([ksef.podatki.gov.pl](https://ksef.podatki.gov.pl) → Tokeny / Uwierzytelnianie) and pass your 10-digit seller NIP in `x-ksef-nip`. Omit `x-ksef-mode` to stay in the MoF **TEST** environment (no fiscal effect). Your KSeF certificate stays with the Ministry of Finance — this server never sees it.
## Tools
| Tool | What it does |
|---|---|
| `create_invoice` | Build an FA(3) structured invoice and submit it to KSeF — `seller_name`, `buyer_nip` + `buyer_name`, `invoice_number`, `items` (name, quantity, `net_price`, `vat_rate` 23/8/5/0) in, **KSeF number** out. Seller NIP comes from the header; buyer NIP is validated with the official checksum; per-rate net/VAT and the gross total are computed for you. |
| `query_invoice` | Fetch an invoice by its KSeF number: status `ACCEPTED` (present in the national KSeF repository under your NIP = fiscal proof). |
Owner policy guardrails ride optional headers (`x-agentpay-max-amount`, `x-agentpay-approval-above`, `x-agentpay-allowed-tools`) — set by the human owner in client config; the agent cannot relax them. The cap applies to the invoice **gross total (PLN)**.
## Why there is no `cancel` tool
**KSeF has no cancel/void operation.** Once a structured invoice is accepted into the national system it cannot be deleted; a mistake is fixed by issuing a **separate correction invoice** (*faktura korygująca*, `RodzajFaktury=KOR`), which is its own document with its own KSeF number. So this server ships exactly two tools — `create_invoice` and `query_invoice` — rather than pretending a cancel exists. (Correction-invoice support can be added later as a distinct create path.)
## How it works (KSeF 2.0 flow)
1. **Auth handshake:** `POST /auth/challenge` → encrypt `token|timestampMs` with **RSA-OAEP (SHA-256)** using the MoF `KsefTokenEncryption` public certificate → `POST /auth/ksef-token` → poll `GET /auth/{ref}` → `POST /auth/token/redeem` for the access token (JWT).
2. **Encrypted session:** generate an AES-256 key + IV, encrypt the key with the MoF `SymmetricKeyEncryption` certificate (RSA-OAEP), `POST /sessions/online`.
3. **Submit:** AES-256-CBC-encrypt the FA(3) XML, `POST /sessions/online/{ref}/invoices` (with plaintext + ciphertext SHA-256 hashes), then `POST /sessions/online/{ref}/close` and read the KSeF number.
Public encryption certificates are fetched live from `GET /security/public-key-certificates` (X.509, `CN=Ministerstwo Finansów`), so key rotation is handled automatically and nothing is embedded.
## Develop
```bash
node test/serve.js # local server on :3231
node test/e2e.js # protocol + validation + VAT-math asserts + LIVE probes against api-test.ksef.mf.gov.pl
```
The e2e suite makes two **real** calls to the government KSeF **test** API: the credential-free `/auth/challenge` round-trip, and a full RSA-OAEP auth handshake with a placeholder token that surfaces KSeF's real structured auth-failure — the deepest verification possible without a portal-minted token.
## Safety
Pure stateless translation layer straight to the government KSeF API. The KSeF certification and taxpayer certificate stay with the Ministry of Finance; credentials travel per-request in headers, nothing is stored. [Privacy policy](https://inv-pl.wishpool.app/privacy).
## Sister servers
Invoices: Mexico CFDI 4.0 [inv-mx](https://inv-mx.wishpool.app) · Chile DTE [inv-cl](https://inv-cl.wishpool.app) · Brazil NF-e [inv-br](https://inv-br.wishpool.app) · Peru CPE [inv-pe](https://inv-pe.wishpool.app) · India GST [inv-in](https://inv-in.wishpool.app) · Local payments in 81 countries, one family: [mcp.wishpool.app](https://mcp.wishpool.app) · Taiwan e-invoice 電子發票 included.
MIT licensed.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessSyncing