Skip to main content
Glama
junter1989k-ai

serbia-invoice-mcp

README.md
# Serbia Invoice MCP 🇷🇸 — How can my AI agent issue a SEF eFaktura elektronska faktura in Serbia?

Remote MCP server that lets any AI agent issue **Serbia SEF eFaktura electronic invoices** (elektronska faktura) into the national **Ministry of Finance** system. It builds **UBL 2.1 SRB-CIUS** XML (Serbia's CIUS of EN 16931) and uploads it under the merchant's own SEF API key. Stateless, bring-your-own credential, never stores anything.

**Live endpoint:** `https://inv-rs.wishpool.app/mcp` · Registry: `app.wishpool/serbia-invoice-mcp`

## Quick start

```json
{
  "mcpServers": {
    "serbia-invoice": {
      "type": "http",
      "url": "https://inv-rs.wishpool.app/mcp",
      "headers": {
        "x-sef-api-key": "<your SEF API key>"
      }
    }
  }
}
```

You generate the **SEF API key** yourself in the SEF portal under **Settings → API management** (Podešavanja → Upravljanje API). Requests default to the SEF **demo** rail (no fiscal effect); add `x-sef-mode: prod` for the live rail. Your key never reaches storage — it is forwarded per-request to SEF as the official `ApiKey` header.

## Tools

| Tool | What it does |
|---|---|
| `create_invoice` | Build a UBL 2.1 SRB-CIUS invoice from seller PIB + name, buyer PIB + name + address + lines (name, qty, net unit price, VAT rate 20/10/0) and upload to SEF eFaktura. Returns `sales_invoice_id` + computed VAT totals. Optional `send_to_cir` for budget/public-sector buyers. |
| `query_invoice` | Check SEF status by `sales_invoice_id`: `NEW`, `SENDING`, `SENT`, `SEEN`, `APPROVED`, `APPROVED_WITH_RESERVATION`, `REJECTED`, `CANCELLED`, `STORNO`, `MISTAKE`, `OVERDUE`, `REMINDED`, `DELETED`. |
| `cancel_invoice` | Cancel (Otkazivanje) a sales invoice you sent, by `sales_invoice_id` + `cancel_comment`, before the buyer accepts it. |

Amounts are in RSD. You supply your own seller identity (`supplier_pib` + `supplier_name`) — SEF validates it against your API-key account. **After the buyer APPROVES, cancellation is closed** — corrections require a storno (credit) document (out of scope in v1).

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.

## Endpoints wrapped (SEF eFaktura publicApi REST)

- Base: DEMO `https://demoefaktura.mfin.gov.rs` · PROD `https://efaktura.mfin.gov.rs` (prefix `/api/publicApi`)
- Upload: `POST /sales-invoice/ubl?requestId={unique}&sendToCir={true|false}` (Content-Type `application/xml`, raw UBL body) → `{ InvoiceId, PurchaseInvoiceId }`
- Status: `GET /sales-invoice?invoiceId={id}` → invoice record incl. `Status`
- Cancel: `POST /sales-invoice/cancel?invoiceId={id}&cancelComment={text}`
- Auth: header `ApiKey` (forwarded from `x-sef-api-key`)

## Develop

```bash
node test/serve.js   # local server on :3238
node test/e2e.js     # protocol + validation + VAT math + UBL structure + fake-key live probes
```

## Safety

Pure stateless translation layer over the national SEF eFaktura API. The API key stays with the merchant and travels per-request in a header; nothing is stored. [Privacy policy](https://inv-rs.wishpool.app/privacy).

## Sister servers

Local invoices, one family: Romania e-Factura (inv-ro) · Mexico CFDI (inv-mx) · Brazil NF-e (inv-br) · Chile DTE (inv-cl) · Peru CPE (inv-pe) · India GST (inv-in). Local payments in 81 countries: [mcp.wishpool.app](https://mcp.wishpool.app).

MIT licensed.