registry-mcp

O MCP de registro de empresas: dados empresariais para agentes de IA a partir de registros nacionais de empresas. Noruega (brreg / Enhetsregisteret: consulta de orgnr, busca por nome, registro de IVA, prazos de declaração) e Reino Unido (Companies House: consulta por número de empresa, busca, prazos de contas e declaração de confirmação).

Documentação

registry-mcp — o MCP do registro de empresas

PyPI PyPI alias npm CI License: MIT Listed on mcpservers.org

Dados de empresas para agentes de IA, em qualquer país. Um único servidor MCP e API REST, três registros nacionais hoje: o Companies House do Reino Unido, consultado por company number; o Enhetsregisteret / Brønnøysundregistrene (brreg) da Noruega, consultado por organisasjonsnummer (orgnr); e o Bolagsverket da Suécia, consultado por organisationsnummer — um único formato JSON, independentemente de qual você consulte.

claude mcp add registry-mcp --transport http https://api.foretak.dev/mcp

Sem etapa de instalação, via stdio:

claude mcp add registry-mcp -- uvx registry-mcp

O que faz valer um espaço na lista de ferramentas:

  • Prazos que citam a regra, não apenas uma data. company_deadlines informa a próxima data de entrega e nomeia o motivo em applies_because — uma obrigação legal de uma forma jurídica norueguesa, ou "o Companies House publica esta data para a própria empresa" quando o registro a informa em vez de nós a calcularmos. Cite o motivo, não apenas o número.
  • Nunca mais de 24 horas desatualizado, e isso é dito. Cada resposta traz cached e fetched_at. A própria base de conhecimento do OpenCorporates orienta os usuários a "aguardar 30 dias" para uma correção chegar ao site — uma diferença de atualização de 30×, declarada pelo próprio concorrente sobre si mesmo.
  • Sete ferramentas, não cinquenta — cinco ferramentas de registro mais dois aliases de conector do ChatGPT. A precisão da seleção de ferramentas degrada além de 30 a 50 ferramentas carregadas no contexto de um agente, e alguns clientes limitam em torno de 40. Sete ferramentas é aproximadamente 17% desse orçamento, em comparação com concorrentes nesse espaço que enviam de 23 a 78 ferramentas para a mesma tarefa.

Segurança. Somente leitura, sempre — nada aqui grava em um registro ou em qualquer outro lugar. Nenhuma credencial é exigida de quem chama; a credencial upstream desta implantação (COMPANIES_HOUSE_API_KEY) é lida do ambiente e nunca é registrada em log nem retornada. Três upstreams nomeados, e nada mais é chamado: data.brreg.no, api.company-information.service.gov.uk e gw.api.bolagsverket.se. Nenhum dado pessoal além do que cada registro nacional já publica sobre a própria entidade — e, como o número de empresa de um empresário individual sueco é o personnummer dele, o log de uso não armazena nenhum identificador para um país cujos identificadores podem ser de uma pessoa física (legal/privacy.md). Este serviço não realiza triagem de sanções, PEP ou mídia adversa, e não verifica dados de conta bancária. Detalhes: SECURITY.md.

Instalação em um clique, para um servidor remoto streamable-HTTP:

Install in VS Code Install in VS Code Insiders Install in Cursor

Outros clientes (Claude Desktop, Cursor, VS Code, Cline, configurações JSON simples): veja docs/clients.md.

Adicionar ao ChatGPT

O ChatGPT acessa um servidor MCP por meio de um conector personalizado, e o modo de pesquisa aprofundada chama exatamente duas ferramentas — search e fetch — que este servidor oferece junto com as cinco ferramentas de registro. No ChatGPT, abra Configurações → Conectores, adicione um conector personalizado e informe:

https://api.foretak.dev/mcp

Sem autenticação, sem chave, sem conta. Se o seu plano do ChatGPT não mostrar conectores personalizados em Configurações → Conectores, ative primeiro Configurações → Segurança e login → Modo de desenvolvedor e depois adicione a URL de https://chatgpt.com/plugins.

search aceita uma consulta em texto livre — um nome de empresa, um identificador nacional ou um nome mais um país ("Tesco Reino Unido") — e retorna linhas citáveis; fetch recebe o id de uma linha ("NO:923609016") e retorna o registro da empresa e seus prazos legais de entrega, com o JSON completo de ambos em metadata.

Adicionar ao Claude Desktop

O Claude Desktop aceita a mesma URL como conector personalizado: Configurações → Conectores → Adicionar conector personalizado e depois https://api.foretak.dev/mcp. Sem chave. Para uma instalação local via stdio, veja Configuração.

Status: 0.3.0, ativo — GET /health retorna {"version":"0.3.0","countries":["GB","NO","SE"]}. As cinco ferramentas de registro e seus formatos de resposta estão congelados; dois aliases de conector (search, fetch) os encapsulam para o ChatGPT e não adicionam nenhum formato novo. A API hospedada em api.foretak.dev está ativa e listada no registro oficial do MCP como io.github.foretak/registry-mcp. Países: Reino Unido (Companies House), Noruega (brreg), Suécia (Bolagsverket) — veja abaixo o formato de identificador de cada país e exemplos de chamadas.

Adicionar ao Claude Code

Os mesmos dois comandos acima — Streamable HTTP ou stdio local. Para adicionar como arquivo .mcp.json no nível do projeto em vez da CLI, veja Configuração.

O que retorna

$ 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"
}

Resumido — o CompanyReport completo também traz previous_names, industry_codes, registers, purpose, parent_id, confidence, cached, fetched_at e notes. Cada campo está documentado em llms-full.txt §5.

euid é o identificador em toda a UE que alguns registros de estados-membros publicam (a Finlândia publica; nenhum dos nossos publica ainda) — nunca o LEI, nunca construído a partir de partes. advertising_protected é true/false/null: se o registro marca esta entidade como protegida contra uso de marketing direto, null significa que o registro não publica tal sinalização (Noruega e Reino Unido, hoje); onde for true (o reklamspärr da Suécia, por exemplo), uma frase em notes declara isso e essa marcação deve acompanhar qualquer dado de contato que você repassar.

O Reino Unido, mesmo formato, mesmo resumo:

$ 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": {"charges": false, "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 traz as datas que o próprio registro publica, com o campo upstream de onde vieram. É [] para Noruega e Suécia, que calculam tudo por conta própria.

A Suécia, adicionada na versão 0.3.0, é onde "um formato" começa a sustentar a afirmação:

$ 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"
}

O Bolagsverket não nomeia licença para esses dados, então nós também não: a string diz qual é a permissão e afirma claramente que não há nome de licença para citar, porque um nome familiar nesse campo seria uma fabricação.

A Suécia não publica nenhum campo de status. status é derivado de três sinais independentes — uma data de baixa, um processo em andamento de liquidação ou reestruturação e o sinalizador "economicamente ativa" do Statistics Sweden — e is_active portanto significa no registro e não em processo de encerramento, o que não é o mesmo que em operação. Quando qualquer um desses não estiver disponível, a resposta é unknown, nunca active.

Duas datas são calculadas, e cada uma traz a disposição de onde vem:

$ 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"}

Seis meses para a assembleia geral anual (aktiebolagslagen 7 kap. 10 §) e sete para a entrega antes que uma multa por atraso incida (årsredovisningslagen 8 kap. 6 §). Nenhuma das datas é adiada por cair em fim de semana, porque nenhuma fonte sueca diz que ela se move. Ambas assumem um exercício fiscal encerrado em 31 de dezembro, que o conjunto de dados gratuito não publica — e uma frase em notes diz exatamente isso, incluindo como deslocar ambas as datas se o fim do exercício for diferente. search_company responde not_implemented para a Suécia: a API gratuita tem quatro operações e nenhuma aceita um nome.

Observe os null. O Companies House não publica status de IVA, número de funcionários nem capital social de nenhuma empresa, então esses campos são null em vez de adivinhados — null significa "este registro não informa", nunca "não". Essa honestidade é o ponto de um formato único entre países.

E os prazos, que é onde o módulo do Reino Unido mostra seu valor:

$ 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."}
  ]
}

Onde o Companies House publica uma data, ela é citada; onde não publica, a data é calculada a partir de uma lei citada e applies_because diz isso. Os prazos do Reino Unido nunca são adiados por cair em fim de semana ou feriado bancário, e days_until fica negativo para uma entrega que o registro ainda mostra como atrasada.

Quer executar você mesmo? O serviço hospedado em api.foretak.dev tem todas as credenciais configuradas. Uma cópia auto-hospedada precisa de uma chave gratuita do Companies House para GB e um par de cliente OAuth 2 do Bolagsverket (BOLAGSVERKET_CLIENT_ID, BOLAGSVERKET_CLIENT_SECRET) para SE; sem elas, esses dois países retornam upstream_error nomeando a variável, e todos os outros países continuam respondendo. A Noruega não precisa de nada.

Ferramentas

FerramentaO que faz
lookup_company(id, country="NO")CompanyReport completo para uma empresa por identificador nacional
search_company(name, country="NO", limit=10)SearchResult — candidatos com identificadores, na ordem de relevância do registro, cada um pontuado
company_deadlines(id, country="NO", today=None)DeadlineReport — a próxima ocorrência de cada obrigação legal de entrega
validate_company_id(id, country="NO")ValidationResult — valida e normaliza um identificador sem chamada de rede
list_countries()Quais registros nacionais são suportados agora

Aliases de conector — para o ChatGPT, que acessa um servidor MCP por exatamente search e fetch (Adicionar ao ChatGPT); não adicionam nenhum formato de resposta novo e não têm equivalente REST.

FerramentaO que faz
search(query)Alias de conector do ChatGPT para search_company — uma consulta em texto livre, {"results": [{"id", "title", "url"}]}
fetch(id)Alias de conector do ChatGPT para lookup_company + company_deadlines — um "{COUNTRY}:{identifier}", um documento Markdown com ambos os relatórios em metadata

Além do recurso registry://rules/{country} (regras de identificador, formas jurídicas, regras de prazo — leia uma vez em vez de validar em loop) e do prompt explain_company.

parent_id e in_group em um CompanyReport norueguês descrevem a relação pai/subunidade do próprio Enhetsregisteret para aquela entidade — nada mais. Não há ferramenta de navegação em grupo: subir em um grupo corporativo significa chamar lookup_company novamente em parent_id, repetidamente, e essa navegação responde "o que o registro lista como pai desta entidade?", não "quem é o proprietário beneficiário ou controla esta empresa?" — uma pergunta diferente que este serviço não responde. Veja llms-full.txt §5.

Por que um agente verifica uma empresa

Três regras tornam isso um dever, não um luxo. O Rundskriv 15/2019 da Finanstilsynet, § 4.4.1, aceita um oppslag contra o Enhetsregisteret com no máximo três meses, um mês quando a verificação se baseia em dados da empresa fornecidos pelo cliente, e pede notoritet sobre a consulta: o que foi consultado e quando. A partir de 1º de janeiro de 2027, empresas norueguesas obrigadas à contabilidade devem faturar umas às outras por e-invoice, e o destinatário é resolvido no ELMA como 0192: mais organisasjonsnummer, o identificador que estas ferramentas já aceitam. A partir de 10 de julho de 2027, o AMLR, Artigo 23(4), exige "prova válida de registro ou um extrato recente do registro" para toda nova relação comercial com uma pessoa jurídica.

É para isso que servem source_url, fetched_at, cached, license e applies_because: qual registro foi consultado, quando foi lido, se veio do cache de 24 h, os termos sob os quais viaja e se um prazo foi citado do registro ou calculado a partir de uma regra nomeada.

Os limites, declarados em vez de implícitos: sem triagem de sanções ou PEP; sem verificação de conta bancária, e a fraude de fatura mais comum é o redirecionamento de pagamento, em que o fornecedor é real e apenas o número da conta está errado; e sem proprietários beneficiários, que o brreg libera somente mediante solicitação, para categorias de solicitantes que não incluem um fornecedor de produto. Versão completa em llms-full.txt §9.

Configuração

Claude Code.mcp.json na raiz do projeto
{
  "mcpServers": {
    "registry-mcp": {
      "command": "uvx",
      "args": ["registry-mcp"],
      "env": {
        "REGISTRY_MCP_CONTACT_EMAIL": "you@example.com",
        "COMPANIES_HOUSE_API_KEY": "your-companies-house-key"
      }
    }
  }
}

Remova COMPANIES_HOUSE_API_KEY se você precisar apenas da Noruega; todos os outros países funcionam sem ele.

Cursor~/.cursor/mcp.json (ou .cursor/mcp.json no projeto)
{
  "mcpServers": {
    "registry-mcp": {
      "command": "uvx",
      "args": ["registry-mcp"],
      "env": { "REGISTRY_MCP_CONTACT_EMAIL": "you@example.com" }
    }
  }
}
Claude Desktopclaude_desktop_config.json

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" }
    }
  }
}
npm em vez de uvx — mesmo servidor, inicializador Node
{
  "mcpServers": {
    "registry-mcp": { "command": "npx", "args": ["-y", "registry-mcp"] }
  }
}

npx registry-mcp depende de uvx registry-mcp (com fallback para pipx run registry-mcp), portanto Python 3.12+ e um dos uv ou pipx devem estar presentes.

Hospedado, sem instalação local — Streamable HTTP
{
  "mcpServers": {
    "registry-mcp": { "type": "http", "url": "https://api.foretak.dev/mcp" }
  }
}

Variáveis de ambiente — todas opcionais:

VariávelSignificado
REGISTRY_MCP_CONTACT_EMAILEndereço de contato enviado no User-Agent ao registro nacional, conforme solicitado pelo Brønnøysundregistrene aos clientes da API. Não definido significa cliente anônimo, que pode ser limitado ou bloqueado upstream.
REGISTRY_MCP_CACHE_PATHCaminho para o cache de respostas SQLite local (TTL de 24 h). Padrão: ./data/cache.sqlite3.
COMPANIES_HOUSE_API_KEYNecessária para o Reino Unido (GB). Uma chave é gratuita e instantânea. Não definida significa que consultas GB retornam upstream_error com uma dica mencionando esta variável — todos os outros países continuam funcionando.
BOLAGSVERKET_CLIENT_ID, BOLAGSVERKET_CLIENT_SECRETNecessárias para a Suécia (SE). Um par de cliente OAuth 2 emitido pelo Bolagsverket mediante solicitação; os dados em si são gratuitos sob o regulamento da UE de conjuntos de dados de alto valor. Não definidas significam que consultas SE retornam upstream_error mencionando ambas as variáveis — todos os outros países continuam funcionando.

REST

Cada ferramenta tem um equivalente REST que retorna o mesmo documento JSON.

# 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-0680

Documentação legível por máquina: /llms.txt, /llms-full.txt, /openapi.json.

Adicionando seu país

A Noruega é uma pasta. O Reino Unido também: registries/gb/ foi adicionado como quatro arquivos e uma linha de importação, e GB apareceu em list_countries, em todas as ferramentas, em /openapi.json e em registry://rules/GB por conta própria. A Suécia também — registries/se/ foi lançada na versão 0.3.0 com nenhuma alteração em core/, incluindo as partes da Suécia que menos se encaixam na abstração: um registro que não publica campo de status, uma operação que o upstream não oferece (search_company responde not_implemented) e um identificador que pode ser o ID nacional de uma pessoa física.

Copie src/registry_mcp/registries/xx/ para registries/<cc>/, implemente quatro métodos, adicione uma linha de importação — nada em core/ muda, e ambas as superfícies mais os manifestos são ativados automaticamente para o novo país.

CONTRIBUTING.md — "Adicione seu país", e o modelo de issue new country para reivindicar um primeiro.

Desenvolvimento

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 .

Estrutura:

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)

Documentos

Fonte de dados e licença

Os dados noruegueses vêm do Enhetsregisteret (Brønnøysundregistrene), publicados sob NLOD 2.0 — atribuição obrigatória. Os dados do Reino Unido vêm do registro público da Companies House, direitos autorais da Coroa, livres para reutilização sem condição de atribuição; nós os citamos mesmo assim. Os dados suecos vêm do Bolagsverket, com o Statistics Sweden (SCB) como segundo produtor no mesmo payload, livres para reutilização como värdefull datamängd sob o regime da UE de conjuntos de dados de alto valor — as próprias palavras do Bolagsverket são "Det krävs inget avtal för att du ska få använda vårt API för värdefulla datamängder" e "Värdefulla datamängder är avgiftsfritt" — e o Bolagsverket não nomeia nenhuma licença, então nós também não: a string license declara a permissão e afirma claramente que não há nome de licença a citar. Cada resposta carrega source, source_url e license para que a atribuição viaje com os dados. O código deste projeto é licenciado sob MIT. Não afiliado ou endossado pelo Brønnøysundregistrene, Companies House ou Bolagsverket.