Skip to main content
Glama
cyanheads

@cyanheads/who-gho-mcp-server

by cyanheads

Version License Docker MCP SDK npm TypeScript Bun

Install in Claude Desktop Install in Cursor Install in VS Code

Framework

Public Hosted Server: https://who-gho.caseyjhand.com/mcp


Overview

Global health statistics from the WHO Global Health Observatory: 3,102 indicators across 194 member states. Search indicators and query data by country, region, income group, sex, and year.

Tools

Tool

Description

who_search_indicators

Search the GHO indicator catalog by keyword in indicator names

who_list_indicators

Browse the full indicator catalog with pagination

who_get_indicator_metadata

Fetch indicator names and dimension types, processing 10 codes per call with continuation for larger batches

who_list_dimensions

List all dimension type codes available in the GHO API

who_list_dimension_values

List valid codes and labels for a dimension type (COUNTRY, REGION, SEX, etc.)

who_query_indicator_data

Query data rows for an indicator with spatial, temporal, and dimension filters

Resources

Resource

Description

who://indicator/{indicatorCode}/metadata

Indicator name and supported filter dimensions for a single code

who://dimension/{dimensionCode}/values

First 100 values for a dimension type

who://dimension/{dimensionCode}/values{?limit,offset}

One explicit page of a dimension type's values

who://dimension/{dimensionCode}/values{?limit,offset,parentCode}

One explicit page, narrowed to a parent code

Each mirrors data also reachable via who_get_indicator_metadata and who_list_dimension_values — useful for clients that inject resources as context but don't call tools.

Agent skill

who-gho-guide covers dimension-position discovery, complete country comparisons, and countries versus regional aggregates. It ships with plugin installs, npm, Docker, and the MCPB bundle. MCP clients can discover its SKILL.md through resources/list or the io.modelcontextprotocol/skills extension (skills/list, skills/get, and resources/directory/read); the server also exposes the skill://{+path} resource template.

Related MCP server: unicefstats-mcp

Capability reference

who_search_indicators tool

  • Each whitespace-separated word must match a substring in the indicator name, in any order; no stemming or fuzzy expansion. If names have no matches, an exact indicator-code lookup is attempted.

  • Returns indicator codes and display names for use with who_query_indicator_data

  • Offset-based pagination (offset, default 0) with limit default 20, max 100; reports totalCount, hasMore, pageInfo, nextOffset

  • An offset at or beyond totalCount returns an empty page; a no_results error is raised only when nothing matches at all


who_list_indicators tool

  • No keyword required — browse the 3,102-indicator catalog

  • Offset-based pagination via limit (default 50, max 500) and offset

  • Returns totalCount and hasMore for iteration


who_get_indicator_metadata tool

  • Accepts up to 1,000 indicator codes and processes the first 10 in parallel; submit returned unprocessedCodes next. With GHO_CLAMP_LIMITS=false, batches over 10 are rejected.

  • Returns the full indicator name and supported dimension types (e.g. COUNTRY, SEX, REGION, AGEGROUP) for each resolved code

  • Indicators with no dimension listing upstream return dimensions: [] plus a dimensionsNote pointing at a sample data row's dimension type/value pairs. Metadata does not identify dimension positions.

  • Codes resolving to neither a catalog entry nor dimension rows land in notFound; the call fails when no processed code resolves and no unprocessed codes remain


who_list_dimensions tool

  • No inputs — returns every dimension type code and human-readable title in the GHO catalog

  • Common types: COUNTRY, REGION, SEX, WORLDBANKINCOMEGROUP, AGEGROUP

  • Use to discover codes before calling who_list_dimension_values


who_list_dimension_values tool

  • Returns codes and labels for the dimension's values (e.g. the 234 country entries, the 43 WHO region codes), plus optional parent-hierarchy fields (parentCode, parentLabel, parentDimension)

  • parent_code narrows hierarchical dimensions — dimension: "COUNTRY" with parent_code: "EUR" returns the 58 countries in the WHO European Region

  • Deterministic ordering by Code; offset-based pagination (offset) with limit default 100, max 500 — GHO (3,103 values) and DHSMICSGEOREGION (4,932) need paging

  • A parent_code that matches nothing returns an empty page for a known dimension; unknown dimensions fail even with a parent filter

  • An unpaired UTF-16 surrogate in dimension fails as a typed malformed_identifier validation error


who_query_indicator_data tool

  • Spatial filters are mutually exclusive per call: country_codes (WHO country codes, including historical entries), region_codes (WHO aggregate rows), or income_group_codes (World Bank aggregate rows) — supplying more than one is a validation error

  • year_from / year_to time range; sex (SEX_BTSX, SEX_FMLE, SEX_MLE) applies only when the indicator's first cross-cutting dimension is SEX. dim1_value, dim2_value, and dim3_value select observed positional values; discover positions from returned type/value pairs, not metadata. sex overrides dim1_value with a notice.

  • include_uncertainty (default true) adds low/high bounds; sort (year_desc default or year_asc) with a total row ordering so paging never repeats or drops rows

  • Offset-based pagination with limit default 200, max 1000; reports totalRows, hasMore, pageInfo, nextOffset

  • Typed failure reasons: indicator_not_found, no_data, ambiguous_spatial_filter, invalid_year_range, invalid_query, malformed_identifier


who://indicator/{indicatorCode}/metadata resource

  • Indicator name and supported filter dimensions as application/json

  • indicatorCode comes from who_search_indicators or who_list_indicators

  • Empty dimensions carries a dimensionsNote when the upstream dimension table lists none for the code, rather than reporting a missing indicator

  • Returns a 404 error only when the code resolves to neither a catalog name nor any dimension rows


who://dimension/{dimensionCode}/values resource

  • Bare URI returns the first 100 values for the dimension (dimensionCode from who_list_dimensions), as application/json

  • Registered separately from the two paged variants below because the MCP SDK's RFC 6570 matcher treats every URI query variable as required — one template cannot serve both a bare and a paged form

  • An unfiltered empty result means the dimension code does not exist


who://dimension/{dimensionCode}/values{?limit,offset} resource

  • limit (1–500) and offset must both be present in the URI — the query variables are required, not optional

  • Same page fields as the bare URI: totalCount, hasMore, nextOffset, and an optional notice

  • An offset at or beyond totalCount returns an empty page, not an error


who://dimension/{dimensionCode}/values{?limit,offset,parentCode} resource

  • Adds parentCode to narrow to one parent value, e.g. parentCode="EUR" for countries in the WHO European Region; limit, offset, and parentCode must all be present in the URI

  • A parentCode that matches nothing returns an empty page for a known dimension; unknown dimensions fail even with a parent filter

  • Same output shape as the bare and paged resources: dimension, values, totalCount, hasMore, nextOffset, notice

Features

Built on @cyanheads/mcp-ts-core: stdio and Streamable HTTP transports, pluggable auth (none / jwt / oauth), swappable storage (in-memory, filesystem, Supabase, Cloudflare KV/R2/D1), structured logging with optional OpenTelemetry tracing.

WHO GHO-specific:

  • Full coverage of the WHO GHO OData API v2 — indicators, dimensions, dimension values, and data queries

  • Configurable base URL and service-operation deadline (GHO_BASE_URL, GHO_REQUEST_TIMEOUT_MS) for custom or mirrored deployments

  • Parallel metadata fan-out for multi-code indicator lookups

  • Deterministic, total row/value ordering — pagination never repeats or drops rows across pages

Agent-friendly output:

  • Tool descriptions encode the cross-tool workflow — agents discover the right call order (search → metadata → query) from descriptions alone

  • Structured pagination signaling (hasMore, nextOffset, pageInfo, and truncated on the data-query tool) so agents can decide whether to page further

  • Discriminated, typed error reasons with a recovery hint on every failure path

  • Distinct empty-page vs. not-found semantics — paging past the end, an unmatched filter, and a genuinely missing code each report differently instead of colliding into one generic empty result

Getting started

Public Hosted Instance

A public instance is available at https://who-gho.caseyjhand.com/mcp — no installation required. Point any MCP client at it via Streamable HTTP:

{
  "mcpServers": {
    "who-gho-mcp-server": {
      "type": "streamable-http",
      "url": "https://who-gho.caseyjhand.com/mcp"
    }
  }
}

Self-Hosted / Local

Add the following to your MCP client configuration file.

{
  "mcpServers": {
    "who-gho-mcp-server": {
      "type": "stdio",
      "command": "bunx",
      "args": ["@cyanheads/who-gho-mcp-server@latest"],
      "env": {
        "MCP_TRANSPORT_TYPE": "stdio",
        "MCP_LOG_LEVEL": "info"
      }
    }
  }
}

Or with npx (no Bun required):

{
  "mcpServers": {
    "who-gho-mcp-server": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@cyanheads/who-gho-mcp-server@latest"],
      "env": {
        "MCP_TRANSPORT_TYPE": "stdio",
        "MCP_LOG_LEVEL": "info"
      }
    }
  }
}

Or with Docker:

{
  "mcpServers": {
    "who-gho-mcp-server": {
      "type": "stdio",
      "command": "docker",
      "args": ["run", "-i", "--rm", "-e", "MCP_TRANSPORT_TYPE=stdio", "ghcr.io/cyanheads/who-gho-mcp-server:latest"]
    }
  }
}

For Streamable HTTP, set the transport and start the server:

MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 bun run start:http
# Server listens at http://localhost:3010/mcp

Prerequisites

  • Bun v1.4.0 or higher (or Node.js ≥24).

  • No API key required — the WHO GHO API is public.

Installation

  1. Clone the repository:

git clone https://github.com/cyanheads/who-gho-mcp-server.git
  1. Navigate into the directory:

cd who-gho-mcp-server
  1. Install dependencies:

bun install
  1. Configure environment:

cp .env.example .env
# edit .env and set optional overrides

Configuration

Variable

Description

Default

MCP_TRANSPORT_TYPE

Transport: stdio or http

stdio

MCP_HTTP_PORT

HTTP server port

3010

MCP_HTTP_ENDPOINT_PATH

HTTP endpoint path where the MCP server is mounted

/mcp

MCP_SESSION_MODE

HTTP session posture: stateless, stateful, or auto. No tool asks the caller for input mid-handler, so the server declares stateless; set this only to override.

stateless

MCP_PUBLIC_URL

Public origin override for TLS-terminating reverse-proxy deployments

none

MCP_AUTH_MODE

Authentication: none, jwt, or oauth

none

MCP_LOG_LEVEL

Log level (debug, info, warning, error, etc.)

info

MCP_GC_PRESSURE_INTERVAL_MS

Opt-in Bun-only forced-GC pressure loop (ms). Try 60000 if RSS grows under sustained HTTP load.

0 (disabled)

LOGS_DIR

Directory for log files (Node.js only)

<project-root>/logs

STORAGE_PROVIDER_TYPE

Storage backend: in-memory, filesystem, supabase, cloudflare-kv/r2/d1

in-memory

GHO_BASE_URL

WHO GHO OData API base URL (override for custom/mirrored deployments)

https://ghoapi.azureedge.net/api/

GHO_REQUEST_TIMEOUT_MS

Service-operation deadline in milliseconds, covering requests, body reads, retries, and backoff

30000

GHO_CLAMP_LIMITS

Clamp positive integer page limits to 100 for search, 500 for indicator/dimension browsing, and 1,000 for data queries, with a notice. Metadata processes 10 entries and returns continuation. false restores advertised maxima and rejection of oversized requests.

true

OTEL_ENABLED

Enable OpenTelemetry

false

OTEL_EXPORTER_OTLP_ENDPOINT

OTLP base URL; traces and metrics export to /v1/traces and /v1/metrics under it. Log export is opt-in through OTEL_EXPORTER_OTLP_LOGS_ENDPOINT.

none

LOG_TOOL_FAILURE_PAYLOADS

Log each failed tool call's arguments and result (key-name redaction only)

false

See .env.example for the full list of optional overrides.

Running the server

Local development

  • Build and run the production version:

    # One-time build
    bun run rebuild
    
    # Run the built server
    bun run start:http
    # or
    bun run start:stdio
  • Run checks and tests:

    bun run devcheck  # Lints, formats, type-checks, and more
    bun run test      # Runs the test suite

Docker

docker build -t who-gho-mcp-server .
docker run --rm -p 3010:3010 who-gho-mcp-server

The Dockerfile defaults to HTTP transport, stateless session mode, and logs to /var/log/who-gho-mcp-server. OpenTelemetry peer dependencies are installed by default — build with --build-arg OTEL_ENABLED=false to omit them.

Project structure

Directory

Purpose

src/index.ts

createApp() entry point — registers tools/resources and inits the GHO service.

src/config

Server-specific environment variable parsing and validation with Zod.

src/mcp-server/tools

Tool definitions (*.tool.ts). Six tools across indicator discovery, dimension lookup, and data queries.

src/mcp-server/resources

Resource definitions. Indicator metadata and dimension values resources.

src/services/gho

WHO GHO OData API service layer — HTTP client, query builder, types.

src/utils

wellFormed() — repairs unpaired UTF-16 surrogates in caller-supplied strings before they reach output, enrichment, or failure data.

tests/

Unit and integration tests, mirroring the src/ structure.

Development guide

See CLAUDE.md for development guidelines and architectural rules. The short version:

  • Handlers throw, framework catches — no try/catch in tool logic

  • Use ctx.log for logging, ctx.state for storage

  • Register new tools and resources in the createApp() arrays

  • Wrap external API calls: validate raw → normalize to domain type → return output schema; never fabricate missing fields

Contributing

Issues are welcome. Run checks and tests before submitting:

bun run devcheck
bun run test

License

Apache-2.0 — see LICENSE for details.

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    D
    maintenance
    Provides access to the World Health Organization's Global Health Observatory data, enabling AI assistants to search, retrieve, and analyze comprehensive health indicators, country statistics, disease burden data, and regional health trends through WHO's OData API.
    1
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    MCP server for UNICEF child development statistics. Query 790+ child-focused indicators across 200+ countries with disaggregations by sex, age, wealth quintile, and residence. No API key required.
    9
    81 PyPI
    7
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    A Model Context Protocol (MCP) server that gives AI assistants direct access to the World Health Organization's Global Health Observatory (GHO) for comparative health systems research.
    15
    13 PyPI
    MIT