Skip to main content
Glama
README.md
# czid-mcp

Czech entity-registry tools for AI agents over the Model Context Protocol — company lookup, VAT (DPH) status, insolvency/registry snapshot, RÚIAN address standardization, Czech identifier validation. Data: official **ARES REST API** (`ares.gov.cz`, public, no key) — open data CC BY 4.0 (ND).

Same skeleton as [barcode-mcp](../barcode-mcp): stateless Streamable HTTP + optional x402 USDC paywall.

## Tools

| Tool | Price | Description |
|---|---|---|
| `company_lookup(id)` | free | ARES base record: name, legal form, address, NACE, DIČ, registers, data box |
| `check_vat(ids[1..20])` | paid | RZP register: plátce DPH yes/no, since, tax office; batch up to 20 |
| `entity_status(id)` | paid | KYC snapshot: active?, register presence (VR/RZP/RS insolvency/RCNS/SZR…), insolvency record |
| `search_company(name)` | paid | ARES name search (prefix match) → IČOs |
| `address_check(address)` | paid | RÚIAN standardization (KOD ADM, PSC, city part) |
| `validate_cz(ico/dic/iban/variableSymbol)` | paid | Offline checksum validation (IČO ISO-7064 mod-11/10, IBAN mod-97, birth number) |

## Connect (hosted, no install)

Live endpoint, no API key for the free tools — registered in the official MCP Registry as `io.github.appvantagelabs2-a11y/czid`.

**Claude Code**
```bash
claude mcp add czid --transport http https://czid.casuyi.com/mcp
```

**Cursor / VS Code (Copilot) / Windsurf / any `mcpServers` JSON client**
```json
{
  "mcpServers": {
    "czid": { "type": "http", "url": "https://czid.casuyi.com/mcp" }
  }
}
```

**Claude Desktop** — Settings → Connectors → *Add custom connector* → URL above.

**Programmatic (JSON-RPC)** — MCP `2025-11-25`, Streamable HTTP:
```bash
curl -X POST https://czid.casuyi.com/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"company_lookup","arguments":{"id":"27082440"}}}'
```

Two ways to use the paid tools (`check_vat`, `entity_status`, `search_company`, `address_check`, `validate_cz`):

1. **x402 (permissionless)** — unpaid calls return HTTP `402` with USDC payment instructions; an x402-capable client pays and retries automatically. No account, no key.
2. **Trial key** — send `X-API-Key: <key>` for a free quota of calls per key (self-evaluation). Responses carry `X-Trial-Remaining: N`; when exhausted the call falls back to the x402 flow. Contact for a key / bulk billing.

Free tools (`company_lookup`) never require either.

## Examples and clients

- [`examples/curl.md`](examples/curl.md) — raw JSON-RPC: initialize, tools/list, free call, 402 challenge, paid with x402 or `X-API-Key`
- [`examples/claude-code.md`](examples/claude-code.md) — connect from Claude Code / Desktop / Cursor / any MCP client
- [`clients/python.py`](clients/python.py) — minimal Python client (stdlib only)
- [`clients/typescript.ts`](clients/typescript.ts) — minimal TypeScript client (fetch only)

## Run (self-host)

```bash
npm install
node http.js                 # :8790, all tools free
# paywalled:
PAY_TO_ADDRESS=0x... X402_NETWORK=base-sepolia PORT=8791 node http-paid.js
# stdio (for any MCP client):
node index.js
```

## Tests

```bash
node test/run.mjs            # 30 tests: offline validators + live ARES golden records
LIVE=0 node test/run.mjs     # offline only
node test/paid-call.mjs      # x402 round-trip (needs funded .buyer.json)
```

## Verified (2026-09-13)

- 30/30 tests green, incl. golden records (Alza.cz a.s. 27082440) and RÚIAN KOD ADM 25958895
- x402: unpaid `check_vat` → 402 challenge; paid → 200; **settled on-chain** (seller +0.005 USDC, Base Sepolia `0x2328`)
- free `company_lookup` passes paywall ungated
- IČO checksum formula verified against 50k real ICOs from ARES dump (99.99%)

## Architecture notes

- No gov-API dependency per call where avoidable: TTL caches (entity 24 h, VAT 1 h, address 7 d).
- VIES deliberately **not** used — returns false for known payers from datacenter IPs (verified). RZP via ARES is the CZ-authoritative source.
- Bulk dump (`/data/radek/ares/ares_vreo_all.tar.gz`, 860 MB, 1.29M XMLs) available for a nightly SQLite mirror — v2, kills upstream rate-limit risk.
- Error bodies structured Czech JSON from ARES (`kod: NENALEZENO` → clean `NOT_FOUND`, never a crash).

## Privacy / legal

Only legal-entity public data (ARES open data). Where RZP publishes a DIČ derived from a birth number (OSVČ), we surface exactly what the register publishes — no additional personal data beyond the registries themselves. Source + `datumAktualizace` in every response per CC BY 4.0 (ND).