Companies House Control MCP Server
Pricing
from $50.00 / 1,000 tool calls
Companies House Control MCP Server
Answer questions about UK companies from the Companies House public register: company profile, filing history, and who the register says controls the company.
Pricing
from $50.00 / 1,000 tool calls
Rating
0.0
(0)
Developer
NexGen Watch
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
0
Monthly active users
2 days ago
Last modified
Share
🧰 Companies House Control MCP Server
Answer questions about UK companies from the Companies House public register — profile, filing history, and who the register says controls the company — live, for onboarding and investigation work.
This is a standby MCP server: it stays warm on Apify and answers tool calls from any MCP client (Claude Desktop, Cursor, an agent framework) at https://nexgenwatch--companies-house-control-mcp.apify.actor/mcp. Billing is pay-per-event: $0.05 when the server starts, then $0.05 per tool call (mcp-tool-call). Source: find-and-update.company-information.service.gov.uk.
No login, no source API key and no CAPTCHA solving are involved: the source is read logged-out.
📊 Sample Output
A standby server answers tool calls rather than writing a dataset, so the sample is the server's own live health answer (GET https://nexgenwatch--companies-house-control-mcp.apify.actor/, HTTP 200, read on 2026-09-17) followed by its tool table:
{"server": "companies-house-control","billing_gate": true,"declared_events": ["apify-actor-start","mcp-tool-call"],"scope": "The UK Companies House public register, via the public company-information web service -- one jurisdiction. The REST API is key-gated (401 without a key) and is not used. Officer appointments, charges and the contents of filing documents are separate pages this server does not open.","rate_limit_per_sec": 2.0,"rate_waits": 0,"ready": true}
| Tool | Arguments | What it returns |
|---|---|---|
search_companies | query: str, limit: int = 20 | Search the UK register by company name. Returns company numbers, names and the register's own status line. Note that the register also matches PREVIOUS names, so a hit need not contain your query. |
get_company_profile | company_number: str | The register's profile for one company: name, status, type, incorporation date, registered office, SIC codes and previous names. |
get_filing_history | company_number: str, pages: int = 1, limit: int = 50 | The company's filing-history listing, newest first. Each row carries its type, date, description and whether the register has finished processing the document. |
get_control | company_number: str | Persons with significant control: who the register says controls the company, their nature of control, status and the date they were notified. |
explain_limits | `` | What this server can and cannot tell you, and the four measured traps in the source. Read this before acting on any answer above. |
✅ What you get
5 tools, each returning a JSON object built only from what the source answered, with a scope and note field stating what the source does and does not cover. A lookup the source answers with 'not found' is a sourced answer (charged); malformed input or a source failure returns a notice that is NOT charged; nothing is ever fabricated.
The source, and why this one
The Companies House REST API is key-gated: measured today it answers
401 {"error":"Empty Authorization header"}. This server uses the public
company-information web service, which needs no key, no login and no cookie — the same
contract as our shipped UK register watch product.
Four things this server gets right that a naive read gets wrong
Every one measured live against the source on 2026-07-30.
1. The search page contains a template that looks exactly like a result
A document-wide scan of <li class="type-company"> returns 21 rows on a live search
page. One of them lives inside <script id="hit-template"> and its company name is the
literal string {{{title}}}. Scoped to the results container the same scan returns 20,
none of them templates.
This server extracts the results container first, and refuses if it is missing — rather than falling back to a document-wide scan, which is the bug itself.
2. Search matches previous names, so a hit need not contain your query
Measured: searching tesco returns KFORD TYRES (GORNAL) LTD at rank 2, because
its previous name was TESCO TYRES LTD. Correct register behaviour, and surprising if you
assume otherwise. Every row carries the register's own match note.
3. The newest filing usually has no document — and the id lives only in the document link
The transaction id appears only inside the "View PDF" link, and the register says of the
newest filing that the document "is being processed and will be available in 10 days".
Anything keyed on that link drops exactly the newest filing. Rows without one get a
deterministic key from date + type + description, and document_available tells you which
kind of key you are holding.
4. The public PSC page carries no official identifier
The only link inside a person-with-control block is a feedback survey. The strongest identity the page offers is company number + normalised name + notified-on date, and every record says so rather than implying a Companies House id.
Also: the date beside a previous company name is a period (
14 Dec 1981 - 25 Aug 1983effective_period.
Tools
| tool | what it answers |
|---|---|
search_companies | Companies matching a name, with number, status line and previous-name matches |
get_company_profile | Name, status, type, incorporation date, registered office, SIC codes, previous names |
get_filing_history | The filing-history listing, newest first, with document-processing state |
get_control | Persons with significant control: who, what control, status, notified date |
explain_limits | What this server will and will not say, and the four traps above. Read before acting. |
Scope
The UK Companies House public register. One jurisdiction. Officer appointments, charges, disqualifications and the contents of filing documents are separate pages this server does not open — only the filing-history listing.
This server reports what the public register prints. It does not verify identity, does not certify ownership or control, and its PSC records carry no official Companies House identifier.
robots.txt on that host is 404 — no Disallow and no Crawl-delay — and every outbound call
is paced anyway through one shared strict-pacing bucket at 2 requests/second,
deliberately slower than the 5/s used against JSON APIs because each call renders a page.
⚙️ Sample inputs
1. Connect an MCP client (Claude Desktop / Cursor style config; your Apify API token goes in the header):
{"mcpServers": {"companies-house-control-mcp": {"url": "https://nexgenwatch--companies-house-control-mcp.apify.actor/mcp","headers": {"Authorization": "Bearer <YOUR_APIFY_TOKEN>"}}}}
2. One tool call over JSON-RPC (what the client sends to /mcp; each call is one mcp-tool-call event):
{"jsonrpc": "2.0","id": 1,"method": "tools/call","params": {"name": "search_companies","arguments": {"query": "<query>","limit": 20}}}
3. Health check from a shell (free — no tool call is charged):
$curl -H "Authorization: Bearer $APIFY_TOKEN" https://nexgenwatch--companies-house-control-mcp.apify.actor/
🧾 JSON sample record
The live health record above is the server's own answer; a tool result carries the fields listed in the tool table plus scope and note.
🔧 How it works
Source. find-and-update.company-information.service.gov.uk — endpoints: https://find-and-update.company-information.service.gov.uk. Public, logged-out reads only.
Standby. Apify keeps one server process warm; each MCP session is served by that process and idle servers are stopped by the platform. Nothing is cached between calls except what the source itself caches.
Charging. Every tool call charges one mcp-tool-call at $0.05 through Apify's pay-per-event billing before the answer is returned; the declared events are asserted against the live pricing at startup (billing_gate in the health answer).
What is not done. No login, no CAPTCHA bypass, no private data, no scraping of pages the source does not publish to any visitor.
💰 Pricing example
| Event | Free | Bronze | Silver | Gold |
|---|---|---|---|---|
Actor Start (apify-actor-start) | $0.05 | $0.05 | $0.05 | $0.05 |
Tool call (mcp-tool-call) | $0.05 | $0.05 | $0.05 | $0.05 |
- 10 tool calls in one session: $0.05 start + 10 × $0.05 = $0.55
- 100 tool calls in one session: $0.05 start + 100 × $0.05 = $5.05
- 1000 tool calls in one session: $0.05 start + 1000 × $0.05 = $50.05
A health check or a connection that makes no tool call charges only the $0.05 start fee. A sourced 'not found' answer is a completed tool call and is charged; a notice for malformed input or a source failure is not charged (settle() charges only chargeable outcomes).
⚖️ Legal & ToS
The server reads public data published by find-and-update.company-information.service.gov.uk to any visitor, identifies itself, and does not access accounts or private data. Use the answers in line with the source's terms and your local law; the intended use is B2B research and agent tooling.
❓ FAQ
Q: Do I need a source API key?
A: No. find-and-update.company-information.service.gov.uk is read logged-out. You need only your Apify API token to connect to the server.
Q: Which MCP clients work?
A: Any client that speaks the MCP HTTP transport: Claude Desktop, Cursor, Windsurf, LangChain/LlamaIndex MCP adapters and Apify's own MCP client. Point it at the /mcp URL above.
Q: What happens when the source has no answer?
A: A sourced 'not found' (for example a 404 for an unknown identifier) comes back as an answer with scope and note explaining what was checked (where the server carries those fields), and is charged as a completed call; malformed input or a source outage returns a notice that is not charged. Nothing is invented.
Q: How is a call billed?
A: One mcp-tool-call event per tool call at $0.05, plus $0.05 when the server starts. Idle time is not billed to you.
Q: Is it rate limited?
A: The server paces requests to the source (RATE_PER_SEC=2.0) and answers calls in the order they arrive.
Q: Can I call it without an MCP client?
A: Yes — the /mcp endpoint is plain JSON-RPC over HTTP (sample input 2), and GET / is a free health check.
🆘 Troubleshooting
- 401 / 403 from the server → the Authorization header is missing or the token is wrong → use
Bearer <your Apify API token>. - 400
Missing session ID→ the client hit/mcpwithout initialising an MCP session → let the MCP client connect (it performs the handshake); raw JSON-RPC needs the session header the initialise call returns. - Tool returns a notice instead of data → the input was malformed or empty, or the source failed → the call was not charged; check the
note/reasonfield, fix the input and call again. - First call is slow → the standby server was cold and Apify started it → later calls in the same session are fast.
🔗 Related Actors
- Cross-Border Sanctions Resolution MCP Server — Resolve a party name against the US OFAC SDN, EU consolidated and UK OFSI sanctions lists in one MCP call, with the match basis and each list's as-of…
- Crossref Citation MCP Server — An MCP server over the official Crossref REST API (api.crossref.org) — scholarly work
- EPO Publication Evidence MCP Server — Retrieve official European patent publications by number or publication day from the EPO publication server, with the INID-coded front page parsed in…
- 🏢 About NexGenData — NexGen Watch is NexGenData's fleet of 256 public monitoring and lookup actors built on official sources, pay-per-result. Browse the catalog at apify.com/nexgenwatch.
⭐ Found this useful?
If this server answered a question your agent could not, a quick review on the Apify Store helps other teams find it. Feature request or a source that changed? Open it from the Issues tab — every one is read.
