Skip to content

Repository files navigation

who-sentinel-mcp

Python 3.10+ MCP License: MIT Code style: ruff

A small Model Context Protocol server that lets an LLM ask grounded questions about WHO public-health data: indicator timeseries from the Global Health Observatory (GHO) and recent stories from Disease Outbreak News (DON).

Not affiliated with the World Health Organization. This is an independent open-source project that consumes WHO's public APIs. WHO content is used under CC BY 4.0 and every tool response carries an attribution line.

An MCP host calls who-sentinel-mcp tools over stdio; the server caches and rate-limits requests to WHO GHO, WHO DON, and HDX HAPI (INFORM Risk Index) and returns JSON with a CC BY 4.0 attribution line.

Why

Asking an LLM about an outbreak in country X tends to produce confident-sounding case counts and stale baselines. This server gives the model a small, opinionated set of tools so it can:

  • look up an indicator code instead of guessing one,
  • pull the country's actual GHO timeseries,
  • compare the latest value against a prior-years baseline,
  • surface recent DON items with a real public URL,
  • pull regex/heuristic case-and-CFR hints out of DON narratives — with confidence flags so the model knows when not to quote them,
  • read the published INFORM Risk Index for a country (UN OCHA / EC JRC, via HDX HAPI) instead of inventing a composite.

Intended for research, teaching, and desk analysis.

Install

Requires uv and Python 3.10+ (the repo pins 3.11 via .python-version).

uv sync

Run

uv run who-sentinel-mcp

The process speaks MCP over stdio, so don't run it interactively in a terminal — point an MCP host at it.

Cursor / Claude Desktop / etc.

{
  "mcpServers": {
    "who-sentinel": {
      "command": "uv",
      "args": ["run", "who-sentinel-mcp"],
      "cwd": "/absolute/path/to/who-sentinel-mcp"
    }
  }
}

Docker

docker build -t who-sentinel-mcp .
docker run -i --rm who-sentinel-mcp

Tools

Tool What it does
search_gho_indicators Find IndicatorCode values by keyword.
list_gho_countries Full WHO RegionCountry table, optional substring filter.
resolve_gho_country Resolve a free-text country / ISO3 to a RegionCountry row.
list_gho_indicator_dimensions Dimensions for one indicator (e.g. COUNTRY, YEAR).
list_gho_entity_sets Browse the GHO /api catalog (~3000 entity sets).
get_latest_outbreaks Recent DON items, optional disease keyword filter.
get_full_report Full DON record by Id, plus public_url.
extract_outbreak_metadata Regex/heuristic case & CFR hints from DON text.
surveillance_synthesis DON narrative + GHO baseline for one disease/country. Refuses by default if the picked IndicatorCode shares no keywords with the disease query (code_validation); pass confirm_indicator=true to override.
compare_gho_countries Same indicator across two countries.
country_risk_index Latest INFORM Risk Index scores (UN OCHA / EC JRC, via HDX HAPI) for a country.
get_server_limits Effective cache TTLs, rate-limit budget, in-process metrics.

Resources (for agent context):

  • who-sentinel://docs/gho-basics
  • who-sentinel://docs/limitations
  • who-sentinel://docs/trust-and-use

Prompt: who_sentinel_workflow — a short suggested workflow for agents.

Configuration

Variable Default Meaning
WHO_SENTINEL_CACHE_TTL 86400 GHO series / indicator cache TTL (seconds).
WHO_SENTINEL_COUNTRY_REGISTRY_TTL 604800 TTL for the RegionCountry + /api catalog.
WHO_SENTINEL_LOG_LEVEL WARNING Stdlib log level. DEBUG includes Python tracebacks in tool error payloads.
WHO_SENTINEL_MAX_HTTP_PER_MINUTE 120 Token-bucket cap on outbound GETs. 0 = unlimited.
WHO_SENTINEL_GHO_BASE https://ghoapi.azureedge.net/api GHO OData base URL.
WHO_SENTINEL_DON_BASE https://www.who.int/api/news/diseaseoutbreaknews DON OData base URL.
WHO_SENTINEL_WHO_WEB_BASE https://www.who.int Base used when building DON public_urls.
WHO_SENTINEL_HDX_HAPI_BASE https://hapi.humdata.org HDX HAPI base URL for country_risk_index.
WHO_SENTINEL_HDX_APP_ID (unset) Required for country_risk_index. Generate one at the HAPI sandbox.

GETs retry on 408, 429, 502, 503, 504 with exponential backoff and respect Retry-After.

How surveillance_synthesis thinks

  1. Resolve the country via resolve_gho_country / list_gho_countries.
  2. If indicator_code is omitted, the response carries indicator_candidates (curated hints first, then live GHO search) so the model can pick one and call back.
  3. With an indicator_code, the default baseline is latest year vs the mean of up to 10 prior years in that GHO series. Override with prior_years_for_baseline (1–20) and/or baseline_latest_year to anchor the "latest" point.
  4. The latest block surfaces gho_last_updated, period_begin/period_end, and value_low / value_high when WHO publishes them.
  5. DON excerpts include a real public_url (https://www.who.int + ItemDefaultUrl).
  6. Every payload carries who_sentinel_meta.disclaimer next to the CC BY attribution line.

Limitations

  • GHO uses per-indicator entity sets. surveillance_synthesis adds a code_validation field and refuses by default when the IndicatorName shares no keywords with the disease query, but a high-confidence pick can still be wrong — code_provenance shows where the code came from; verify via search_gho_indicators and list_gho_indicator_dimensions.
  • Disease hints come from data/disease_hints.json — a small editorial overlay merged with an auto-generated snapshot of the live GHO Indicator catalog (refreshed weekly by scripts/refresh_disease_hints.py). Still starting points, not authoritative.
  • DON country matching is text-based. We expand each country into pycountry names + an alias overlay (e.g. DRC, Burma, Côte d'Ivoire), and ISO3 codes use word boundaries, but narratives can still use subnational place names.
  • extract_outbreak_metadata uses regex heuristics. Inspect confidence and cfr_source (explicit_text vs derived_or_none) before quoting numbers.
  • country_risk_index is a thin passthrough of the published INFORM Risk Index (CC BY 4.0); we don't compute composites of our own. Set WHO_SENTINEL_HDX_APP_ID to enable it.

Development

uv sync --all-groups
uv run ruff check .
uv run pytest

CI runs uv sync --locked, ruff, and pytest. Integration-style tests use mocked HTTP only — no live WHO calls in CI.

License

Code is released under the MIT License. WHO data is used under CC BY 4.0; see the attribution line prefixed on every tool response.

About

An MCP server and tools for WHO GHO, Disease Outbreak News, and the INFORM Risk Index.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages