siret-mcp
# siret-mcp
MCP server for French company registry data. Ask about any French company by name, SIREN or SIRET and get back clean JSON — with every registry code already translated into plain French.
The official registry hands you `"nature_juridique": "5710"`, `"activite_principale": "62.01Z"`, `"tranche_effectif_salarie": "12"`. An LLM handed that either guesses or hallucinates. This server hands it `"Société par actions simplifiée (SAS)"`, `"Programmation informatique"`, `"20 à 49 salariés"` — with the original code alongside so the answer stays checkable.
No API key. No account.
## Install
**Claude Code**
```bash
claude mcp add siret -- npx -y siret-mcp
```
**Cursor** — `~/.cursor/mcp.json`:
```json
{
"mcpServers": {
"siret": {
"command": "npx",
"args": ["-y", "siret-mcp"]
}
}
}
```
**Claude Desktop** — `claude_desktop_config.json`, same block as Cursor.
Restart the client. You should see four tools.
## Try these
- *"Is SIREN 552100554 still active, and what legal form is it?"*
- *"Find software companies in Loire-Atlantique with more than 20 employees."*
- *"What does NAF code 43.22A mean?"*
- *"Here's a SIRET from an invoice: 55210055400015 — verify it and tell me the registered address."*
- *"List every establishment for this SIREN and flag which is the head office."*
## Tools
| Tool | What it does |
|---|---|
| `search_companies` | Fuzzy search by name, trade name, acronym or officer. Filters: département, postal code, NAF code, active-only. Returns compact summaries. |
| `get_company` | Full profile from a SIREN (9 digits) or SIRET (14). Validates the Luhn checksum before spending a request. |
| `list_establishments` | All known sites for a SIREN, head office first, with a `complete` flag so you know if the list is exhaustive. |
| `explain_code` | Decodes NAF / legal form / workforce bracket / status. Offline, no API call. |
Plus a `siret://health` resource exposing cache stats.
## Design decisions worth knowing
**Codes always travel with labels.** Every coded field returns `{code, label, exact, source}`. `exact: false` means the label came from a fallback (a NAF section rather than the precise class), so a model can hedge appropriately instead of stating a guess as fact.
**Absent fields are named, not nulled.** Each profile carries a `missing` array. Given `"workforce": null`, a model will often invent a headcount. Given `"missing": ["workforce"]`, it says the registry doesn't hold it.
**Errors are returned, not thrown.** Failures come back as JSON with a `hint`, so the model can retry or reformulate rather than dying mid-conversation.
**Caching is the product, not an optimisation.** The upstream rate-limits bursts. A 6h TTL cache (`SIRENE_CACHE_TTL_MS`) is what makes this usable in an agent loop that asks about the same company nine times.
**Four tools, not twelve.** Every extra tool costs the calling model context and adds a way for it to pick wrong.
## Limitations
- **Code tables are partial.** Full NAF rev. 2 is ~732 codes and catégorie juridique ~300; this ships the common ones plus a fallback that flags itself as approximate (`exact: false`).
- **Backed by `recherche-entreprises.api.gouv.fr`**, not INSEE Sirene v3. No API key means this runs immediately. The trade-off is fewer fields and no exhaustive establishment listing.
- **Cache is in-process.** Fine for a local stdio server, wrong for a hosted multi-tenant one.
## Data & attribution
Data comes from the [API Recherche d'Entreprises](https://recherche-entreprises.api.gouv.fr) (DINUM), derived from INSEE SIRENE, under [Licence Ouverte](https://www.etalab.gouv.fr/licence-ouverte-open-licence/). Officer records may include a birth year. You are responsible for using the data lawfully.
## Development
```bash
git clone https://github.com/tbellicha/siret-mcp.git
cd siret-mcp
npm install
npm run build
npm test # node:test, offline
npm run test:live # hits the real API
npm run typecheck
```
## Licence
[MIT](./LICENSE) © 2026 tbellicha
TDQS
Scored across 4 tools
Each tool has a clear, separate job: searching companies, retrieving a full company profile, listing establishment sites, and explaining registry codes. The cross-references between search_companies and get_company reinforce their complementary roles rather than creating ambiguity.
All tool names follow a consistent lowercase snake_case verb_noun pattern: search_companies, get_company, list_establishments, explain_code. The naming is uniform, predictable, and accurately reflects each action.
Four tools is well-scoped for a read-only French business registry lookup server. Each tool covers a distinct part of the workflow without unnecessary duplication or bloat.
The server covers the core lookup lifecycle: fuzzy search, full company profile retrieval, establishment enumeration, and code translation. Since this is a read-only registry service, CRUD operations are not expected, and there are no obvious dead ends in the workflow.