Skip to main content
Glama
kaylum54

companies-house-screening-mcp

by kaylum54

companies-house-screening-mcp

MCP 호스트에서 영국 기업등록소 공개 레지스터를 대상으로 영국 기업을 스크리닝합니다. 공급업체 목록 일괄 스크리닝, 한 번의 호출로 회사 스냅샷 확인, 위험 점수가 아닌 사실 기반 신호를 제공합니다.

상태: 6단계 중 6단계. 실행 중인 서버에서 생성되고 CI에서 검증되는 문서와 함께 11개의 도구, 도구 선택 평가, 라이브 API에서 기록된 픽스처가 포함되어 있습니다. 릴리스 파이프라인은 구축되었지만 아직 게시되지 않았습니다.

다른 프로젝트가 있으며, 알아두셔야 합니다

companies-house-mcp는 @aicayzer가 2025년 7월부터 운영 중이며, v4.0.0에 이르렀고, 활발히 유지보수되고 있습니다. 동일한 API를 다룹니다. 이 프로젝트는 선구자가 아니며 그렇게 주장하지도 않습니다.

두 프로젝트는 형태가 다르므로, 어떤 것을 사용할지는 작업 내용에 따라 달라집니다.

폭넓은 기능이 필요하다면 그들의 것을 사용하세요. 더 많은 API를 노출합니다 — 등록, 면제, 영국 법인, 임원 자격 상실 — 그리고 중요한 것은 제출된 서류 자체를 다운로드할 수 있다는 점입니다. 이 프로젝트는 의도적으로 그렇게 하지 않습니다: Companies House 문서 API는 여기서 범위를 벗어납니다.

브라우징이 아니라 스크리닝이 목적이라면 이 프로젝트를 사용하세요. 중요한 차이점:

일괄 스크리닝

screen_companies는 최대 50개의 이름 또는 번호를 받아 각각 한 행씩 반환합니다. 다른 곳에서는 이 기능을 제공하지 않습니다.

회사 번호를 추측하지 않음

조회 도구는 요청 전에 회사 이름을 단호히 거부합니다. 이름이 주어지면 모델은 그럴듯한 번호를 생성하고, 그럴듯한 잘못된 번호는 다른 실제 회사를 반환하며, 이후 어떤 단계에서도 이를 오류로 표시하지 않습니다. ADR 5.

점수가 아닌 신호

각 관찰 뒤에 날짜 또는 이름과 함께 레지스터에서 읽은 사실, 그리고 의도적으로 등급을 매기지 않습니다. ADR 7에 그 근거가 있습니다.

조용히 누락되는 것 없음

부분 결과는 명시적으로 표시됩니다. 스크리닝 테이블이 짧게 반환되면 항상 그 이유를 설명합니다. ADR 8.

낡지 않는 문서

도구 참조는 실행 중인 서버에서 생성되며 모든 예제가 실행됩니다. 어느 하나라도 어긋나면 CI가 실패합니다. ADR 9.

도구 선택 평가

실제 모델에게 어떤 도구를 사용할지 묻고, 불안정하면 실패합니다. ADR 10.

11개의 결정 사항이 docs/adr에 기록되어 있으며, 그중에는 당연한 방향으로 가지 않은 것들도 있습니다.

Related MCP server: Companies House MCP Server

설치

npx -y companies-house-screening-mcp

호스트 구성:

{
  "mcpServers": {
    "companies-house": {
      "command": "npx",
      "args": ["-y", "companies-house-screening-mcp"],
      "env": { "COMPANIES_HOUSE_API_KEY": "your_key" }
    }
  }
}

또는 Docker 사용 시 — JSON-RPC 프레이밍을 손상시키는 TTY 때문에 -i를 사용하고 -t는 사용하지 않습니다:

docker run --rm -i -e COMPANIES_HOUSE_API_KEY=your_key ghcr.io/OWNER/companies-house-screening-mcp

무료 API 키는 developer.company-information.service.gov.uk에서 받으세요: 등록하고, Live 환경에 대해 애플리케이션을 만들고, REST 유형의 키를 생성하세요(스트림 키는 동일한 방식으로 인증하지만 다른 서비스용입니다).

왜 또 다른 API 래퍼인가

이것을 구축하는 당연한 방법은 엔드포인트당 하나의 MCP 도구를 만드는 것입니다. 22개의 얇은 패스스루, 주말 작업, 그리고 대부분의 게시된 MCP 서버가 그렇게 합니다. 또한 세 가지 특정한 방식으로 나쁩니다:

  • 모든 도구 스키마는 작업에 필요하지 않더라도 매 턴마다 모델의 컨텍스트에 있습니다.

  • 오케스트레이션을 모델에 떠넘깁니다. "이 공급업체를 온보딩해도 안전한가"는 검색, 프로필, 임원, 담보, 파산으로 이어집니다 — 다섯 번의 왕복과 스레드를 잃을 다섯 번의 기회.

  • Companies House 페이로드는 모델이 읽지 않는 구조를 담고 있습니다 — links, etag, kind, 항목별 ETag, 제출 트랜잭션 배열, 9개 키 주소 객체. 이를 정리하면 엔드포인트에 따라 36%에서 72%까지 절약되며, 가정이 아닌 실제 기록된 응답을 기준으로 측정됩니다(npm run measure).

따라서 이 서버는 질문 중심으로 구성된 11개의 도구를 노출하며, 그 중 두 개(company_snapshot 및 screen_companies)는 서버 측에서 팬아웃을 수행하고 하나의 파생 객체를 반환합니다. 조회 도구는 회사 번호를 받고 회사 이름을 거부합니다. 이름이 주어지면 모델이 번호를 추측할 것이고, 그럴듯한 잘못된 회사 번호는 이후 어떤 단계에서도 오류로 표시되지 않는 실제 회사를 반환하기 때문입니다.

도구

도구

반환 내용

find_company

이름 또는 번호에 대한 순위가 매겨진 후보와 disambiguation_needed 플래그.

find_officer

사람 이름에 대한 후보 임원 ID와 임명 횟수.

get_company

프로필, 연체 제출, 담보, 파산, 최근 설립에 대한 파생 플래그.

get_officers

현재 및 사임한 임원, 각각 다른 회사를 조회하는 데 필요한 ID 포함.

get_filing_history

제출된 내용과 시기, 카테고리로 필터링 가능.

get_charges

담보 부채, API가 보고하지 않는 파생 outstanding_count 포함.

get_psc

회사를 실제로 통제하는 사람과 그 통제 방식.

get_insolvency

파산 사건과 선임된 실무자.

get_officer_appointments

임원이 재직 중인 모든 회사 — 이해 충돌 도구.

company_snapshot

프로필, 임원, 담보, 파산을 한 번의 호출로, 신호 포함.

screen_companies

최대 50개 회사 입력, 각각 한 행씩 출력, 조용히 누락되는 것 없음.

전체 참조: docs/tools. 작업 예제: docs/recipes — 공급업체 스크리닝, 임원 충돌 확인, 송장 검증, 채무자 위험, 경쟁사 제출 모니터링.

신호는 사실이지 등급이 아닙니다. 이 서버는 회사를 점수화하지 않으며 거래해도 안전한지 여부를 알려주지 않습니다 — 레지스터에서 찾은 내용을 각 관찰 뒤의 날짜 또는 이름과 함께 보고하며, 판단은 맥락을 가진 사람에게 맡깁니다. 빈 신호 목록은 목록에 있는 항목이 발견되지 않았다는 뜻이지 회사가 건전하다는 뜻이 아닙니다. ADR 7에 전체 근거가 있습니다.

모든 도구는 readOnlyHint: true로 주석 처리되고, 출력 스키마를 게시하며, verbose를 받아 정리된 객체와 함께 원본 페이로드를 반환합니다.

도구 내부

구성 요소

역할

loadConfig

시작 시 모든 환경 변수를 검증하고 모든 문제를 한 번에 보고하며, 내부 필드가 아닌 변수 이름을 지정합니다.

CompaniesHouseClient

기본 인증 요청, 요청별 타임아웃, 429 및 5xx에 대한 지터 재시도, 조건부 재검증, 실패 시 오래된 데이터 폴백.

RateLimiter

문서화된 600회/5분에 맞춘 슬라이딩 윈도우, 안전 여유 및 직렬화된 획득.

ResponseCache

메모리 우선 디스크, 리소스 종류별 TTL, 원자적 쓰기, 손상된 항목은 미스로 처리.

CompaniesHouseError

모든 실패는 안정적인 코드, 평문 문장, 다음 단계를 포함합니다.

프로젝션

업스트림을 필드별로 방어적으로 읽고, 출력은 게시된 스키마에 대해 엄격하게 검증됩니다.

284개의 테스트, 네트워크 없음, 실행에 API 키 불필요.

구성

필요한 변수는 하나뿐입니다.

변수

기본값

설명

COMPANIES_HOUSE_API_KEY

—

필수입니다. 개발자 포털에서 REST API 키를 생성하세요. 스트리밍 키가 아닙니다.

CH_API_BASE_URL

https://api.company-information.service.gov.uk

프록시 사용 시 재정의하기 위한 값입니다.

CH_RATE_LIMIT

600

윈도우(window)당 요청 수입니다. 키를 다른 프로세스와 공유한다면 값을 낮추세요.

CH_RATE_WINDOW_MS

300000

5분입니다.

CH_RATE_SAFETY_MARGIN

0.95

이 프로세스가 사용할 예산의 비율입니다.

CH_CACHE_ENABLED

true

CH_CACHE_DIR

플랫폼 캐시 디렉터리

XDG_CACHE_HOME과 LOCALAPPDATA를 존중합니다.

CH_TIMEOUT_MS

10000

요청당 제한 시간입니다.

CH_MAX_RETRIES

3

첫 시도 이후의 재시도 횟수입니다.

CH_LOG_LEVEL

info

error, warn, info 또는 debug입니다. 로그는 stderr로 출력됩니다.

CH_ENV_FILE

—

서버가 읽을 .env의 절대 경로입니다. 의도적으로 기본값을 설정하지 않습니다.

개발

npm install
npm test
npm run typecheck
npm run build
npm run docs:generate

문서는 생성되며 게이트(gate)로 통제됩니다. docs/tools는 실행 중인 서버를 실제 MCP 클라이언트로 연결해 렌더링되고, docs/recipes의 모든 호출은 페이지가 빌드될 때 실행됩니다. 커밋된 내용이 다르면 npm run docs:check는 실패합니다. CI는 테스트 전에 이 작업을 실행하고, 테스트 스위트도 동일한 비교를 수행하므로 변경 사항이 아직 눈앞에 있는 동안 실패가 발생합니다. 도구 설명을 바꾸었다면 재생성해야 합니다. 그렇지 않으면 빌드가 실패로 표시됩니다.

테스트 스위트는 실제 Companies House API에서 기록한 픽스처를 대상으로 오프라인에서 실행되므로, 아무것도 설정하지 않은 새로운 클론도 동작합니다. npm run record-fixtures는 픽스처를 다시 기록합니다 — 어떤 회사의 데이터이며 왜 그 픽스처를 선택했는지는 tests/fixtures/README.md를 참고하세요.

키를 확보했다면 .env.example을 .env로 복사하고 내용을 채우세요:

npm run test:live

모든 개발 명령은 해당 파일을 읽습니다. 셸에 이미 설정된 값이 파일보다 우선합니다. 배포된 서버는 CH_ENV_FILE이 특정 파일을 명시하지 않는 한 .env를 읽지 않습니다 — 호스트는 자신의 작업 디렉터리에서 서버를 실행하므로, 그 자리에 우연하게 존재하는 .env를 읽는 것은 잘못된 자격 증명을 불러오는 일이 될 수 있습니다.

그 테스트는 CI에서 매일 밤 실행됩니다. 이 테스트의 목적은 통과하는 것이 아니라, Companies House가 필드를 변경한 주에 크게 실패해서 사용자가 차이를 발견하기 전에 픽스처가 갱신되게 하는 것입니다.

도구 선택 평가

이 저장소의 모든 테스트는 도구가 동작하는가를 묻습니다. 하지만 하나도 묻지 못하는 것이 있습니다. — 사용자가 실제 질문을 할 때 모델이 올바른 도구를 선택하는가입니다. 도구가 올바르고 빠르고 완전히 테스트되어도, 설명이 모호하거나 다른 도구와 겹친다면 절대 선택되지 않을 수 있습니다. 이것이 공개된 MCP 서버에서 가장 흔하게 실제로 발생하는 결함입니다.

npm run eval -- --repeat 3

OpenRouter 또는 Anthropic API를 통해 실행됩니다 — OPENROUTER_API_KEY 또는 ANTHROPIC_API_KEY를 설정하세요. 기본값은 OpenRouter의 z-ai/glm-5.2로, 전체 실행 한 번당 약 4p 정도입니다. 비용 때문에 아무도 실행하지 않는 평가는 아무 효과가 없기 때문입니다. 비교를 위해 --model을 도구 지원이 있는 모델로 지정할 수 있습니다.

사람이 실제로 쓰는 방식으로 표현된 14개의 질문에 대해 어떤 도구가 첫 번째로 호출되었는지, 금지된 도구를 사용했는지, 인자가 올바른지, 그리고 가장 중요한 것은 질문에 없던 회사 번호를 모델이 지어냈는지로 채점합니다. 세 번 중 두 번 통과하는 사례는 flaky(불안정)로 보고되어 실패 처리됩니다. 선택이 확률적으로 오락가락한다는 것은 두 도구의 설명이 겹친다는 뜻이기 때문입니다.

세 가지 모델(GLM 5.2, Kimi K3, DeepSeek V4 Pro)에서 실행한 성능은 93–98%입니다. grounding 그룹 — 회사명만 주어지고 번호가 없을 때 번호를 기억하는 대신 검색하는 케이스 —에는 세 모델 모두 7/7로 통과했습니다. 실패는 한곳에 몰려 있었고, 그중 세 건은 어떤 모델의 문제가 아니라 제 도구 설명의 결함이었고, 한 건은 평가 자체의 결함이었습니다.

Companies House API 키는 필요 없습니다. 아무것도 실행되지 않습니다. 자세한 비교와 발견 사항은 evals/README.md에 있고, 판단 근거는 ADR 10에 있습니다.

설계 노트

11개의 결정이 docs/adr에 정리되어 있습니다:

  1. 아키텍처 결정 기록

  2. 슬라이딩 윈도우 속도 제한기와 안전 여유

  3. 예외가 아닌 데이터로서의 오류 처리

  4. 캐싱, TTL 및 오래된 항목 폴백

  5. 질문 형태의 도구, 그리고 이름이 거부되는 이유

  6. 결과 페이로드를 두 번 보내는 이유

  7. 점수가 아닌 신호

  8. 부분 결과 및 조용히 버리지 않기

  9. 생성된 문서, CI에서 게이트하기

  10. 도구 선택 평가

  11. 태그 기반 릴리스와 provenance 서명

범위

영구적으로 읽기 전용입니다. 모든 도구는 readOnlyHint: true로 표시되어 있으며 쓰기 경로는 없습니다. 문서를 회사 대신 제출하는 Companies filing API는 위험 특성이 다른 별도의 제품이므로 이 저장소의 범위 밖입니다. 스트리밍 API도 범위 밖입니다. 문서 API를 통해 제출물의 PDF 또는 iXBRL을 가져오는 것은 7단계에 있고, 읽기 전용으로 유지됩니다.

로드맵

단계

내용

상태

1

클라이언트, 인증, 속도 제한기, 캐시, 오류 매핑, 픽스처

완료

2

Zod 스키마와 형태가 갖춰진 프로젝션을 사용한 아홉 가지 기본 도구

완료

3

company_snapshot 및 screen_companies

완료

4

생성된 도구 문서와 CI 드리프트 검사, 다섯 가지 작업 예시

완료

5

도구 선택 평가 스위트, CI에서 라이브 스모크 테스트, 나머지 ADR

완료

6

provenance가 포함된 npm 및 Docker 릴리스

파이프라인 구축 완료, 미출시

라이선스

소스 코드는 MIT입니다.

이 서버가 반환하는 데이터는 Companies House가 Open Government Licence v3.0에 따라 공개한 것으로, MIT 라이선스의 적용 대상이 아닙니다. 이 데이터를 재배포하려면 OGL이 요구하는 출처 표시를 포함해야 합니다:

공공 부문 정보를 포함하며, Open Government Licence v3.0에 따라 라이선스가 부여되었습니다.

이 프로젝트는 Companies House와 제휴 관계가 아니며, 그 승인을 받지 않았습니다.publicwise.

Available Tools

11 tools
company_snapshotCompany snapshotA
Read-onlyIdempotent

Everything worth knowing about one company in a single call: profile, serving officers, outstanding charges and insolvency cases, plus a list of signals read off the register. Use this instead of calling get_company, get_officers, get_charges and get_insolvency separately — it costs one round trip of yours rather than four, and it fills in the sections that Companies House reports as 404 when a company simply has none. The signals are facts, not a rating: this server does not score companies, and an empty signal list means nothing on the list was found rather than that the company is sound. Check sections_included before drawing a conclusion from an absent signal.

ParametersJSON Schema
NameRequiredDescriptionDefault
verboseNoAlso return the untouched Companies House payload under `raw`, alongside the shaped result. Roughly two and a half times the size; use it only when a field you need is missing from the shaped result.
company_numberYesEight-character Companies House number, such as 00000006 or SC123456. Leading zeros may be omitted. This tool does not accept a company name — call find_company first if that is all you have.
include_chargesNoInclude charges. On by default.
include_officersNoInclude serving officers. On by default; turn it off to save one request per company.
include_insolvencyNoInclude insolvency cases. On by default.

Output Schema

ParametersJSON Schema
NameRequiredDescription
rawNoThe untouched Companies House payload. Present only when verbose was true.
metaYesProvenance and budget for this answer.
nameYes
statusNo
chargesNo
signalsYes
accountsYes
officersNo
age_yearsNo
sic_codesYes
insolvencyNo
dissolved_onNo
company_numberYes
incorporated_onNo
type_descriptionNo
sections_includedYesWhich sections were fetched. Signals can only reflect the sections listed here.
sections_unavailableYesSections that failed. The snapshot is still returned; treat those signals as unknown.
confirmation_statementYes
registered_office_addressNo

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, openWorldHint, idempotentHint, and non-destructive. The description adds valuable behavior: signals are facts not ratings, empty signal list means nothing found rather than soundness, incomplete 404 sections are filled, and the caller must check sections_included before concluding absence. This goes beyond the structured hints without contradicting them.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but well organized: it opens with the core value proposition, then gives the comparison to siblings, then the interpretation caveat, then the sections_included caution. Every sentence adds information and none are redundant with the schema or annotations.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the output schema exists and annotations carry the safety profile, the description covers what an agent needs to invoke correctly: when to use it, what it returns at a high level, how to interpret empty signals, and how to control size/cost via parameters. Nothing critical is missing for a read-only aggregation tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all five parameters well. The description adds context beyond the schema, particularly the round-trip cost implication of include_officers and the caution about verbose payload size. It does not re-describe every parameter, which is appropriate given full schema coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a strong verb phrase ('Everything worth knowing about one company in a single call') and enumerates the exact resources covered: profile, serving officers, outstanding charges, insolvency cases, and signal list. It also explicitly contrasts with sibling calls (get_company, get_officers, get_charges, get_insolvency), making differentiation unmistakable.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly states when to use this tool instead of the four separate sibling tools, noting the round-trip advantage and the fact that it fills in sections that Companies House reports as 404. It also warns against misinterpreting empty signal lists and directs users to check sections_included, and implicitly routes name-only lookups to find_company via the schema description.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

find_companyFind a companyA
Read-onlyIdempotent

Search Companies House for a UK company by name, trading name or number. Start here whenever you have a name rather than a number, because every other tool in this server needs the number. Returns a shortlist with status, type and incorporation date so that companies with similar names can be told apart. When disambiguation_needed is true, ask the user which one they meant instead of taking the first result — dozens of live companies share a name, and picking the wrong one produces a confident answer about the wrong business.

ParametersJSON Schema
NameRequiredDescriptionDefault
queryYesCompany name, partial name, or company number.
verboseNoAlso return the untouched Companies House payload under `raw`, alongside the shaped result. Roughly two and a half times the size; use it only when a field you need is missing from the shaped result.
start_indexNoZero-based offset into the full result set. Use pagination.has_more to decide.
items_per_pageNoHow many records to return. Defaults to the API default; the maximum is 100.

Output Schema

ParametersJSON Schema
NameRequiredDescription
rawNoThe untouched Companies House payload. Present only when verbose was true.
metaYesProvenance and budget for this answer.
queryYes
companiesYes
paginationYesWhere this page sits in the full result set.
exact_name_matchNoCompany number whose name matches the query exactly. Absent if none did.
disambiguation_neededYesMore than one candidate and no exact name match. Ask the user which one they meant.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark the tool as readOnly, openWorld, idempotent, and non-destructive, so the bar for additional disclosure is met. The description goes beyond annotations by explaining the shortlist contents, the disambiguation flag, and the real risk of confidently answering about the wrong company when names collide. This is valuable behavioral context not present in the schema or annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is three sentences, each earning its place: the first states the core function, the second gives routing guidance, and the third warns about a critical failure mode. It is front-loaded with the action and resource, and there is no filler or restatement of the tool name.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only search tool with a 100%-covered schema, an output schema, and strong annotations, the description is complete. It covers purpose, when to use it, what results look like, and how to handle ambiguity. Nothing needed for correct invocation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema fully documents all four parameters. The description adds no new parameter semantics beyond what the schema already provides, though it does reinforce that the query can be a name, trading name, or number, which matches the schema. Baseline 3 is appropriate because the schema carries the full burden.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific action ('Search Companies House for a UK company'), specific inputs (name, trading name or number), and a specific output (shortlist with status, type, incorporation date). It distinguishes this tool from siblings by explicitly positioning it as the starting point when you have a name rather than a number, which differentiates it from get_company and similar number-based tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives direct usage guidance: use this tool whenever you have a name rather than a number, because every other tool in the server needs the number. It also gives a concrete behavioral rule: when disambiguation_needed is true, ask the user which company they meant rather than blindly taking the first result.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

find_officerFind an officerA
Read-onlyIdempotent

Search Companies House for a company officer — a director, secretary or LLP member — by name. Returns candidate officer IDs with how many appointments each holds. Use it when you have a person and want the companies they are involved in; feed the officer_id to get_officer_appointments. Officer records are per-appointment-identity rather than per-person, so a common name returns many candidates and the appointment count and date of birth are usually what separates them.

ParametersJSON Schema
NameRequiredDescriptionDefault
queryYesThe officer's name.
verboseNoAlso return the untouched Companies House payload under `raw`, alongside the shaped result. Roughly two and a half times the size; use it only when a field you need is missing from the shaped result.
start_indexNoZero-based offset into the full result set. Use pagination.has_more to decide.
items_per_pageNoHow many records to return. Defaults to the API default; the maximum is 100.

Output Schema

ParametersJSON Schema
NameRequiredDescription
rawNoThe untouched Companies House payload. Present only when verbose was true.
metaYesProvenance and budget for this answer.
queryYes
officersYes
paginationYesWhere this page sits in the full result set.

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the read-only/idempotent annotations, the description discloses a key behavioral quirk: officer records are per-appointment-identity rather than per-person, so common names return many candidates and appointment count plus date of birth separate them. This is exactly the kind of caveat an agent needs before invoking or interpreting results.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose is front-loaded in the opening sentence, followed by return values, usage guidance, and a caveat. Every sentence adds useful information and there is no padding or redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers what the tool does, when to use it, what it returns, a key data-model caveat, and the downstream tool to call next. With a complete input schema and an output schema present, nothing essential is missing for correct selection and invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already describes all four parameters with 100% coverage, so the baseline is 3. The description adds no param-specific detail beyond 'by name', which the schema already conveys; it relies on the schema for parameter meaning.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States the exact operation — 'Search Companies House for a company officer by name' — and scopes it to directors, secretaries, and LLP members. It also clarifies the output is candidate officer IDs with appointment counts, which distinguishes it from company search and officer-appointment retrieval tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit usage condition: use it when you have a person and want the companies they are involved in, and names get_officer_appointments as the next step. It does not spell out when-not-to-use it versus siblings like get_officers, but the context is otherwise clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_chargesGet chargesA
Read-onlyIdempotent

Secured debt registered against a company: who holds each charge, what it covers, when it was created and whether it has been satisfied. outstanding_count is derived here because Companies House reports what has been settled but never what has not, and outstanding charges are the number that matters when screening a supplier or a debtor. A floating charge covering all assets is worth reading closely. Needs a company number.

ParametersJSON Schema
NameRequiredDescriptionDefault
verboseNoAlso return the untouched Companies House payload under `raw`, alongside the shaped result. Roughly two and a half times the size; use it only when a field you need is missing from the shaped result.
company_numberYesEight-character Companies House number, such as 00000006 or SC123456. Leading zeros may be omitted. This tool does not accept a company name — call find_company first if that is all you have.

Output Schema

ParametersJSON Schema
NameRequiredDescription
rawNoThe untouched Companies House payload. Present only when verbose was true.
metaYesProvenance and budget for this answer.
chargesYes
total_countYes
company_numberYes
satisfied_countYes
outstanding_countYesDerived: total minus satisfied and part-satisfied.
part_satisfied_countYes

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

While annotations already declare readOnlyHint, openWorldHint, idempotentHint, and destructiveHint=false, the description adds meaningful behavioral context: outstanding_count is derived because Companies House does not report unsettled charges, and floating charges deserve closer scrutiny. This goes beyond the structured annotations without contradicting them.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is four sentences and each contributes value: what the tool returns, an important derived-field nuance, a risk heuristic, and an input requirement. It is appropriately front-loaded with the core definition, though slightly longer than strictly necessary.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the output schema exists and the tool is a read-only retrieval operation, the description covers the essential context: what charges are, why the derived field matters, a caution about floating charges, and the required identifier. Minor gaps like pagination are not critical given the output schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already fully documents company_number and verbose. The description adds no new parameter-specific detail beyond restating that a company number is needed, which the schema already covers. A baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly identifies the resource (secured debt/charges registered against a company) and the specific attributes returned: holder, coverage, creation date, and satisfaction status. This distinguishes it from sibling tools like get_company or get_psc, which address different company data domains.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives a concrete use case ('when screening a supplier or a debtor') and states the required input ('Needs a company number'). It does not explicitly call out alternatives or when not to use the tool, but the schema does point to find_company when only a company name is available.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_companyGet a company profileA
Read-onlyIdempotent

The registered profile for one UK company: legal name, status, type, incorporation date, registered office, SIC codes, and the accounts and confirmation statement due dates. Also returns derived flags that Companies House does not provide — whether filings are overdue, whether the company holds charges or has insolvency history, and whether it was incorporated within the last year. Use it to verify a company is real and active before relying on it. Needs a company number; call find_company first if you only have a name.

ParametersJSON Schema
NameRequiredDescriptionDefault
verboseNoAlso return the untouched Companies House payload under `raw`, alongside the shaped result. Roughly two and a half times the size; use it only when a field you need is missing from the shaped result.
company_numberYesEight-character Companies House number, such as 00000006 or SC123456. Leading zeros may be omitted. This tool does not accept a company name — call find_company first if that is all you have.

Output Schema

ParametersJSON Schema
NameRequiredDescription
rawNoThe untouched Companies House payload. Present only when verbose was true.
metaYesProvenance and budget for this answer.
nameYes
typeNo
flagsYesDerived risk signals. Each one is computed here, not returned by Companies House.
statusNo
accountsYes
age_yearsNoWhole years since incorporation.
sic_codesYesStandard Industrial Classification codes for the trade.
dissolved_onNo
jurisdictionNo
status_detailNo
company_numberYes
incorporated_onNo
type_descriptionNo
confirmation_statementYes
registered_office_addressNo
registered_office_in_disputeNo

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already establish that the tool is read-only, idempotent, and non-destructive. The description adds valuable behavioral context beyond annotations: it returns derived flags that Companies House itself does not provide, such as overdue indicators, charges/insolvency history presence, and recent incorporation. It also repeats the input constraint that only a company number is accepted. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is longer than minimal but every sentence earns its place: first the returned data inventory, then the derived flags, then the intended use case and prerequisite. It is front-loaded with the resource and scope, and there is no filler or tautology.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the read-only annotations, complete parameter schema, and existing output schema, the description covers everything an agent needs to select and invoke this tool correctly: what it returns, what derived flags it adds, when to use it, and how to handle a name-only input. No critical behavioral or prerequisite information is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already fully documents both company_number and verbose. The tool description reinforces the 'do not pass a name' caveat and the find_company prerequisite, but it does not add meaningful parameter-level semantics beyond what the input schema already provides. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: it returns the registered profile for one UK company, and enumerates the exact fields included (legal name, status, type, incorporation date, registered office, SIC codes, due dates). It also distinguishes the tool from find_company by clarifying that get_company needs a company number and does not accept a name.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly says to use this tool to verify a company is real and active before relying on it, and directs agents to call find_company first if only a name is available. It does not explicitly mention when to prefer related sibling tools like get_charges or get_insolvency, but it does clarify that it returns only derived flags about those topics rather than full details.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_filing_historyGet filing historyA
Read-onlyIdempotent

What a company has filed and when — accounts, confirmation statements, officer changes, mortgages, address changes. Use it to judge whether a company is filing on time, to see when accounts were last made up, or to watch a competitor's filing cadence. Descriptions come back as Companies House template keys such as accounts-with-accounts-type-small, with their values alongside; the key is readable enough to interpret and is not translated here because a partial translation would render some filings wrongly. Filter with category to cut the volume. Needs a company number.

ParametersJSON Schema
NameRequiredDescriptionDefault
verboseNoAlso return the untouched Companies House payload under `raw`, alongside the shaped result. Roughly two and a half times the size; use it only when a field you need is missing from the shaped result.
categoryNoRestrict to one category, e.g. accounts, confirmation-statement, officers, mortgage, address, capital, incorporation, resolution, insolvency.
start_indexNoZero-based offset into the full result set. Use pagination.has_more to decide.
company_numberYesEight-character Companies House number, such as 00000006 or SC123456. Leading zeros may be omitted. This tool does not accept a company name — call find_company first if that is all you have.
items_per_pageNoHow many records to return. Defaults to the API default; the maximum is 100.

Output Schema

ParametersJSON Schema
NameRequiredDescription
rawNoThe untouched Companies House payload. Present only when verbose was true.
metaYesProvenance and budget for this answer.
filingsYes
paginationYesWhere this page sits in the full result set.
company_numberYes

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description adds genuine behavioral context beyond the read-only annotations by explaining that filing descriptions come back as un-translated Companies House template keys and why partial translation was avoided. It also hints at response volume by recommending category filtering, which is useful for an agent deciding how to call the tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loaded: it states the core purpose first, then use cases, then an important output-format caveat, then a filtering tip. Every sentence earns its place without verbose framing or redundant schema repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the output schema and fully described input parameters, the description covers the important operational details: what filings are included, how keys are represented, why translation is skipped, and how to reduce volume. It could be slightly stronger by mentioning pagination behavior explicitly, but the start_index parameter and output schema already carry that burden.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the parameters are fully documented in the schema. The description adds only minimal parameter-related guidance, such as using category to cut volume and requiring a company number, which mostly restates what the schema already says.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific statement of what the tool returns — "What a company has filed and when" — and lists concrete filing types such as accounts, confirmation statements, and officer changes. This clearly distinguishes it from sibling tools like get_company or get_officers by focusing on filing history events.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit use cases: judging whether a company files on time, seeing when accounts were last made up, and watching a competitor's filing cadence. It also notes the need for a company number and suggests filtering with category, though it does not explicitly name alternative tools or state when not to use it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_insolvencyGet insolvency historyA
Read-onlyIdempotent

Insolvency cases registered against a company: the type of proceeding, its key dates, and the insolvency practitioners appointed. Call it when get_company reports has_insolvency_history, or as part of a credit or supplier risk check. A company with no insolvency history returns a not-found error rather than an empty list, which is a quirk of the API and means exactly what it sounds like. Needs a company number.

ParametersJSON Schema
NameRequiredDescriptionDefault
verboseNoAlso return the untouched Companies House payload under `raw`, alongside the shaped result. Roughly two and a half times the size; use it only when a field you need is missing from the shaped result.
company_numberYesEight-character Companies House number, such as 00000006 or SC123456. Leading zeros may be omitted. This tool does not accept a company name — call find_company first if that is all you have.

Output Schema

ParametersJSON Schema
NameRequiredDescription
rawNoThe untouched Companies House payload. Present only when verbose was true.
metaYesProvenance and budget for this answer.
casesYes
case_countYes
company_numberYes

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond readOnly/idempotent annotations, it discloses a genuinely surprising API quirk: no history yields a not-found error rather than an empty list. This prevents an agent from misinterpreting an error as a failure of the tool itself.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences: what the tool returns, when to use it, and the one edge case an agent must know. Every sentence earns its place and important constraints are front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, the description need not re-specify return fields. It covers purpose, trigger, error behavior, and required input, and annotations cover safety, making this complete for reliable invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so both company_number and verbose are already documented in the schema. The description adds only a high-level 'Needs a company number' restatement, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific resource (insolvency cases registered against a company) and the meaningful output (proceeding type, key dates, practitioners). It also ties it to get_company's has_insolvency_history flag, which differentiates it from sibling tools without needing to inspect schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit trigger conditions: call it when get_company reports has_insolvency_history or as part of a credit/supplier risk check. It does not enumerate exclusions or alternatives, but there is no dedicated sibling insolvency tool, and 'Needs a company number' clarifies a prerequisite.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_officer_appointmentsGet an officer’s appointmentsA
Read-onlyIdempotent

Every company an officer is or has been appointed to. This is the conflict-of-interest and director-network tool: run it across a board to find the shared directorship nobody declared, or across one person to see whether they have a history of dissolved companies. Needs an officer_id, which comes from get_officers or find_officer and never from a name.

ParametersJSON Schema
NameRequiredDescriptionDefault
verboseNoAlso return the untouched Companies House payload under `raw`, alongside the shaped result. Roughly two and a half times the size; use it only when a field you need is missing from the shaped result.
officer_idYesOfficer identifier from get_officers or find_officer, not a person’s name.
start_indexNoZero-based offset into the full result set. Use pagination.has_more to decide.
items_per_pageNoHow many records to return. Defaults to the API default; the maximum is 100.

Output Schema

ParametersJSON Schema
NameRequiredDescription
rawNoThe untouched Companies House payload. Present only when verbose was true.
metaYesProvenance and budget for this answer.
nameNo
officer_idYes
paginationYesWhere this page sits in the full result set.
appointmentsYes
date_of_birthNo
active_appointment_countYesDerived from the returned page, not the whole set.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly/idempotent/non-destructive, and the description adds behavior beyond that: the result includes both current and historical appointments ('is or has been appointed to') and is suited for spotting dissolved-company history. No annotation contradiction exists.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tightly written sentences: core function, illustrative use cases, and the key input requirement. Every sentence contributes new information and the most important facts are front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only list endpoint with a full output schema and fully documented parameters, the description covers the essential context: what data is returned, why an agent would use it, and where the required identifier comes from. Nothing critical is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema carries most parameter documentation. The description adds important semantic value for officer_id by stating it must come from get_officers or find_officer and not from a name, which prevents a common misuse.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states the exact resource ('Every company an officer is or has been appointed to') and positions the tool as the conflict-of-interest/director-network lookup. This clearly distinguishes it from siblings like get_company or get_officers, which have different scopes.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives concrete when-to-use scenarios: running across a board to expose undeclared shared directorships, or checking a person's history of dissolved companies. It does not explicitly list sibling alternatives or exclusion conditions, but the use-case framing is clear enough to route an agent correctly.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_officersGet company officersA
Read-onlyIdempotent

The directors, secretaries and members of one company, current and resigned, each with an officer_id you can pass to get_officer_appointments. Use it to see who runs a company, or as the first step in a conflict-of-interest check across a board. Service addresses are withheld unless verbose is set, because they are personal data and are rarely what the question needs. Needs a company number; call find_company first if you only have a name.

ParametersJSON Schema
NameRequiredDescriptionDefault
verboseNoAlso return the untouched Companies House payload under `raw`, alongside the shaped result. Roughly two and a half times the size; use it only when a field you need is missing from the shaped result.
start_indexNoZero-based offset into the full result set. Use pagination.has_more to decide.
company_numberYesEight-character Companies House number, such as 00000006 or SC123456. Leading zeros may be omitted. This tool does not accept a company name — call find_company first if that is all you have.
items_per_pageNoHow many records to return. Defaults to the API default; the maximum is 100.

Output Schema

ParametersJSON Schema
NameRequiredDescription
rawNoThe untouched Companies House payload. Present only when verbose was true.
metaYesProvenance and budget for this answer.
officersYes
paginationYesWhere this page sits in the full result set.
active_countNo
company_numberYes
inactive_countNoAppointments that ended because the company did, rather than by resignation. Non-zero on a dissolved company, and the reason active + resigned can fall short of the total.
resigned_countNo

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark the tool read-only and idempotent, and the description adds non-obvious behavior: service addresses are withheld for privacy unless verbose is set. It also discloses that verbose returns a much larger raw payload, which helps the agent set expectations beyond what the annotations convey.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four sentences, each earning its place: the tool's output, the use cases, the privacy caveat, and the prerequisite. The most actionable information is front-loaded, and there is no redundant wording.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, the description does not need to explain return values. Combined with full schema documentation for all parameters, the description covers purpose, usage context, privacy behavior, and how to chain with sibling tools, so nothing critical is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, which sets a baseline of 3. The description adds extra meaning for company_number by emphasizing it cannot be a name and requires find_company first, and for verbose by explaining the privacy trade-off. The remaining parameters are adequately documented in the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: get officers of one company, including current and resigned. It also distinguishes itself from related siblings by noting each result carries an officer_id to pass to get_officer_appointments, making it clearly different from find_officer or get_officer_appointments.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly gives when to use the tool: to see who runs a company or as the first step in a conflict-of-interest check. It also names the prerequisite (company number) and directs the agent to call find_company first if only a name is available.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_pscGet persons with significant controlA
Read-onlyIdempotent

Who OWNS a company. Use this for any question about ownership, shareholders, beneficial owners or who is ultimately behind a business — the company profile does not carry ownership and get_company will not answer it. Returns each person or entity with significant control: how much they own (shareholding band), how that control is held (voting rights, right to appoint directors), and whether the interest is current or ceased. Ownership is often not the same as the directors, so this is a different question from get_officers. Where a company cannot identify a controller it files a statement instead of a person, and that statement is returned in the name field. Needs a company number.

ParametersJSON Schema
NameRequiredDescriptionDefault
verboseNoAlso return the untouched Companies House payload under `raw`, alongside the shaped result. Roughly two and a half times the size; use it only when a field you need is missing from the shaped result.
start_indexNoZero-based offset into the full result set. Use pagination.has_more to decide.
company_numberYesEight-character Companies House number, such as 00000006 or SC123456. Leading zeros may be omitted. This tool does not accept a company name — call find_company first if that is all you have.
items_per_pageNoHow many records to return. Defaults to the API default; the maximum is 100.

Output Schema

ParametersJSON Schema
NameRequiredDescription
rawNoThe untouched Companies House payload. Present only when verbose was true.
metaYesProvenance and budget for this answer.
paginationYesWhere this page sits in the full result set.
controllersYes
active_countNo
ceased_countNo
company_numberYes

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is covered. The description adds meaningful behavior beyond the annotations: it explains the returned fields, states that interests can be current or ceased, and discloses the edge case where a statement is returned in the name field instead of a person. This provides actionable behavioral context without contradicting the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but every sentence earns its place: it states the core purpose, gives usage context, distinguishes from siblings, explains the return data, and covers a key edge case. The most important routing signal is front-loaded with 'Who OWNS a company,' and the final 'Needs a company number' is a useful practical requirement. There is no filler or repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only, idempotent tool with an output schema and 100% schema parameter coverage, the description is complete. It explains what the tool returns, when to use it, how it differs from related tools, how to handle the statement fallback, and the prerequisite of a company number. Pagination is already covered by the schema's start_index and items_per_page descriptions, so no further behavioral detail is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the input schema already documents all four parameters thoroughly, including company_number format, verbose behavior, pagination offset, and items_per_page. The description adds only 'Needs a company number' and the hint to call find_company if only a name is available, which the schema already states. This is the baseline 3 case: the schema carries the parameter-semantics burden and the description does not need to compensate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with the concrete, memorable phrase 'Who OWNS a company' and immediately identifies the resource: persons with significant control, including shareholding bands and control mechanisms. It also differentiates itself from related tools by explicitly stating that get_company will not answer ownership questions and that ownership is a different question from get_officers, so an agent can distinguish it from siblings without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

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 this for any question about ownership, shareholders, beneficial owners or who is ultimately behind a business.' It also names exclusions and alternatives, warning that get_company will not answer this and directing users to find_company if they only have a company name. This is exactly the kind of routing context an agent needs.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

screen_companiesScreen a list of companiesA
Read-onlyIdempotent

Use this whenever the question is about MORE THAN ONE company — a list, a comparison, "which of these", a batch from procurement, anything with several names or numbers in it. Prefer it over calling company_snapshot repeatedly: it costs a quarter of the requests and returns a table you can read at a glance. Screens up to 50 companies and returns one row each: status, age, and which signals were found. Names that match more than one company are never guessed at; they come back under unresolved with their candidates so you can ask which was meant. Anything skipped for want of rate-limit budget comes back under not_screened with the reason, so the table is never quietly shorter than the list you passed in. Rows carry signal codes only — call company_snapshot on one company number for the detail behind them. Officers are excluded by default because they cost an extra request per company; sections_used says what the signals could see.

ParametersJSON Schema
NameRequiredDescriptionDefault
companiesYesCompany names or numbers. Mixed input is fine. Maximum 50 per call.
include_chargesNoInclude charges. On by default.
include_officersNoFetch officers too, enabling the no_active_officers and recent_officer_departures signals. Off by default: it adds one request per company.
include_insolvencyNoInclude insolvency cases. On by default.

Output Schema

ParametersJSON Schema
NameRequiredDescription
metaYesProvenance and budget for this answer.
screenedYes
requestedYes
unresolvedYesInputs that could not be resolved to exactly one company. Never guessed at.
not_screenedYesInputs deliberately skipped, with the reason. Nothing is dropped silently.
sections_usedYesSignals in this table can only reflect these sections. Officers are off by default.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark this read-only/idempotent, but the description adds substantial behavioral context: one row per company, signal codes only, unresolved names returned with candidates rather than guessed, not_screened entries with reasons for rate-limit skips, and officer handling with cost implications. None of this is visible in the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Dense but every sentence contributes: usage guidance is front-loaded, the alternative is named early, and edge-case behaviors are explained in logical order. No filler or repetition of schema content.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity and the presence of an output schema, the description covers all necessary operational details: limits, return shape, unresolved/not_screened behavior, signal-code usage, and officer cost trade-offs. Nothing an agent needs to safely invoke it is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds meaningful context beyond the schema: it explains that names matching multiple companies are not guessed, unresolved results include candidates, and include_officers carries an extra request cost. This helps an agent choose parameters more wisely.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description states a specific verb and resource ('Screen a list of companies') and immediately clarifies it is for MORE THAN ONE company. It explicitly contrasts with company_snapshot, so an agent can distinguish the intended use without inspecting schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit when-to-use conditions: lists, comparisons, batches, and anything with several names or numbers. It also names the alternatives (company_snapshot for detail, repeated calls as the less efficient option) and explains when to switch.

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.

  1. 11 tool updatesv0.4.0
    • Changedcompany_snapshot7 fields changed
      • changedOutput schema / properties / charges / properties / holders / description
        Previous value: -"Who holds the outstanding charges."New value: +"Holders of returned charges not recorded as fully satisfied."
      • addedOutput schema / properties / charges / properties / part_satisfied_count
        Added value: +{
        +  "type": "number"
        +}
      • changedOutput schema / properties / charges / required
        Previous value: -[
        -  "total_count",
        -  "outstanding_count",
        -  "satisfied_count",
        -  "holders"
        -]New value: +[
        +  "total_count",
        +  "outstanding_count",
        +  "satisfied_count",
        +  "part_satisfied_count",
        +  "holders"
        +]
      • changedOutput schema / properties / meta / properties / licence / description
        Previous value: -"Companies House data is Open Government Licence v3.0."New value: +"OGL v3.0 applies to eligible public-sector information. Personal data and other OGL exclusions are not licensed by this label; applicable data-protection duties still apply."
      • addedOutput schema / properties / officers / properties / pagination
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Coverage of the fetched officer page, before filtering to active officers. Follow get_officers pagination for the full list; counts describe the whole register.",
        +  "properties": {
        +    "has_more": {
        +      "description": "More records exist. Call again with start_index advanced by `returned`.",
        +      "type": "boolean"
        +    },
        +    "items_per_page": {
        +      "type": "number"
        +    },
        +    "returned": {
        +      "description": "How many records are in this response.",
        +      "type": "number"
        +    },
        +    "start_index": {
        +      "type": "number"
        +    },
        +    "total_results": {
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "start_index",
        +    "items_per_page",
        +    "total_results",
        +    "returned",
        +    "has_more"
        +  ],
        +  "type": "object"
        +}
      • changedOutput schema / properties / officers / required
        Previous value: -[
        -  "active"
        -]New value: +[
        +  "pagination",
        +  "active"
        +]
      • changedOutput schema / properties / signals / items / properties / code / enum
        Previous value: -[
        -  "dissolved",
        -  "insolvency_proceedings",
        -  "not_active",
        -  "insolvency_history",
        -  "accounts_overdue",
        -  "confirmation_statement_overdue",
        -  "outstanding_charges",
        -  "floating_charge_over_all_assets",
        -  "no_active_officers",
        -  "recent_officer_departures",
        -  "incorporated_within_last_year",
        -  "registered_office_in_dispute"
        -]New value: +[
        +  "dissolved",
        +  "insolvency_proceedings",
        +  "not_active",
        +  "insolvency_history",
        +  "accounts_overdue",
        +  "confirmation_statement_overdue",
        +  "outstanding_charges",
        +  "part_satisfied_charges",
        +  "floating_charge_over_all_assets",
        +  "no_active_officers",
        +  "recent_officer_departures",
        +  "incorporated_within_last_year",
        +  "registered_office_in_dispute"
        +]
    • Changedfind_company2 fields changed
      • addedInput schema / properties / query / maxLength
        Added value: +256
      • changedOutput schema / properties / meta / properties / licence / description
        Previous value: -"Companies House data is Open Government Licence v3.0."New value: +"OGL v3.0 applies to eligible public-sector information. Personal data and other OGL exclusions are not licensed by this label; applicable data-protection duties still apply."
    • Changedfind_officer2 fields changed
      • addedInput schema / properties / query / maxLength
        Added value: +256
      • changedOutput schema / properties / meta / properties / licence / description
        Previous value: -"Companies House data is Open Government Licence v3.0."New value: +"OGL v3.0 applies to eligible public-sector information. Personal data and other OGL exclusions are not licensed by this label; applicable data-protection duties still apply."
    • Changedget_charges1 field changed
      • changedOutput schema / properties / meta / properties / licence / description
        Previous value: -"Companies House data is Open Government Licence v3.0."New value: +"OGL v3.0 applies to eligible public-sector information. Personal data and other OGL exclusions are not licensed by this label; applicable data-protection duties still apply."
    • Changedget_company1 field changed
      • changedOutput schema / properties / meta / properties / licence / description
        Previous value: -"Companies House data is Open Government Licence v3.0."New value: +"OGL v3.0 applies to eligible public-sector information. Personal data and other OGL exclusions are not licensed by this label; applicable data-protection duties still apply."
    • Changedget_filing_history1 field changed
      • changedOutput schema / properties / meta / properties / licence / description
        Previous value: -"Companies House data is Open Government Licence v3.0."New value: +"OGL v3.0 applies to eligible public-sector information. Personal data and other OGL exclusions are not licensed by this label; applicable data-protection duties still apply."
    • Changedget_insolvency1 field changed
      • changedOutput schema / properties / meta / properties / licence / description
        Previous value: -"Companies House data is Open Government Licence v3.0."New value: +"OGL v3.0 applies to eligible public-sector information. Personal data and other OGL exclusions are not licensed by this label; applicable data-protection duties still apply."
    • Changedget_officer_appointments1 field changed
      • changedOutput schema / properties / meta / properties / licence / description
        Previous value: -"Companies House data is Open Government Licence v3.0."New value: +"OGL v3.0 applies to eligible public-sector information. Personal data and other OGL exclusions are not licensed by this label; applicable data-protection duties still apply."
    • Changedget_officers2 fields changed
      • addedOutput schema / properties / inactive_count
        Added value: +{
        +  "description": "Appointments that ended because the company did, rather than by resignation. Non-zero on a dissolved company, and the reason active + resigned can fall short of the total.",
        +  "type": "number"
        +}
      • changedOutput schema / properties / meta / properties / licence / description
        Previous value: -"Companies House data is Open Government Licence v3.0."New value: +"OGL v3.0 applies to eligible public-sector information. Personal data and other OGL exclusions are not licensed by this label; applicable data-protection duties still apply."
    • Changedget_psc1 field changed
      • changedOutput schema / properties / meta / properties / licence / description
        Previous value: -"Companies House data is Open Government Licence v3.0."New value: +"OGL v3.0 applies to eligible public-sector information. Personal data and other OGL exclusions are not licensed by this label; applicable data-protection duties still apply."
    • Changedscreen_companies8 fields changed
      • addedInput schema / properties / companies / items / maxLength
        Added value: +256
      • changedOutput schema / properties / meta / properties / licence / description
        Previous value: -"Companies House data is Open Government Licence v3.0."New value: +"OGL v3.0 applies to eligible public-sector information. Personal data and other OGL exclusions are not licensed by this label; applicable data-protection duties still apply."
      • addedOutput schema / properties / screened / items / properties / meta
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Provenance and budget for this answer.",
        +  "properties": {
        +    "age_seconds": {
        +      "description": "How long ago the cached answer was retrieved. Absent for a live answer.",
        +      "type": "number"
        +    },
        +    "cached": {
        +      "description": "Answer came from the local cache rather than a live request.",
        +      "type": "boolean"
        +    },
        +    "licence": {
        +      "const": "OGL-v3.0",
        +      "description": "OGL v3.0 applies to eligible public-sector information. Personal data and other OGL exclusions are not licensed by this label; applicable data-protection duties still apply.",
        +      "type": "string"
        +    },
        +    "rate_limit_remaining": {
        +      "description": "Requests still available in the current five-minute window. Pace long runs by this.",
        +      "type": "number"
        +    },
        +    "rate_limit_resets_in_ms": {
        +      "description": "Milliseconds until more budget becomes available.",
        +      "type": "number"
        +    },
        +    "stale": {
        +      "description": "Answer came from an expired cache entry because Companies House was unreachable. Treat the data as possibly out of date.",
        +      "type": "boolean"
        +    }
        +  },
        +  "required": [
        +    "cached",
        +    "stale",
        +    "rate_limit_remaining",
        +    "rate_limit_resets_in_ms",
        +    "licence"
        +  ],
        +  "type": "object"
        +}
      • addedOutput schema / properties / screened / items / properties / officers_pagination
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Officer page coverage when officers were requested.",
        +  "properties": {
        +    "has_more": {
        +      "description": "More records exist. Call again with start_index advanced by `returned`.",
        +      "type": "boolean"
        +    },
        +    "items_per_page": {
        +      "type": "number"
        +    },
        +    "returned": {
        +      "description": "How many records are in this response.",
        +      "type": "number"
        +    },
        +    "start_index": {
        +      "type": "number"
        +    },
        +    "total_results": {
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "start_index",
        +    "items_per_page",
        +    "total_results",
        +    "returned",
        +    "has_more"
        +  ],
        +  "type": "object"
        +}
      • addedOutput schema / properties / screened / items / properties / sections_included
        Added value: +{
        +  "description": "Sections actually fetched for this company.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / screened / items / properties / sections_unavailable
        Added value: +{
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "code": {
        +        "description": "The error code from the failed request.",
        +        "type": "string"
        +      },
        +      "message": {
        +        "type": "string"
        +      },
        +      "section": {
        +        "description": "Which part of the snapshot could not be read.",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "section",
        +      "code",
        +      "message"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • changedOutput schema / properties / screened / items / properties / signal_codes / items / enum
        Previous value: -[
        -  "dissolved",
        -  "insolvency_proceedings",
        -  "not_active",
        -  "insolvency_history",
        -  "accounts_overdue",
        -  "confirmation_statement_overdue",
        -  "outstanding_charges",
        -  "floating_charge_over_all_assets",
        -  "no_active_officers",
        -  "recent_officer_departures",
        -  "incorporated_within_last_year",
        -  "registered_office_in_dispute"
        -]New value: +[
        +  "dissolved",
        +  "insolvency_proceedings",
        +  "not_active",
        +  "insolvency_history",
        +  "accounts_overdue",
        +  "confirmation_statement_overdue",
        +  "outstanding_charges",
        +  "part_satisfied_charges",
        +  "floating_charge_over_all_assets",
        +  "no_active_officers",
        +  "recent_officer_departures",
        +  "incorporated_within_last_year",
        +  "registered_office_in_dispute"
        +]
      • changedOutput schema / properties / screened / items / required
        Previous value: -[
        -  "input",
        -  "company_number",
        -  "name",
        -  "signal_codes",
        -  "signal_count"
        -]New value: +[
        +  "input",
        +  "company_number",
        +  "name",
        +  "signal_codes",
        +  "signal_count",
        +  "sections_included",
        +  "sections_unavailable",
        +  "meta"
        +]
  2. 11 tool updatesv0.2.0
    • First observedcompany_snapshot
    • First observedfind_company
    • First observedfind_officer
    • First observedget_charges
    • First observedget_company
    • First observedget_filing_history
    • First observedget_insolvency
    • First observedget_officer_appointments
    • First observedget_officers
    • First observedget_psc
    • First observedscreen_companies

TDQS

A4.4/5.0

Scored across 11 tools

Disambiguation5/5

Each tool targets a distinct resource/action: company search vs company profile, officer search vs officer list vs officer appointments, and individual getters vs aggregate snapshot/batch screening. The one area of potential overlap, company_snapshot with get_company/get_officers/get_charges/get_insolvency, is explicitly described as a replacement for combined calls, so agents can choose correctly.

Naming Consistency4/5

The naming mostly follows a clear find_/get_ pattern, where find_ is for search and get_ is for retrieval by an ID. The pattern is weakened slightly by company_snapshot and screen_companies, which are descriptive but break the verb-prefix convention.

Tool Count5/5

11 tools is well within the ideal range and every tool earns its place: seven single-resource lookups, two search entry points, one aggregate snapshot, and one batch screening tool. The count feels deliberately scoped for a Companies House screening domain rather than padded or thin.

Completeness5/5

The surface covers the full screening workflow: company identification, company status, officers, ownership/PSC, charges, insolvency, filing history, officer appointment networks, individual deep-dives, and batch comparison. There are no obvious dead ends or missing operations that would prevent an agent from answering typical due-diligence questions.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    C
    quality
    F
    maintenance
    Access UK company data through the Companies House API directly in MCP clients, with 45+ tools for company info, search, officers, filing history, ownership, and charges.
    37
    39 npm
    29
    AGPL 3.0
  • F
    license
    Not graded
    quality
    D
    maintenance
    A local MCP server that exposes the UK Companies House API as tools for Claude Desktop and Cowork, enabling company search, profile retrieval, officer lookup, and document downloads.
    -
  • F
    license
    Not graded
    quality
    D
    maintenance
    MCP server exposing the full UK Companies House Public Data API, enabling natural language queries for company profiles, search, officers, filing history, charges, insolvency, and persons with significant control, as well as downloading and reading PDF documents.
    -