A clean interface to the WHO Global Health Observatory's 3,059 health indicators across 194 member states. You get six tools that handle the full query workflow: search indicators by keyword, fetch metadata to see which dimensions an indicator supports, then pull actual data rows with filters for country, region, year, and sex. The server wraps the WHO GHO OData API and handles things like pagination limits, uncertainty intervals, and filter validation. Runs via stdio locally or connects to a public hosted instance at who-gho.caseyjhand.com. Built on the mcp-ts-core framework, so it includes structured error recovery and works identically in Claude Desktop, Cursor, or any MCP client. Reach for this when you need programmatic access to comparative health statistics without manually parsing WHO's web interface.
Query WHO Global Health Observatory data — 3,059 indicators across 194 member states with country, region, year, and sex filters via MCP. STDIO or Streamable HTTP.
6 tools for working with WHO Global Health Observatory data:
| 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 supported filter dimensions for up to 10 codes |
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 |
who_search_indicatorsSearch the WHO GHO indicator catalog by keyword.
"life expectancy", "immunization", "mortality", "diabetes", or "HIV"who_query_indicator_datawho_list_indicatorsBrowse the full indicator catalog with offset-based pagination.
limit (default 50, max 500) and offsettotal and hasMore for iterationwho_get_indicator_metadataFetch metadata for one to ten indicator codes in a single call.
COUNTRY, SEX, REGION, AGEGROUP)who_query_indicator_data to confirm which filter dimensions are validnotFound rather than raising an errorwho_list_dimensionsList all dimension type codes available in the GHO API.
COUNTRY, REGION, SEX, WORLDBANKINCOMEGROUP, AGEGROUPwho_list_dimension_valueswho_list_dimension_valuesList valid filter values for a single dimension type.
parentCode, parentLabel, parentDimension)who_query_indicator_datawho_query_indicator_dataQuery data rows for a single WHO GHO indicator.
country_codes (ISO 3166-1 alpha-3), region_codes (WHO regions), or income_group_codes (World Bank groups)year_from / year_toSEX_BTSX (both), SEX_FMLE, SEX_MLE — only applies when the indicator uses SEX as its first cross-cutting dimensiondim1_value for indicators using non-SEX cross-cutting dimensionslow/high) via include_uncertainty (default true)totalRows and truncated for handling large result sets| Type | URI | Description |
|---|---|---|
| Resource | who://indicator/{indicatorCode}/metadata | Indicator name and supported filter dimensions for a single code |
| Resource | who://dimension/{dimensionCode}/values | All valid values for a dimension type |
who_search_indicators — find indicator codes by keywordwho_get_indicator_metadata — confirm which filter dimensions the indicator supportswho_query_indicator_data — fetch data with country/region/year/sex filtersTo look up filter codes: who_list_dimensions → who_list_dimension_values.
Built on @cyanheads/mcp-ts-core:
none, jwt, oauth)in-memory, filesystem, Supabase, Cloudflare KV/R2/D1WHO GHO-specific:
Agent-friendly output:
truncated, truncatedNote, hasMore) so agents can decide whether to paginaterecovery hints on every failure pathAdd 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
git clone https://github.com/cyanheads/who-gho-mcp-server.git
cd who-gho-mcp-server
bun install
All configuration is validated at startup via Zod schemas in src/config/server-config.ts. Key environment variables:
| 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_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 | HTTP request timeout in milliseconds | 30000 |
OTEL_ENABLED | Enable OpenTelemetry | false |
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
| Directory | Purpose |
|---|---|
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/config | Server-specific environment variable parsing and validation with Zod. |
tests/ | Unit and integration tests, mirroring the src/ structure. |
See CLAUDE.md for development guidelines and architectural rules. The short version:
try/catch in tool logicctx.log for logging, ctx.state for storagecreateApp() arraysIssues and pull requests are welcome. Run checks and tests before submitting:
bun run devcheck
bun run test
This project is licensed under the Apache 2.0 License. See the LICENSE file for details.
MCP_LOG_LEVELdefault: infoSets the minimum log level for output (e.g., 'debug', 'info', 'warn').
MCP_HTTP_HOSTdefault: 127.0.0.1The hostname for the HTTP server.
MCP_HTTP_PORTdefault: 3010The port to run the HTTP server on.
MCP_HTTP_ENDPOINT_PATHdefault: /mcpThe endpoint path for the MCP server.
MCP_AUTH_MODEdefault: noneAuthentication mode to use: 'none', 'jwt', or 'oauth'.