registry-mcp
The server is a read-only MCP/REST service for looking up official company-registry data, currently for Norway (Brønnøysundregistrene/Enhetsregisteret) and the UK (Companies House).
lookup_company: fetch a full CompanyReport by national identifier — legal form, status, addresses, VAT, employees, share capital, deadlines, previous names, industry codes, and more
search_company: find companies by name, returning scored candidates with identifiers and basic details
company_deadlines: get the next statutory filing deadlines (e.g. annual accounts, confirmation statement) with due dates, and the legal/published reason each applies
validate_company_id: instantly check and normalise an identifier (checksum for Norwegian orgnr; shape/normalisation for UK CRN) with no network call
list_countries: discover which national registries are supported, plus their identifier schemes, licences, and API-key requirements
It also exposes a REST API matching these tools, resources like registry://rules/{country}, and a explain_company prompt, with all responses carrying cache/freshness metadata and citations.
Allows looking up company information, including statutory filing deadlines, for Tesco PLC from the UK Companies House register.
registry-mcp — the company registry MCP
Company data for AI agents, any country. One MCP server and REST API, three national registers today: the United Kingdom's Companies House, looked up by company number; Norway's Enhetsregisteret / Brønnøysundregistrene (brreg), looked up by organisasjonsnummer (orgnr); and Sweden's Bolagsverket, looked up by organisationsnummer — one JSON shape whichever you ask.
claude mcp add registry-mcp --transport http https://api.foretak.dev/mcp?src=readmeNo install step, over stdio:
claude mcp add registry-mcp -- uvx registry-mcpWhat makes it worth a tool slot:
Deadlines that cite the rule, not just a date.
company_deadlinesgives the next filing date and names why inapplies_because— a Norwegian legal form's statutory duty, or "Companies House publishes this date for the company itself" when the register states it rather than us computing it. Quote the reason, not just the number.Never more than 24 hours stale, and it says so. Every response carries
cachedandfetched_at. OpenCorporates' own knowledge base tells users to "allow 30 days" for a correction to reach its site — a 30× freshness gap, stated by the incumbent about itself.Seven tools, not fifty — five registry tools plus two ChatGPT connector aliases. Tool-selection accuracy degrades past 30-50 tools loaded into an agent's context, and some clients cap around 40. Seven tools is roughly 17% of that budget, next to competitors in this space shipping 23 to 78 tools for the same job.
Security. Read-only, always — nothing here writes to a register or anywhere else. No credentials are required from a caller; this deployment's own upstream credential (COMPANIES_HOUSE_API_KEY) is read from the environment and never logged or returned. The base lookup calls three named upstreams and nothing else: data.brreg.no, api.company-information.service.gov.uk and gw.api.bolagsverket.se. include=["lei"]/include=["parents"] additionally call api.gleif.org (GLEIF, CC0, keyless); include=["peppol"] additionally resolves a DNS record at the Peppol SML and calls whichever SMP host it names for that participant, falling back to the Peppol Directory (directory.peppol.eu) only when neither answers — see the attachments above. No personal data beyond what each national register already publishes about the entity itself — and because a Swedish sole trader's company number is their personnummer, the usage log stores no identifier at all for a country whose identifiers can be a natural person's (legal/privacy.md). This service does not perform sanctions, PEP or adverse-media screening, and it does not verify bank account details. Details: SECURITY.md.
One-click install, for a remote streamable-HTTP server:
Other clients (Claude Desktop, Cursor, VS Code, Cline, plain JSON configs): see docs/clients.md.
Add to ChatGPT
ChatGPT reaches an MCP server through a custom connector, and its deep research mode calls
exactly two tools — search and fetch — which this server ships alongside the five registry
tools. In ChatGPT, open Settings → Connectors, add a custom connector, and give it:
https://api.foretak.dev/mcp?src=readmeNo authentication, no key, no account. If your ChatGPT plan does not show custom connectors under Settings → Connectors, turn on Settings → Security and login → Developer mode first, then add the URL from https://chatgpt.com/plugins.
search takes one free-text query — a company name, a national identifier, or a name plus a
country ("Tesco United Kingdom") — and returns citable rows; fetch takes a row's id
("NO:923609016") and returns that company's register record and its statutory filing
deadlines, with the full JSON of both in metadata.
Related MCP server: nordic-registry-mcp-server
Add to Claude Desktop
Claude Desktop takes the same URL as a custom connector: Settings → Connectors → Add custom
connector, then https://api.foretak.dev/mcp?src=readme. No key. For a local stdio install instead, see
Configuration.
Status:
0.4.2, live —GET /healthreturns{"version":"0.4.2","countries":["GB","NO","SE"]}. The five registry tools and their response shapes are frozen; two connector aliases (search,fetch) wrap them for ChatGPT and add no new shape. The hosted API atapi.foretak.devis live, and listed in the official MCP registry asio.github.foretak/registry-mcp. Countries: United Kingdom (Companies House), Norway (brreg), Sweden (Bolagsverket) — see below for each country's identifier format and example calls.
Add to Claude Code
The same two commands as above — Streamable HTTP or local stdio. To add it as a project-level .mcp.json file instead of the CLI, see Configuration.
What it returns
$ curl https://api.foretak.dev/v1/NO/company/923609016
{
"country": "NO", "registry": "brreg",
"id": "923609016", "id_formatted": "923 609 016", "id_scheme": "organisasjonsnummer", "euid": null,
"name": "EQUINOR ASA",
"legal_form_code": "ASA", "legal_form": "Public limited company", "legal_form_local": "Allmennaksjeselskap",
"status": "active", "is_active": true, "registered_at": "1995-03-12",
"vat_registered": true, "vat_number": "NO923609016MVA", "vat_registered_at": "1989-07-01",
"employees": 21239, "share_capital": 5976872600.0, "share_capital_currency": "NOK",
"business_address": {"lines": ["Forusbeen 50"], "postal_code": "4035", "city": "STAVANGER"},
"advertising_protected": null,
"source": "Enhetsregisteret (Brønnøysundregistrene)", "license": "NLOD 2.0"
}Abridged — the full CompanyReport also carries previous_names, industry_codes, registers, purpose, parent_id, confidence, cached, fetched_at and notes. Every field is documented in llms-full.txt §5.
euid is the EU-wide identifier some member-state registers publish (Finland does; none of ours do yet) — never the LEI, never constructed from parts. advertising_protected is true/false/null: whether the register marks this entity as protected against direct-marketing use, null meaning the register publishes no such flag at all (Norway and the UK, today); where it is true (Sweden's reklamspärr, for one), a notes sentence states it and that marking must travel with any contact details you pass on.
The United Kingdom, same shape, same abridgement:
$ curl https://api.foretak.dev/v1/GB/company/00445790
{
"country": "GB", "registry": "companies-house",
"id": "00445790", "id_formatted": null, "id_scheme": "company number", "euid": null,
"name": "TESCO PLC",
"legal_form_code": "plc", "legal_form": "Public limited company",
"status": "active", "is_active": true, "registered_at": "1947-11-27",
"vat_registered": null, "vat_number": null,
"employees": null, "employees_reported": false,
"registers": {"insolvency": false},
"industry_codes": [{"code": "47110", "description": null, "scheme": "SIC 2007", "rank": 1}],
"business_address": {"lines": ["Tesco House, Shire Park", "Kestrel Way"], "postal_code": "AL7 1GA", "city": "Welwyn Garden City"},
"advertising_protected": null,
"published_deadlines": [
{"kind": "annual_accounts", "due_date": "2027-08-26", "period_end": "2027-02-26", "overdue": false, "source": "accounts.next_accounts.due_on"},
{"kind": "confirmation_statement", "due_date": "2027-07-02", "period_end": "2027-06-18", "overdue": false, "source": "confirmation_statement.next_due"}
],
"source": "Companies House (UK)", "license": "Crown copyright — Companies House public register, free to re-use"
}published_deadlines carries the dates the register publishes itself, with the upstream field each came from. It is [] for Norway and Sweden, which compute all of their own.
Sweden, added in 0.3.0, is where "one shape" starts to earn the claim:
$ curl https://api.foretak.dev/v1/SE/company/5560160680
{
"country": "SE", "registry": "bolagsverket",
"id": "5560160680", "id_formatted": "556016-0680", "id_scheme": "organisationsnummer", "euid": null,
"name": "Telefonaktiebolaget LM Ericsson",
"legal_form_code": "AB", "legal_form": "Private or public limited company", "legal_form_local": "Aktiebolag",
"status": "active", "is_active": true, "registered_at": "1918-08-19",
"vat_registered": null, "vat_number": null,
"employees": null, "employees_reported": false,
"industry_codes": [{"code": "70100", "description": "Verksamheter som utövas av huvudkontor", "scheme": "SNI 2007", "rank": 1}],
"postal_address": {"postal_code": "16483", "city": "STOCKHOLM", "country_code": "SE"},
"advertising_protected": null,
"published_deadlines": [],
"source": "Bolagsverket (bolagsverket.se)",
"license": "Free re-use (Bolagsverket/SCB high-value datasets, EU Open Data Directive) — the publisher names no licence"
}Bolagsverket names no licence for this data, so neither do we: the string says what the permission is and says plainly that there is no licence name to quote, because a familiar name in that field would be a fabrication.
Sweden publishes no status field at all. status is derived from three independent signals — a strike-off date, an ongoing winding-up or restructuring procedure, and Statistics Sweden's "economically active" flag — and is_active therefore means on the register and not winding down, which is not the same as trading. Where any of that is unavailable the answer is unknown, never active.
Two dates are computed, and each carries the provision it comes from:
$ curl "https://api.foretak.dev/v1/SE/company/5560160680/deadlines?today=2026-09-07"
{"kind": "general_meeting", "due_date": "2027-06-30", "days_until": 296, "rolled_forward": false, "period_label": "2026"}
{"kind": "annual_accounts", "due_date": "2027-07-31", "days_until": 327, "rolled_forward": false, "period_label": "2026"}Six months to the annual general meeting (aktiebolagslagen 7 kap. 10 §) and seven to the filing before a late fee bites (årsredovisningslagen 8 kap. 6 §). Neither date is rolled forward off a weekend, because no Swedish source says it moves. Both assume a financial year ending 31 December by default — a notes sentence says exactly that, including how to shift both dates if the year end is different — but Bolagsverket's document list does publish a filed annual report's own year end: pass include=["filings"] (company_deadlines accepts it on both surfaces) to read it and replace the assumption with the register's own figure. search_company answers not_implemented for Sweden: the free API has four operations and none of them accepts a name.
Note the nulls. Companies House publishes no VAT status, no employee count and no share capital for any company, so those fields are null rather than guessed — null means "this register does not say", never "no". That honesty is the point of one shape across countries.
And the deadlines, which is where the UK module earns its keep:
$ curl "https://api.foretak.dev/v1/GB/company/00445790/deadlines?today=2026-09-04"
{
"company_name": "TESCO PLC", "today": "2026-09-04",
"deadlines": [
{"kind": "confirmation_statement", "local_name": "Confirmation statement (CS01)",
"due_date": "2027-07-02", "period_end": "2027-06-18", "days_until": 301,
"applies_because": "Companies House publishes this date for the company itself; it is the register's own figure, not a calculation."},
{"kind": "annual_accounts", "local_name": "Annual accounts",
"due_date": "2027-08-26", "period_end": "2027-02-26", "days_until": 356,
"applies_because": "Companies House publishes this date for the company itself; it is the register's own figure, not a calculation."}
]
}Where Companies House publishes a date, it is quoted; where it does not, the date is computed from a cited statute and applies_because says so. UK deadlines never roll forward off a weekend or bank holiday, and days_until goes negative for a filing the register still shows as overdue.
Running it yourself? The hosted service at api.foretak.dev has every credential configured. A self-hosted copy needs a free Companies House key for GB and an OAuth 2 client pair from Bolagsverket (BOLAGSVERKET_CLIENT_ID, BOLAGSVERKET_CLIENT_SECRET) for SE; without them those two countries return upstream_error naming the variable, and every other country keeps answering. Norway needs nothing.
Tools
Tool | What it does |
| Full |
|
|
|
|
|
|
| Which national registries are supported right now |
Connector aliases — for ChatGPT, which reaches an MCP server through exactly search and fetch (Add to ChatGPT); add no new response shape and have no REST twin.
Tool | What it does |
| ChatGPT connector alias for |
| ChatGPT connector alias for |
Plus the resource registry://rules/{country} (identifier rules, legal forms, deadline rules — read once instead of validating in a loop) and the prompt explain_company.
Attachments — a second, independent fetch alongside the base report, opt-in per name: include=["filings"] on MCP, ?include=filings on REST.
filings— what the entity has filed, and when (GB,NO,SE)charges— registered charges against the entity (GBonly)insolvency— winding-up and administration proceedings (GBonly)financials— the register's own financial figures (turnover, profit, balance sheet, equity and liabilities) for the latest filed accounting period, answering whether a supplier looks solvent — Norway's own key-figures feed, Sweden's read out of the entity's own filed annual report (NO,SE)lei— the Legal Entity Identifier GLEIF publishes for the entity, CC0-licensed and keyless (every country exceptSE)parents— the direct and ultimate corporate parent GLEIF's Level 2 data discloses, or the entity's own stated reason — a category word such asNATURAL_PERSONS, never a name — when it discloses none (same countries aslei)peppol— whether the entity can receive an e-invoice over the Peppol network, read live from the SML/SMP walk ahead of the 1 January 2027 e-invoicing duty (NOonly)
A country's declared set is supported_includes on list_countries / GET /v1/countries; see llms-full.txt for the two-level nullability and the per-country scope of filings.
parent_id and in_group on a Norwegian CompanyReport describe Enhetsregisteret's own parent/sub-unit relation for that entity — nothing more. There is no group-walk tool: following a corporate group upward means calling lookup_company again on parent_id, repeatedly, and that walk answers "what does the register list as this entity's parent?", not "who beneficially owns or controls this company?" — a different question this service does not answer. include=["parents"] above is a different route to an adjacent fact — GLEIF's opinion of who consolidates this entity's accounts, not Enhetsregisteret's own hierarchy and not beneficial ownership either. See llms-full.txt §5.
Why an agent checks a company
Three rules make this a duty rather than a nicety. Finanstilsynet's Rundskriv 15/2019 § 4.4.1 accepts an oppslag against Enhetsregisteret no older than three months, one month where the check rests on company details the customer supplied, and asks for notoritet about the lookup: what was consulted, and when. From 1 January 2027 Norwegian bookkeeping-obliged businesses must invoice each other by e-invoice, and the receiver is resolved in ELMA as 0192: plus organisasjonsnummer, the identifier these tools already take. From 10 July 2027, AMLR Article 23(4) requires "valid proof of registration or a recently issued excerpt of the register" for every new business relationship with a legal entity.
That is what source_url, fetched_at, cached, license and applies_because are for: which record was consulted, when it was read, whether it came from the 24 h cache, the terms it travels under, and whether a deadline was quoted from the register or computed from a named rule.
The limits, stated rather than implied: no sanctions or PEP screening; no bank-account verification, and the commonest invoice fraud is payment redirection, where the supplier is real and only the account number is wrong; and no beneficial owners, which brreg releases on application only, to categories of applicant that do not include a product vendor. Fuller version in llms-full.txt §9.
Configuration
{
"mcpServers": {
"registry-mcp": {
"command": "uvx",
"args": ["registry-mcp"],
"env": {
"REGISTRY_MCP_CONTACT_EMAIL": "you@example.com",
"COMPANIES_HOUSE_API_KEY": "your-companies-house-key"
}
}
}
}Drop COMPANIES_HOUSE_API_KEY if you only need Norway; every other country works without it.
{
"mcpServers": {
"registry-mcp": {
"command": "uvx",
"args": ["registry-mcp"],
"env": { "REGISTRY_MCP_CONTACT_EMAIL": "you@example.com" }
}
}
}macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"registry-mcp": {
"command": "uvx",
"args": ["registry-mcp"],
"env": { "REGISTRY_MCP_CONTACT_EMAIL": "you@example.com" }
}
}
}{
"mcpServers": {
"registry-mcp": { "command": "npx", "args": ["-y", "registry-mcp"] }
}
}npx registry-mcp shells out to uvx registry-mcp (falling back to pipx run registry-mcp), so Python 3.12+ and one of uv or pipx must be present.
{
"mcpServers": {
"registry-mcp": { "type": "http", "url": "https://api.foretak.dev/mcp?src=readme" }
}
}Environment variables — all optional:
Variable | Meaning |
| Contact address sent in the |
| Path to the local SQLite response cache (24 h TTL). Defaults to |
| Required for the United Kingdom ( |
| Required for Sweden ( |
REST
Every tool has a REST twin returning the identical JSON document.
# One company by organisasjonsnummer
curl https://api.foretak.dev/v1/NO/company/923609016
# Search by name
curl "https://api.foretak.dev/v1/NO/search?q=equinor&limit=5"
# Statutory filing deadlines, from a date you choose
curl "https://api.foretak.dev/v1/NO/company/923609016/deadlines?today=2026-01-15"
# Checksum-validate an identifier — no upstream call, instant
curl https://api.foretak.dev/v1/NO/validate/923609016
# Which countries are live, and which need an API key
curl https://api.foretak.dev/v1/countries
# The same five routes for the United Kingdom — GB, never UK
curl https://api.foretak.dev/v1/GB/company/00445790
curl "https://api.foretak.dev/v1/GB/search?q=tesco&limit=5"
curl "https://api.foretak.dev/v1/GB/company/00445790/deadlines?today=2026-09-04"
curl https://api.foretak.dev/v1/GB/validate/445790
# Sweden — four of the five. /search returns 501 not_implemented: the free
# Bolagsverket API has no name index, and the error's hint says so.
curl https://api.foretak.dev/v1/SE/company/5560160680
curl "https://api.foretak.dev/v1/SE/company/5560160680/deadlines?today=2026-09-07"
curl https://api.foretak.dev/v1/SE/validate/556016-0680Machine-readable docs: /llms.txt, /llms-full.txt, /openapi.json.
Adding your country
Norway is one folder. So is the United Kingdom: registries/gb/ was added as four files and one import line, and GB appeared in list_countries, in every tool, in /openapi.json and in registry://rules/GB on its own. So is Sweden — registries/se/ shipped in 0.3.0 with no change to core/, including the parts of Sweden that fit the abstraction worst: a register that publishes no status field, an operation the upstream does not offer (search_company answers not_implemented), and an identifier that can be a natural person's national ID.
Copy src/registry_mcp/registries/xx/ to registries/<cc>/, implement four methods, add one import line — nothing in core/ changes, and both surfaces plus the manifests light up for the new country automatically.
→ CONTRIBUTING.md — "Add your country", and the new country issue template to claim one first.
Development
uv sync --all-extras
uv run pytest # `-m "not live"` to skip the tests that hit the real registry
uv run mypy .
uv run ruff check .Layout:
src/registry_mcp/core/ country-neutral models, Registry ABC, rules, date helpers
src/registry_mcp/registries/ one folder per country — no/ (Norway), gb/ (UK), se/ (Sweden), xx/ (template)
src/registry_mcp/api/ FastAPI REST surface
src/registry_mcp/mcp/ FastMCP server (stdio + Streamable HTTP at /mcp)Documents
NORBIZ_SPEC.md— technical spec of the Norwegian moduleUK_SPEC.md— technical spec of the UK moduleSWEDEN_SPEC.md— technical spec of the Swedish moduleDECISIONS.md— interface and schema decisionsKEYWORDS.md— the canonical alias listSUBMISSIONS.md— registry submission statuslegal/terms.md— terms of use and data attribution
Data source and licence
Norwegian data comes from Enhetsregisteret (Brønnøysundregistrene), published under NLOD 2.0 — attribution required. UK data comes from the Companies House public register, Crown copyright, free to re-use with no attribution condition; we cite it anyway. Swedish data comes from Bolagsverket, with Statistics Sweden (SCB) as a second producer inside the same payload, free to re-use as a värdefull datamängd under the EU high-value-datasets regime — Bolagsverket's own words are "Det krävs inget avtal för att du ska få använda vårt API för värdefulla datamängder" and "Värdefulla datamängder är avgiftsfritt" — and Bolagsverket names no licence, so neither do we: the license string states the permission and states plainly that there is no licence name to quote. Every response carries source, source_url and license so the attribution travels with the data. This project's own code is MIT licensed. Not affiliated with or endorsed by Brønnøysundregistrene, Companies House or Bolagsverket.
Available Tools
5 toolscompany_deadlinesStatutory filing deadlines for a companyARead-onlyIdempotentInspect
Give the next occurrence of each statutory filing deadline a company faces.
country="NO" covers the Norwegian calendar (Regnskapsregisteret, Skatteetaten) for a
company looked up by organisasjonsnummer (orgnr, org.nr) in Brønnøysundregistrene /
Enhetsregisteret (brreg): årsregnskap, generalforsamling, skattemelding,
aksjonærregisteroppgaven, mva-melding, a-melding. country="GB" covers the two
Companies House obligations for a company number (CRN): the annual accounts filing and
the confirmation statement (CS01).
Pass today (YYYY-MM-DD) for a reproducible answer; it defaults to the server's
current UTC date. Quote due_date, not statutory_date. Each deadline's
applies_because states where the date came from — quote it rather than presenting a
date as unconditional fact: for Norway it names the legal form or flag and any
assumption behind a computed date, and for the UK it says whether the date is
Companies House's own published figure or one this tool computed from the statutory
period. UK dates never roll forward off a weekend or bank holiday, so due_date
equals statutory_date there; days_until goes negative for a filing Companies House
still shows as overdue rather than rolling it to the next cycle. An empty deadlines
list is a real answer — for Norway a bankrupt, deleted or compulsorily-liquidated
entity or a branch/sub-unit, and for the UK any company whose status is not active —
and notes explains why.
On error, this tool raises with the error text {"error": {"code", "message", "hint"}}. bad_request means today was not YYYY-MM-DD — fix the format and
retry. Any lookup_company error code (invalid_id, not_found,
unsupported_country, upstream_error, upstream_timeout) can also surface here,
since this tool looks the entity up first — follow that code's hint.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | The company's national identifier. Norway (country='NO'): a nine-digit organisasjonsnummer (orgnr), e.g. '923609016'; spaces, dots and a 'NO...MVA' VAT suffix are accepted and normalised. United Kingdom (country='GB'): a Companies House company number (CRN), eight characters, e.g. '00445790' or 'OC303675'; a short number is zero-padded for you. | |
| today | No | Date to compute deadlines from, YYYY-MM-DD. Defaults to the server's current UTC date — pass it explicitly for a reproducible answer. A value that is not YYYY-MM-DD is a bad_request naming the required format. | |
| country | No | ISO-3166-1 alpha-2 country code. 'NO' = Norway (Brønnøysundregistrene / Enhetsregisteret), 'GB' = United Kingdom (Companies House). 'UK' is not a country code here and is rejected. Call list_countries for the current set rather than hard-coding one. | NO |
Output Schema
| Name | Required | Description |
|---|---|---|
| notes | No | Caveats to surface to the user, carried over from the company report: why the list is empty, an unclassified legal form, a status that suspends filing. |
| today | Yes | The date 'next occurrence' was computed from, inclusive. Echoed back so the answer is reproducible and an agent can tell a cached answer from a fresh one. |
| country | Yes | ISO-3166-1 alpha-2, upper-case. |
| registry | Yes | Registry slug, e.g. 'brreg'. |
| deadlines | No | One entry per obligation kind, always the next occurrence, sorted by due_date. An empty list is a real answer, not an error — read `notes` for why. |
| company_id | Yes | Canonical national identifier the deadlines were computed for. |
| company_name | No | Registered name, so the caller can echo it back to a user. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the tool read-only, idempotent, open-world, and non-destructive, and the description adds substantial behavioral detail beyond that: `due_date` must be quoted rather than `statutory_date`, `applies_because` explains date provenance, UK dates never roll off weekends, `days_until` can go negative, and an empty list is a real answer. It even documents error propagation from `lookup_company` with actionable hints.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but every sentence carries operational weight: country coverage, result-field guidance, edge-case meanings, and error handling are all present with no filler. The top-loaded purpose sentence immediately orients the agent, and the paragraphs follow a logical order from scope to output interpretation to failures.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with three parameters, an output schema, and complex country-specific behavior, the description is unusually complete. It explains what each country's results mean, how to quote results, when an empty list is legitimate, how errors are structured, and how to recover from `bad_request`. Nothing an agent needs to call and interpret this tool correctly is left unaddressed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already covers all three parameters at 100% coverage, so the baseline is 3. The description adds meaningful extra semantics: it maps `country='NO'` to the Norwegian deadline calendar and `country='GB'` to the two Companies House obligations, and it links `today` to reproducibility and `bad_request` format errors. That is more than the schema alone provides, though not a full replacement for the schema's detailed `id` documentation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence states a specific verb and resource: 'Give the next occurrence of each statutory filing deadline a company faces.' It then distinguishes the two supported country scopes (Norway and the UK) and their registries and obligation types, so the agent can tell exactly what the tool covers and how it differs from sibling lookup/search/validation tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context on when this tool applies, including country-specific obligations, the meaning of an empty `deadlines` list, and the need to pass `today` for reproducible answers. It does not explicitly name alternatives or say 'use X instead when Y', so it falls just short of a 5, but the usage context is strong.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_countriesList supported national company registriesARead-onlyIdempotentInspect
List every national company registry this service can answer for right now, plus
each one's identifier scheme (id_scheme, id_example, id_description), source URL,
licence, and whether the upstream register needs a credential (requires_api_key, and
api_key_env naming the environment variable that must be set for it).
Call this before your first lookup in a country you have not used here before, or whenever a user names a country you are unsure is supported — never hard-code a country list of your own, since it grows as registry modules are added with no change to any other tool's shape. Stub/example modules are hidden; only registries that actually answer are listed. This tool has no error mode; a failure here is a bug, not something to retry differently.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| countries | No | One row per registry that can answer right now, sorted by country code. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, and the description adds genuinely valuable behavior beyond that: stub/example modules are hidden, the registry set grows dynamically without schema changes, and — most notably — 'This tool has no error mode; a failure here is a bug, not something to retry differently.' This last disclosure directly shapes agent behavior by preventing useless retry loops.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tightly packed paragraphs with no filler. The first establishes the verb, resource, and return fields; the second delivers usage timing, a prohibition, a filtering behavior, and error semantics. Every sentence earns its place and the core purpose is front-loaded in the opening clause.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter, read-only listing tool, this is complete. The output schema exists to document the return structure, annotations cover the safety profile, and the description covers everything else an agent needs: what is returned, when to call it, what is filtered out, and how to interpret failures. There are no gaps an agent would have to guess about.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters with an empty schema at 100% coverage, so there are no input semantics to clarify. Per the baseline for zero-parameter tools, a 4 is appropriate; the description correctly spends no space on inputs and instead uses that space for output contents and usage guidance.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource — 'List every national company registry this service can answer for right now' — and goes on to enumerate exactly what each entry contains (id_scheme, source URL, licence, credential requirements). This clearly differentiates it from the sibling tools (lookup_company, search_company, company_deadlines, validate_company_id), none of which list available registries.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit invocation conditions: 'Call this before your first lookup in a country you have not used here before, or whenever a user names a country you are unsure is supported.' It also provides a strong negative rule — 'never hard-code a country list of your own' — which prevents the agent from caching or assuming a static list. No alternative tool is relevant for this operation, so no exclusion is needed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
lookup_companyLook up a company in a national business registerARead-onlyIdempotentInspect
Look up a company by its national identifier and get the full CompanyReport — legal form, status, address, VAT registration where the register publishes it, board and accounts duties, employees, and more.
country="NO" is the norway company lookup for the norwegian business registry:
Brønnøysundregistrene / Enhetsregisteret (brreg), by organisasjonsnummer (orgnr,
org.nr). country="GB" is the uk company lookup at Companies House, by company number
(company registration number, CRN) — eight characters, digits or a two-letter prefix
and six digits, e.g. 00445790 or OC303675; short numbers are zero-padded for you, and
"UK" is not a country code here, use "GB".
Use it once you have the identifier — from the user, an invoice, a contract, or a
search_company hit's id; the identifier is normalised for you, so spaces, dots and
a Norwegian VAT suffix ('NO...MVA') are all accepted. Call list_countries if you are
unsure a country is supported. Read the returned notes before acting on the result —
it carries caveats such as bankruptcy, dissolution, a deleted entity, or an
unclassified legal form.
On error, this tool raises with the error text {"error": {"code", "message", "hint"}} (DECISIONS.md D-007). invalid_id means the identifier is malformed —
fix it or call search_company with the company name instead of retrying the same
string. not_found means the identifier is well-formed but no such entity exists —
call search_company. unsupported_country means no module exists for that country
yet — call list_countries. upstream_error/upstream_timeout means the national
register is unavailable; it has already been retried once here, so wait roughly a
minute before trying again yourself.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | The company's national identifier. Norway (country='NO'): a nine-digit organisasjonsnummer (orgnr), e.g. '923609016'; spaces, dots and a 'NO...MVA' VAT suffix are accepted and normalised. United Kingdom (country='GB'): a Companies House company number (CRN), eight characters, e.g. '00445790' or 'OC303675'; a short number is zero-padded for you. | |
| country | No | ISO-3166-1 alpha-2 country code. 'NO' = Norway (Brønnøysundregistrene / Enhetsregisteret), 'GB' = United Kingdom (Companies House). 'UK' is not a country code here and is rejected. Call list_countries for the current set rather than hard-coding one. | NO |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | Canonical national identifier, digits/letters only, no spaces or dots. |
| name | Yes | Current registered name. |
| No | Contact email as registered. | |
| notes | No | Caveats an agent should surface to the user, plain English, one per item. |
| phone | No | Contact phone as registered. |
| cached | No | True when served from our cache rather than a live fetch. |
| sector | No | Institutional sector description. |
| source | No | Human-readable source name, e.g. 'Enhetsregisteret (brreg.no)'. |
| status | No | Normalised lifecycle status. |
| country | Yes | ISO-3166-1 alpha-2, upper-case, e.g. 'NO'. |
| license | No | Licence of the upstream data, e.g. 'NLOD 2.0'. |
| purpose | No | Statutory purpose / objects clause, joined into one string. |
| website | No | Website as registered. |
| activity | No | Free-text description of actual activity. |
| in_group | No | Part of a corporate group. |
| registry | Yes | Registry slug, e.g. 'brreg'. |
| employees | No | Registered number of employees. None = not reported. |
| id_scheme | No | Name of the identifier scheme, e.g. 'organisasjonsnummer'. |
| is_active | No | Convenience mirror of `status == active`, so agents need no enum table. |
| parent_id | No | Identifier of the parent/owning entity, if any. |
| registers | No | Other national sub-registers this entity is or is not in, keyed by a lower-case slug, e.g. {'stiftelsesregisteret': false}. |
| confidence | No | How sure we are this record is the entity the caller meant (D-005). |
| fetched_at | No | UTC timestamp of the live fetch this record came from. |
| founded_at | No | Incorporation / foundation date. |
| is_subunit | No | True when this record is a branch/sub-unit, not a legal entity. |
| legal_form | No | English label, e.g. 'Private limited company'. |
| source_url | No | Direct URL of the upstream record, for citation. |
| vat_number | No | VAT identifier if it differs from `id` (Norway: id + 'MVA'). |
| sector_code | No | Institutional sector code. |
| id_formatted | No | The identifier as a local would write it, e.g. '923 609 016'. |
| registered_at | No | Date first entered in the central register. |
| share_capital | No | Registered share capital. |
| status_detail | No | One sentence in English explaining the status and the flag it came from. |
| has_board_duty | No | True when this legal form must have a registered board. |
| industry_codes | No | Industry classifications, primary first. |
| postal_address | No | Postal address. |
| previous_names | No | Former registered names, newest first. |
| vat_registered | No | Registered for VAT (Norway: Merverdiavgiftsregisteret). |
| bankruptcy_date | No | Date bankruptcy was opened. |
| deregistered_at | No | Date the entity was deleted from the register. |
| legal_form_code | No | National legal-form code, e.g. 'AS', 'ASA', 'ENK'. |
| business_address | No | Visiting/registered office. |
| confidence_basis | No | Why that confidence, e.g. 'exact identifier lookup'. |
| legal_form_local | No | Local label, e.g. 'Aksjeselskap'. |
| limited_liability | No | True when owners are not personally liable for debts. |
| vat_registered_at | No | Date of VAT registration. |
| employees_reported | No | Whether the registry holds an employee figure at all (distinguishes 0 from unknown). |
| published_deadlines | No | Filing dates the upstream register publishes for this entity itself, carried verbatim. Empty for a register that publishes none — most of them. This is the input `Registry.deadlines(report, today)` needs to prefer the register's own figure over any calculation (DECISIONS.md D-018), and it is what keeps that method the pure function of (report, today) its contract promises. |
| in_business_register | No | Listed in the commercial register (Norway: Foretaksregisteret). |
| share_capital_currency | No | ISO-4217 code for `share_capital`. |
| has_annual_accounts_duty | No | True when this legal form must file annual accounts with the state. |
| last_annual_accounts_year | No | Most recent financial year for which accounts were filed. |
| business_register_registered_at | No | Date entered in the commercial/business register, where that is separate. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (readOnly, openWorld, idempotent, non-destructive), the description discloses important behaviors: identifier normalization and zero-padding, country-specific register behavior, the requirement to read returned notes for caveats like bankruptcy or dissolution, and retry/error semantics including that upstream errors have already been retried once.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose and is information-dense, with country details and error handling clearly separated. It is somewhat long and partially duplicates the schema's parameter documentation, but the length is justified by the multi-country behavior and error guidance.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with two well-documented parameters, rich annotations, an output schema, and sibling tools, the description is complete: it covers when to use it, country-specific identifier formats, error handling, retries, and warnings about the returned data. Nothing essential is missing for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3 even if the description adds no parameter info. The description does reinforce the schema's details about organisasjonsnummer, CRN, zero-padding, and accepted country codes, but it mostly duplicates what the input schema already states rather than adding substantial new parameter-level meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Look up a company by its national identifier and get the full CompanyReport'. It clearly distinguishes lookup from search by stating that lookup is used once the identifier is already known, and it names the sibling search_company as the source of an id.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly states when to use the tool: 'Use it once you have the identifier — from the user, an invoice, a contract, or a search_company hit's id.' It also provides alternative routing on errors: use search_company for invalid_id/not_found and list_countries for unsupported_country.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_companySearch a national company register by nameARead-onlyIdempotentInspect
Search a national company register by name, when you have a name rather than an identifier.
country="NO" searches Brønnøysundregistrene / Enhetsregisteret (brreg) for Norwegian
companies — the norway company lookup tool for the norwegian business registry when the
organisasjonsnummer (orgnr, org.nr) is not yet known. country="GB" is the uk company
search: Companies House by company name, returning each hit's company number
(company registration number, CRN).
Use it when a user gives you a company name, then call lookup_company with the id
of the right hit for the full report — a search hit is deliberately thin (name, legal
form, status, city) and must not be acted on directly. limit is 1-100 (default 10).
Hits arrive in the register's own relevance order, so read each hit's confidence
rather than assuming the first row is the best one. Zero hits is not an error: hits
is [], total is 0, and hint says what to try next — Norwegian names are
registered upper-case and often carry an 'AS', 'ASA' or 'NUF' suffix, and UK names a
'LIMITED', 'LTD', 'PLC' or 'LLP' one, worth dropping before concluding a company does
not exist.
On error, this tool raises with the error text {"error": {"code", "message", "hint"}}. bad_request means limit was out of range or name was empty — fix and
retry. unsupported_country means call list_countries first.
upstream_error/upstream_timeout means the national register is unavailable; wait
roughly a minute and retry at most once more.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Company name to search for, free text — not an identifier. Use lookup_company once you have the id of the right hit. | |
| limit | No | Maximum hits to return. 1-100, default 10; a value outside that range is a bad_request, not a silent clamp. | |
| country | No | ISO-3166-1 alpha-2 country code. 'NO' = Norway (Brønnøysundregistrene / Enhetsregisteret), 'GB' = United Kingdom (Companies House). 'UK' is not a country code here and is rejected. Call list_countries for the current set rather than hard-coding one. | NO |
Output Schema
| Name | Required | Description |
|---|---|---|
| hint | No | What to do next, e.g. 'call lookup_company with the id of the right hit'. |
| hits | No | Best matches, best first: always sorted by `confidence` descending. Hits that score equally keep the order the upstream register returned them in. |
| query | Yes | The name that was searched for. |
| total | No | Total matches upstream, which may exceed len(hits). |
| cached | No | Served from cache. |
| country | Yes | ISO-3166-1 alpha-2, upper-case. |
| registry | Yes | Registry slug. |
| truncated | No | True when `total` exceeds the returned hits. |
| fetched_at | No | UTC timestamp of the fetch. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, openWorldHint, idempotentHint, and destructiveHint, and the description adds substantial behavioral detail beyond them: search hits are deliberately thin, order is the register's own relevance order, zero hits returns an empty array and hint, and errors have a structured shape with retry guidance. It also notes that 'UK' is rejected and country codes should not be hard-coded, reinforcing the openWorldHint.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but every sentence carries operational value. It is front-loaded with the core purpose and usage, then moves into edge cases and error handling in a logical order. No filler or tautological repetition; the length is justified by the tool's complexity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description is complete for a search tool of this complexity. It covers return-value expectations (thin hits, confidence, relevance order), zero-hit semantics, error codes and retry policy, supported countries, and how to proceed to `lookup_company`. The presence of an output schema makes it unnecessary to document every return field, and the description still adds useful context about interpretation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Even though schema coverage is 100%, the description adds meaning beyond the schema: it explains what each country code maps to, why `name` is free text rather than an identifier, the exact bounds and failure behavior for `limit`, and the presence of a `confidence` field on hits. This significantly improves the agent's ability to use the parameters correctly.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb, resource, and scope: "Search a national company register by name, when you have a name rather than an identifier." It explicitly contrasts with `lookup_company`, which is the sibling it must not be confused with, and explains the two supported country-specific registers.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit when-to-use guidance: use it when the user provides a company name, then call `lookup_company` with the `id` of the right hit. It also covers when NOT to treat zero hits as an error, how to handle invalid input, and when to call `list_countries` first, leaving no ambiguity about tool routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
validate_company_idValidate a company identifier (no network call)ARead-onlyIdempotentInspect
Check whether a national company identifier is well-formed — no network call.
country="NO" checksum-checks a Norwegian organisasjonsnummer (orgnr, org.nr) for
Brønnøysundregistrene / Enhetsregisteret (brreg); this is the cheap norway company
lookup pre-check for the norwegian business registry. country="GB" shape-checks and
normalises a UK company number (company registration number, CRN) for Companies House:
it zero-pads a short number ('445790' → '00445790') and upper-cases a prefix
('oc303675' → 'OC303675'). A CRN has no check digit, so a GB valid: true means the
shape is right and nothing more.
Use it on user input or a spreadsheet column before spending a real lookup_company
call, since it is instant and free.
Returns a ValidationResult and never raises for a malformed identifier: valid: false
comes with reason (what failed) and hint (what to do next) rather than a tool
error — this tool answers a question, it does not fail on bad input
(DECISIONS.md D-010). A valid identifier does not mean the entity exists; follow it
with lookup_company if you need facts.
The only real error here is unsupported_country (no module for that country yet —
call list_countries), raised with the error text {"error": {"code", "message", "hint"}}.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | The company's national identifier. Norway (country='NO'): a nine-digit organisasjonsnummer (orgnr), e.g. '923609016'; spaces, dots and a 'NO...MVA' VAT suffix are accepted and normalised. United Kingdom (country='GB'): a Companies House company number (CRN), eight characters, e.g. '00445790' or 'OC303675'; a short number is zero-padded for you. | |
| country | No | ISO-3166-1 alpha-2 country code. 'NO' = Norway (Brønnøysundregistrene / Enhetsregisteret), 'GB' = United Kingdom (Companies House). 'UK' is not a country code here and is rejected. Call list_countries for the current set rather than hard-coding one. | NO |
Output Schema
| Name | Required | Description |
|---|---|---|
| hint | No | What to do next when `valid` is false — the same hint the invalid_id error carries. None when valid: the next call is simply lookup. |
| input | Yes | The identifier exactly as the caller supplied it. |
| valid | Yes | True when the identifier passes this country's format and checksum. |
| reason | No | One English sentence saying why it is valid, or what failed. |
| country | Yes | ISO-3166-1 alpha-2, upper-case. |
| registry | Yes | Registry slug, e.g. 'brreg'. |
| formatted | No | The identifier as a local would write it, e.g. '923 609 016'. None when invalid. |
| id_scheme | No | Name of the identifier scheme, e.g. 'organisasjonsnummer'. |
| normalized | No | Canonical form to pass to lookup, e.g. '923609016'. None when invalid. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (readOnly, idempotent, non-destructive), the description discloses meaningful behavior: no network call, checksum validation for Norway vs shape-only validation for the UK, normalisation rules, the guarantee that it never raises for malformed identifiers, and the unsupported_country error contract. No contradiction with annotations exists.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is structured logically: purpose first, then per-country behavior, then usage recommendation, then return/error behavior. It is a bit verbose in places — such as repeating the 'cheap' idea — but every major sentence contributes useful operational detail.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a validation-only tool with an output schema, the description covers all necessary operational aspects: what it validates, how each supported country behaves, the error contract, and when to use it versus lookup_company. Nothing an agent needs to invoke it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already describes both parameters well (100% coverage), so the baseline is 3. The description adds extra semantic value by explaining the validation algorithms, the zero-padding and upper-casing behavior, and the meaning of a GB valid:true. This goes beyond what the schema provides, though not a huge margin.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Check whether a national company identifier is well-formed — no network call.' It clearly separates this from lookup_company by framing it as a cheap pre-check, and from search_company by focusing on validation rather than search. The scope is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly tells the agent when to use it: 'Use it on user input or a spreadsheet column before spending a real lookup_company call, since it is instant and free.' It also routes unsupported countries to list_countries. This gives clear contextual guidance for choosing the tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
5 tool updates
v0.1.0- First observed
company_deadlines - First observed
list_countries - First observed
lookup_company - First observed
search_company - First observed
validate_company_id
TDQS
Scored across 5 tools
Each tool has a distinct role: search by name, lookup by identifier, validate identifiers locally, list supported countries, and retrieve filing deadlines. There is no ambiguity between them, and the descriptions reinforce when to use which.
Most tools follow a clear verb_noun pattern: lookup_company, search_company, validate_company_id, list_countries. company_deadlines breaks the pattern slightly by leading with the noun rather than a verb, but the set remains highly readable and predictable.
Five tools is well-scoped for a company registry MCP server. Each tool covers a necessary part of the workflow without redundancy or bloat.
The tool surface covers the full user journey: discover supported countries, validate an identifier, search by name, fetch the full company report, and retrieve statutory deadlines. There are no obvious dead ends or missing operations for the stated registry-lookup domain.
Maintenance
Related MCP Connectors
CompanyLens is a remote MCP server giving AI agents instant access to official company registry data across 19 jurisdictions in Europe, the Americas, and Asia-Pacific. Eighteen read-only tools let you search companies and people, look up officers and beneficial owners, map corporate networks through shared directors, screen names against the UK disqualified directors register, find every company at a registered address, and pull filing history — all from a single connector. Visit our website: https://companylens.io
Nordic company intelligence: look up companies, AI summaries, scores and signals via MCP.
Companies House MCP — UK statutory company registry (BYO key)
OpenCorporates MCP — Global company registry data (free, no auth, rate limited)
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceProvides access to Norway's official business registry for searching companies, looking up organizational details, and identifying company roles and sub-units. It utilizes data from Brønnøysundregistrene to enable detailed queries by industry, municipality, or organization number.4 npmMIT
- AlicenseNot gradedqualityAmaintenanceMCP server for Nordic company registries. Verify companies, check board members, signing authority, and financial data across Norway, Denmark, Finland, and Sweden using official public APIs. 23 tools covering search, details, roles, and batch lookups.198Apache 2.0

companieswiseofficial
AlicenseAqualityDmaintenanceProvides verified UK company lookup and number validation for AI agents using official Companies House data. Enables lookup of registered details by number, validation of company number format, and search by company name.341 npmApache 2.0- AlicenseAqualityDmaintenanceEnables AI agents to search and retrieve Norwegian company data from the Brønnøysund Register Centre's open API, including company details, roles, and subunits.59 npmMIT