Skip to main content
Glama

nhs-intelligence-mcp

一个 MCP 服务器,暴露 NHS 等待时间和信托情报工具,使智能体客户端(Claude Code、Claude Desktop 或任何兼容 MCP 的主机)能够基于真实的公共数据回答关于 NHS 提供者绩效的开放性问题。

服务器仅暴露数据和分析工具;它从不调用 LLM。智能体推理发生在连接的客户端中,由客户端串联这些工具。这保证了数字的确定性,并且整个服务器可在离线状态下进行单元测试。

状态

里程碑 3。覆盖三个数据源的五个工具:RTT 趋势、My Planned Care 当前状态(查询和排名)、CQC 质量评级,以及一个结合了全部三者的 trust_profile。每个工具都端到端地配有离线测试套件(57 个测试)。

关于信托身份的说明

这三个数据源对信托的命名方式不同:RTT 使用数字提供者代码(例如 RGT),My Planned Care 使用信托名称(例如 Guy's and St Thomas'),CQC 使用自己的提供者 id(例如 1-101681210)。单一来源工具采用其数据源发布的身份。trust_profile 通过一份精选的映射文件将三者协调一致;不在映射中的信托返回 found=false。评级数据是补充性的:如果 CQC 数据源不可达,该概览会丢弃那一部分,但仍返回等待时间和趋势数据。

Related MCP server: NHS MCP Server

设计

src/nhs_intel/
  domain/      # immutable value objects (WaitTimePoint, TrustRating, ...)
  sources/     # adapters behind Protocols (CSV feeds, CQC HTTP, identity map)
  analysis/    # pure trend, ranking and profile-join logic
  server.py    # thin FastMCP layer: validate -> pure handler -> serialise

纯核心(domain、analysis)没有 I/O 操作,也不导入 MCP,因此它可以在没有网络和实时 NHS 数据源的情况下在 CI 中运行。包括 CQC HTTP 客户端在内的每个数据源都位于一个 Protocol 之后,因此测试可以注入内存中的假实现,整个测试套件完全离线。这就是 nhs-webscraper 的端口与适配器边界,应用于数据源。

数据源

数据源

频率

作用

访问

NHS England RTT

每月

趋势主干

CSV 缓存

My Planned Care (via nhs-webscraper)

每周

当前状态层

CSV

CQC 评级

每日

信托质量背景

公共 API,无需密钥

工具

工具

输入

返回

wait_time_trend

provider_code, specialty

开始/结束等待时间、差值、% 变化、方向、月度序列(RTT)

lookup_wait_time

provider(名称), specialty

一个信托的最新当前等待时间(My Planned Care)

rank_trusts_by_wait

specialty, region?, limit?

按当前等待时间排名的信托,最长的在前(My Planned Care)

get_trust_rating

cqc_provider_id

总体及按领域的 CQC 评级

trust_profile

identifier, specialty, by_name?

一个信托的综合当前等待时间、趋势和评级

趋势方向由相对死区(默认 5%)决定,因此长时间等待中的小幅波动会被解读为 flat,而不是虚假趋势:这与 MRR-prediction 项目中做出的噪声抑制选择相同。排名列表会将发布了某专科但没有数值的信托排在已排名信托之后,使覆盖缺口可见,并与零等待区分开来。

运行

依赖项通过 uv 管理,并锁定在 uv.lock 中;同时导出一份普通的 requirements.txt,供没有 uv 的人使用。

# uv resolves and creates .venv automatically from uv.lock:
uv sync --extra dev

# Point the server at an ingested RTT CSV cache (provider_code,specialty,weeks,as_of):
export NHS_INTEL_RTT_CSV=tests/fixtures/rtt_sample.csv

# Optional: My Planned Care scraper output for the current-state tools.
export NHS_INTEL_PLANNED_CARE_CSV=tests/fixtures/planned_care_sample.csv

# Optional: cross-source identity mapping for trust_profile.
export NHS_INTEL_IDENTITY_CSV=tests/fixtures/identity_sample.csv

# Optional: a partnerCode string sent with CQC requests to identify your caller.
export NHS_INTEL_CQC_PARTNER_CODE=my-org

# Run the MCP server over stdio:
uv run nhs-intel-mcp

没有 uv 时:pip install -r requirements.txt,然后直接运行 nhs-intel-mcp,并设置相同的环境变量。

只有 NHS_INTEL_RTT_CSV 是必需的;每个工具都会在其数据源未配置时明确报告,并且 CQC 数据源在不可达时会降级为缺失的评级部分。.mcp.json 使用 uv run 为 Claude Code 注册服务器,因此无论调用 shell 中当前激活的是什么环境,都会使用项目自身的环境。

开发

uv sync --extra dev
uv run pytest    # offline, no network or keys required
uv run ruff check .

Available Tools

5 tools
get_trust_ratingA

Look up a trust's current CQC quality rating by its CQC provider id (e.g. '1-101681210'). Returns the overall rating (e.g. 'Good', 'Requires improvement') and any per-domain ratings (safe, effective, caring, responsive, well-led). Returns found=false if the provider is unknown or not yet rated; do not infer a rating in that case.

ParametersJSON Schema
NameRequiredDescriptionDefault
cqc_provider_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.5/5.0
Behavior4/5

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

With no annotations, the description carries the behavioral disclosure burden. It discloses the return shape (overall plus per-domain ratings), the not-found behavior (found=false), and an important instruction not to infer a rating. This is strong for a read-only lookup tool, though it does not explicitly mention safety or data freshness.

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 sentences, each earning its place: purpose and input, return content, and the critical not-found behavior. Information is front-loaded and no filler is present.

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 single-parameter lookup tool with an output schema, the description is complete. It covers input, expected outputs, the not-found case, and the correct behavior when no rating exists. Nothing essential for an agent to select and call the tool correctly 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 0%, so the description must compensate. It explains that cqc_provider_id is the CQC provider id and supplies a realistic example ('1-101681210'), adding meaning beyond the bare schema field. It does not elaborate on id source or formatting rules, but the example and context are sufficient for correct invocation.

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 action (look up), the resource (a trust's current CQC quality rating), and the lookup key (CQC provider id), with a concrete example. It also distinguishes itself from sibling tools focused on wait times and trust profiles by explicitly focusing on CQC quality ratings.

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 states the task and input clearly enough that an agent knows when to invoke it: whenever a trust's CQC rating is needed. It does not explicitly name sibling alternatives or exclusion conditions, but the focused wording and the contrast with wait-time-related siblings imply the appropriate use case.

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

lookup_wait_timeA

Look up the latest reported waiting time for one NHS trust and specialty from My Planned Care (updated weekly). Waits are in whole weeks. Provide the trust name as published (e.g. 'Guy's and St Thomas'') and the specialty (e.g. 'Cardiology'). Returns found=false if the trust/specialty is not held; do not invent a figure. Note the trust is identified by name here, unlike wait_time_trend which uses an RTT provider code.

ParametersJSON Schema
NameRequiredDescriptionDefault
providerYes
specialtyYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A5/5.0
Behavior5/5

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

With no annotations provided, the description carries the full burden of behavioral disclosure. It states that waits are in whole weeks, data is updated weekly, found=false is returned when the trust/specialty is not held, and that the agent must not invent a figure. These are material behaviors beyond the schema.

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?

Every sentence adds necessary information: purpose and source, units, parameter formatting, not-found behavior, and the sibling-tool distinction. The description is front-loaded with the core purpose and contains no filler.

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 two-parameter lookup tool with an output schema, this description is remarkably complete. It covers source, freshness, units, input formatting, missing-data behavior, and the key alternative tool, leaving no significant gap for an agent to resolve.

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

Parameters5/5

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

Schema description coverage is 0%, so the description must compensate. It does so thoroughly by explaining that provider should be 'the trust name as published' with an example, and specialty should be like 'Cardiology' — also clarifying the name-based identifier, which is essential for correct use.

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 specific verb and resource: 'Look up the latest reported waiting time for one NHS trust and specialty from My Planned Care.' It clearly distinguishes this tool from wait_time_trend by noting the trust is identified by name here rather than by RTT provider code.

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 explicitly contrasts this tool with wait_time_trend, stating that lookup_wait_time uses the trust name while wait_time_trend uses an RTT provider code. This gives the agent a concrete basis for choosing between the two alternatives.

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

rank_trusts_by_waitA

Rank NHS trusts by their latest waiting time for a specialty (longest first), using My Planned Care weekly data. Provide the specialty; optionally restrict to a region and cap the number of trusts returned. Trusts that publish the specialty but no wait figure are listed after the ranked ones, so coverage gaps are visible rather than hidden.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
regionNo
specialtyYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.4/5.0
Behavior4/5

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

With no annotations, the description must carry behavioral disclosure, and it does: it reveals the ordering, the optional filters, and the important edge-case behavior that trusts without figures are listed after ranked ones. It does not mention read-only status or availability constraints, but for a data-query tool the stated behavior is substantively transparent.

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?

Two sentences contain the core purpose, data source, ordering, optional parameters, and an edge-case behavior with zero filler. The statement is front-loaded with the action and resource.

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?

For a ranking tool with an output schema, the description is largely complete: it explains the data source, ordering, filters, and gap behavior. Minor details like the unit of waiting time or whether limit applies to gap-listed trusts are not stated, but an agent can invoke the tool correctly from this description.

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?

The schema has 0% parameter coverage, so the description must compensate, and it maps all three parameters: specialty is the required filter, region restricts geography, and limit caps the number of returned trusts. It does not enumerate valid specialty/region values, but it conveys the role of each parameter beyond the bare 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?

The description names a specific action ('Rank NHS trusts by their latest waiting time for a specialty'), specifies ordering ('longest first'), and identifies the data source. This clearly differentiates it from siblings like wait_time_trend or lookup_wait_time, which are point/trend lookups rather than cross-trust rankings.

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 states the use case clearly—comparing trusts across a specialty and optionally filtering by region or count. It does not explicitly name sibling alternatives or say when not to use it, but the ranking purpose and data source give enough context for an agent to select it over lookup/trend tools.

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

trust_profileA

Build a combined profile for one NHS trust and specialty, joining its current wait (My Planned Care), waiting-time trend (RTT), and CQC quality rating. Identify the trust by RTT provider code (e.g. 'RGT') or trust name (e.g. 'Guy's and St Thomas''); set by_name=true when passing a name. Each section is null when that source holds no data. If the trust is not in the identity mapping, returns found=false.

ParametersJSON Schema
NameRequiredDescriptionDefault
by_nameNo
specialtyYes
identifierYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.2/5.0
Behavior4/5

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

With no annotations, the description carries the behavioral disclosure burden and does disclose key edge cases: sections are null when a source has no data and found=false when the trust isn't in the identity mapping. It does not mention any side effects, auth, or rate limits, but for a read/composite tool these may be less critical; output schema can cover return details.

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 sentences, no filler: purpose first, then identity parameters, then fallback/null behavior. Every sentence adds a distinct piece of knowledge an agent needs.

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?

The core behavior, identity resolution, nullable sections, and not-found case are all covered, and an output schema exists for return shapes. The main remaining gap is valid specialty values, but the description is otherwise sufficient for correct tool 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?

Schema coverage is 0%, so the description must compensate. It explains identifier as an RTT provider code or trust name and defines by_name=true for names, but specialty is only implied by context with no accepted values, format, or examples, leaving one required parameter underspecified.

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 composite verb+resource: builds a combined profile for one NHS trust and specialty, joining three named sources. This clearly differentiates it from siblings like wait_time_trend and get_trust_rating, which presumably cover a single source.

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 establishes clear context for when to use it — when current wait, RTT trend, and CQC rating are needed together. It also gives conditional guidance for identifier mode via by_name, but doesn't explicitly name sibling alternatives for single-source queries, so no exclusions are stated.

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

wait_time_trendA

Summarise how the waiting time for a given NHS trust and specialty has moved over time, using NHS England RTT monthly data. Waits are in weeks. Provide the provider code (e.g. 'RGT') and specialty (e.g. 'Cardiology'). Returns the start and end values, the change in weeks, the percentage change, a direction (improving | worsening | flat), and the full monthly series. If no data is held for that trust/specialty, returns found=false; do not invent a trend in that case.

ParametersJSON Schema
NameRequiredDescriptionDefault
specialtyYes
provider_codeYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.7/5.0
Behavior5/5

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

With no annotations provided, the description carries the full behavioral disclosure burden and does an excellent job. It discloses the output return fields (start/end values, change, percentage, direction, full monthly series), the units (weeks), and the found=false edge case, explicitly instructing not to invent a trend when data is absent.

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 yet information-dense: purpose, units, input guidance, output summary, and edge-case handling are all included in three sentences. Every sentence earns its place and no filler exists.

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 modest complexity, an output schema, and no annotations, the description is complete. It covers the data source, input semantics, units, expected return values, and the missing-data behavior, so an agent has everything needed to invoke it correctly and interpret results appropriately.

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 0%, so the description must compensate for both parameters. It does by explaining that provider_code is an NHS trust code with an example ('RGT') and specialty is a clinical specialty with an example ('Cardiology'), giving an agent enough semantic grounding to call the tool correctly.

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 states a specific verb ('Summarise') and a specific resource ('waiting time for a given NHS trust and specialty... moved over time'), which distinguishes it from sibling tools like lookup_wait_time or rank_trusts_by_wait. It also previews concrete outputs, leaving no ambiguity about what the tool does.

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 clearly implies when to call this tool: when a trend summary over time is needed, rather than a point lookup or ranking. It gives concrete input requirements (provider code, specialty) and an explicit no-data behavior, but 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.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 5 tool updatesv0.1.0
    • First observedget_trust_rating
    • First observedlookup_wait_time
    • First observedrank_trusts_by_wait
    • First observedtrust_profile
    • First observedwait_time_trend

TDQS

A4.4/5.0

Scored across 5 tools

Disambiguation5/5

Each tool targets a clearly distinct query: single-trust trend, single-trust latest wait, cross-trust ranking, quality rating, and combined profile. The descriptions explicitly call out different data sources and identity keys, so an agent should not misselect.

Naming Consistency3/5

Three tools use a verb-first pattern (lookup_, rank_, get_), but wait_time_trend and trust_profile are noun phrases, so the set lacks a single consistent convention. The names are still readable and specific, but the pattern is mixed.

Tool Count5/5

Five tools is a well-scoped size for an NHS intelligence read-only server. Each tool covers a distinct query need without redundancy or bloat.

Completeness5/5

The surface covers current waiting times, historical trends, cross-trust ranking, quality ratings, and an integrated profile joining those sources. Because trust_profile accepts either an RTT code or a trust name, it also bridges the identifier gap, so there are no dead-end lookup paths.

Maintenance

ActivitySlowing
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    B
    maintenance
    Enables querying of current A\&E waiting times, specialist outpatient waiting times, and general outpatient clinic quotas in Hong Kong using natural language through MCP.
    3
    20 PyPI
    4
    MIT
  • F
    license
    A
    quality
    D
    maintenance
    Enables AI assistants to query NHS public health datasets, including prescribing data, dataset exploration, and organisation lookup via the NHSBSA Open Data Portal.
    9
    -
  • A
    license
    Not graded
    quality
    B
    maintenance
    MCP server for the Semble practice-management API, enabling AI agents to search for patients, contacts, and users, as well as retrieve patient relationships via read-only tools.
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    Enables querying the Polish National Health Fund (NFZ) public API for medical waiting lists and service dictionary, allowing AI to compare wait times and find providers.
    3
    MIT