uk-company-check
by AxRS37
README.md
# uk-company-check — UK Companies House as MCP agent tools
An [MCP](https://modelcontextprotocol.io) server that turns the **free, official Companies House API** (the UK company registry — profiles, officers, filing history for every UK company) into four tools your AI agent can call.
Every UK B2B seller doing prospect research needs this data: is the prospect still trading, who are its directors, what industry codes is it under. Non-UK (US included) lead-gen and KYB sellers need it too — UK registry data is public, in English, and every company number is a join key.
- **Audience:** B2B prospect researchers, lead-gen sellers, KYB/due-diligence workflows, any agent that needs UK company facts.
- **Cost: £0.** The API key is free (2-minute signup, no credit card). The server has no other dependencies beyond the official MCP SDK.
- **No API key? It still runs.** The server starts, lists its tools, and returns a plain-English "here's how to get the free key" message instead of crashing (agents can read that to the user).
## What it does — the four tools
| Tool | What it answers |
|---|---|
| `search_companies(query)` | "Find me UK companies named X" → name, company number, status, incorporation date, address |
| `get_company(company_number)` | Full registry profile: status (active/dissolved/…), incorporation date, registered office, SIC codes **with plain-English descriptions**, current officers (directors & secretary) with appointment dates and occupations |
| `get_filing_history(company_number)` | What the company filed and when — confirmation statements, accounts, officer changes |
| `explain_sic_code(code)` | Decode any UK SIC code to its official plain-English description. **Works offline** (embedded official list) — no key, no network |
`get_company` calls two registry endpoints (profile + officers) and returns one merged answer, so an agent doesn't have to orchestrate. Company numbers are accepted with or without leading zeros (`123456` → `00123456`), case-insensitively for `SC`/`NI` prefixes.
## 5-minute setup
Requirements: Python 3.10+ and either [`uv`](https://docs.astral.sh/uv/) or `pip`. Nothing else — no Node, no database, no paid services.
**1. Get your free Companies House API key (2 minutes, no card).**
Go to <https://developer.company-information.service.gov.uk/signin> and register an account. Sign in, open **Applications**, create a new application, and copy the API key it shows you. That's the whole signup. (Do not commit the key anywhere — see the `.env.example`.)
Companies House documents the limit as **600 requests per 5-minute window** per key — orders of magnitude more than prospect research needs. This server also caches answers for an hour, so repeat questions cost no quota.
**2. Install.**
```bash
# with uv (fastest):
uv venv && uv pip install -e .
# or with plain pip:
python3 -m venv .venv && .venv/bin/pip install -e .
```
**3. Test the install (30 seconds).**
```bash
.venv/bin/python -m pytest tests/ -q
```
You'll see `43 passed` — all tests run offline against a pretend registry on localhost, so they never spend your API quota or need the network.
**4. Wire it into your MCP client.**
Example for Claude Desktop / Cursor / any MCP client that uses JSON config:
```json
{
"mcpServers": {
"uk-company-check": {
"command": "/ABSOLUTE/PATH/TO/uk-company-check/.venv/bin/python",
"args": ["-m", "uk_company_check"],
"env": { "CH_API_KEY": "your_real_api_key" }
}
}
}
```
(Any MCP client works the same way: launch `python -m uk_company_check` on stdio with `CH_API_KEY` in the environment. Alternative env name: `COMPANIES_HOUSE_API_KEY`.)
**5. Try it.** In your client, ask:
> Find UK companies called "Driver Plumbing" and tell me whether the top one is active, who its directors are, and what its SIC codes mean.
The agent will call `search_companies` → `get_company` → `explain_sic_code` and answer with sourced registry facts.
## Example tool calls and responses
These are real outputs from this server's test suite (run against a pretend registry whose fixture company mirrors the live API's exact field shapes — see `tests/fake_ch.py`). With your API key, the live Companies House returns the same shapes with real data.
`search_companies("driver plumbing")` →
```json
{
"query": "driver plumbing",
"total_results": 2,
"companies": [
{
"company_number": "00123456",
"company_name": "DRIVER PLUMBING & HEATING LTD",
"company_status": "active",
"incorporated": "2015-03-10",
"address": "28 London Road, Great Glen, Leicestershire, LE8 9FL",
"nature_of_business": "43220"
},
{
"company_number": "08765432",
"company_name": "OLD ROOFS LTD",
"company_status": "dissolved",
"incorporated": "2001-01-01",
"address": "1 Old Street, Leicester, LE1 1AA",
"nature_of_business": null
}
]
}
```
`get_company("123456")` → (officers listed newest appointment first; resigned officers filtered out)
```json
{
"company_name": "DRIVER PLUMBING & HEATING LTD",
"company_number": "00123456",
"status": "active",
"type": "ltd",
"incorporated": "2015-03-10",
"ceased": null,
"registered_office": "28 London Road, Great Glen, Leicestershire, LE8 9FL, United Kingdom",
"sic_codes": [
{ "code": "43220", "description": "Plumbing, heat and air-conditioning installation" },
{ "code": "99999", "description": "Dormant Company" }
],
"has_charges": false,
"has_insolvency_history": false,
"officers": [
{
"name": "Acme Corporate Services Limited",
"role": "corporate-secretary",
"appointed_on": "2020-01-01",
"occupation": null,
"nationality": null,
"year_of_birth": null
},
{
"name": "John Driver",
"role": "director",
"appointed_on": "2015-03-10",
"occupation": "Plumber",
"nationality": "British",
"year_of_birth": 1980
}
],
"note": null
}
```
`get_filing_history("00123456")` →
```json
{
"company_number": "00123456",
"total_count": 2,
"filings": [
{
"date": "2025-06-01",
"type": "CS01",
"category": "confirmation-statement",
"description": "confirmation statement (2025-05-10)",
"description_values": { "made_up_to": "2025-05-10" }
},
{
"date": "2024-12-15",
"type": "AA",
"category": "accounts",
"description": "legacy (group of companies' accounts made up to 31 March 2024)",
"description_values": { "description": "group of companies' accounts made up to 31 March 2024" }
}
]
}
```
`explain_sic_code("43220")` →
```json
{ "code": "43220", "description": "Plumbing, heat and air-conditioning installation" }
```
## How it's tested (and why you can trust the README)
43 tests in three layers — **all offline**, no network, no API quota:
1. **Client unit tests** (`tests/test_ch_api.py`) — company-number normalisation, caching (a cached call provably makes zero HTTP requests), friendly errors for 401/404/429, SIC descriptions.
2. **Tool layer tests** (`tests/test_server_tools.py`) — each tool's output shape, resigned-officer filtering, SIC enrichment, all four tools registered, every tool has a docstring (agent-visible descriptions).
3. **Protocol tests** (`tests/test_protocol.py`) — launch the real server as a subprocess, speak MCP JSON-RPC over stdio (initialize → tools/list → tools/call), and verify responses. Also proves zero-key mode starts and self-explains instead of crashing.
The fake registry (`tests/fake_ch.py`) mirrors the exact Companies House response field names (`company_name`, `company_status`, `sic_codes`, `officer_role`, `appointed_on`, …) as documented on the official reference pages.
Run them yourself:
```bash
.venv/bin/python -m pytest tests/ -v
```
## Works with both MCP SDK generations
The official Python SDK renamed its main class between versions: 1.x exposes `mcp.server.fastmcp.FastMCP`, 2.x renamed it to `mcp.server.mcpserver.MCPServer`. This server imports whichever is installed, so `pip install mcp` can give you either and it still runs. The protocol tests pass against both. (Tested against 1.14.0 and 2.2.0, on Python 3.12 and 3.14.)
## Who it's for
- **B2B sellers and agencies** doing UK prospect research (segment by SIC code, verify a company is active before outreach).
- **US and non-UK lead-gen sellers** — UK registry data is public, in English, structured; the company number is a stable join key for enrichment.
- **KYB / due-diligence agents** — status, officers, and filing history are the three core checks.
- **Any MCP client user** who just wants UK company facts on tap.
## Licence
MIT for the code (see `LICENSE`). The embedded SIC code descriptions in `src/uk_company_check/sic_data.py` are official UK SIC 2007 condensed-list data from Companies House, under the Open Government Licence v3.0 — Crown copyright preserved. Companies House data returned at runtime belongs to the UK Crown / Companies House and is used under OGL v3.0.This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues