mcpField
C
cdc-health-mcp-server

cdc-health-mcp-server

Remote
github.com/cyanheadsHealth5Updated 2w ago
Repository

About cdc-health-mcp-server

An MCP server for exploring CDC public health data, aimed at researchers and analysts. It combines searchable Socrata datasets and queryable CDC WONDER mortality statistics with schema and catalog tools.

Key features

  1. 01Search CDC dataset catalog
  2. 02Inspect dataset schemas and metadata
  3. 03Query datasets with SoQL
  4. 04Retrieve CDC WONDER mortality statistics
  5. 05Access catalog resources and analysis prompt

Use cases

  1. 01Find datasets on vaccination or surveillance
  2. 02Analyze mortality by year and demographic group
  3. 03Filter and aggregate CDC dataset records

MCP support

Exposes five tools, two resources, and an analysis prompt to MCP clients. It supports STDIO and Streamable HTTP, including a public hosted endpoint.

Configuration

Remote servers need no local install. Pick your client, then copy the config or install in one click.

Endpointhttps://cdc.caseyjhand.com/mcp
Copy install command
Claude CodeTerminal
Cursor.cursor/mcp.json
VS Code.vscode/mcp.json
Claude Desktopclaude_desktop_config.json
Windsurf~/.codeium/windsurf/mcp_config.json

Run commands in a terminal; paste JSON into the client’s MCP config and restart. Servers that need sign-in will prompt on first connect.

Packages
npm@cyanheads/cdc-health-mcp-server0.10.0

Tools

5
ParameterTypeRequiredDescription
tagsarrayNoFilter by domain tags (e.g., ["covid19", "surveillance"]). Tags widen the search instead of narrowing it — a dataset matches when it carries any one of them, so every tag added returns more results, and an unrecognized tag matches nothing and leaves the result set unchanged. Values match the catalog's own tag vocabulary, case-insensitively; call cdc_list_catalog_vocabulary for the values in use with their entry counts, or read the tags field on any result. To narrow, combine tags with query or category, which intersect with the tag set.
limitintegerNoResults to return (default 10). One call returns at most 100: a larger limit, up to 10,000, is capped at 100, and the response says so and gives the offset to continue from while more datasets match. offset plus limit must not exceed 10000 once limit is capped.
orderenumNoResult ordering. "dataset_id" (default) sorts deterministically by each dataset's unique catalog ID — required for stable offset pagination, since consecutive pages form a gap-free, duplicate-free traversal. "relevance" returns best-match ranking for keyword search but is not stably paginable across pages, so walking offsets can skip or repeat datasets.dataset_id | relevance
querystringNoFull-text search across dataset names and descriptions (e.g., "diabetes mortality", "lead exposure children").
domainenumNoCDC Socrata host to search. "data.cdc.gov" (default) and "chronicdata.cdc.gov" front the same catalog and return the same entries, so switching hosts neither widens nor narrows a search — chronic-disease and small-area collections such as PLACES, the Heart Disease & Stroke Atlas, and Environmental Public Health Tracking are found from either.data.cdc.gov | chronicdata.cdc.gov
offsetintegerNoPagination offset for browsing beyond first page (max 9999). offset plus limit must not exceed 10000 once limit is capped; both CDC portals hold well under two thousand entries, so offsets near that ceiling page past the end of the catalog.
categorystringNoFilter by domain category (e.g., "NNDSS", "Vaccinations", "Behavioral Risk Factors"). Values come from the catalog's own vocabulary and are matched exactly, including case — "Vaccinations" matches 89 entries while "Vaccination" matches none. Call cdc_list_catalog_vocabulary for every value with its entry count rather than guessing at one.

Details

From the project README

@cyanheads/cdc-health-mcp-server

Search and query CDC public health data — mortality, vaccinations, surveillance, behavioral risk (Socrata SODA API) via MCP. STDIO or Streamable HTTP.

5 Tools • 2 Resources • 1 Prompt

Version License Docker MCP SDK npm TypeScript Bun

Install in Claude Desktop Install in Cursor Install in VS Code

Framework

Public Hosted Server: https://cdc.caseyjhand.com/mcp


Overview

CDC public health data from the CDC Open Data portal and CDC WONDER. Search 1,000+ datasets on vaccination, surveillance, and behavioral risk, inspect their schemas and query them with SoQL, or pull national mortality statistics by year, age, sex, and race.

Tools
ToolDescription
cdc_discover_datasetsSearch the CDC dataset catalog by keyword, category, or tag
cdc_get_dataset_schemaFetch column schema, row count, and metadata for a dataset
cdc_list_catalog_vocabularyList the catalog's category and tag values with their entry counts
cdc_query_datasetExecute SoQL queries — filter, aggregate, sort, full-text search, select fields
cdc_query_wonderQuery CDC WONDER for national mortality, population, and death rates across five databases
Resources
ResourceDescription
cdc://datasetsTop 50 most-viewed catalog entries, for orientation
cdc://datasets/{datasetId}Dataset metadata and the first 100 columns for a specific dataset

Both resources mirror data also reachable via cdc_discover_datasets and cdc_get_dataset_schema, for clients that surface resources but not tools.

Prompts
PromptDescription
analyze_health_trendGuided workflow for investigating a public health question across CDC data

Capability reference

cdc_discover_datasets tool
  • Filters: query, category, and tags. Up to 100 results per page (default 10); offset + limit is capped at 10,000 (page_out_of_range past it). order is dataset_id (default, stable paging) or relevance
  • Results carry assetType, columnCount (0 marks a chart, map, or other non-tabular asset), an 8-name columnSample, and a description cut to 300 characters, plus totalCount and appliedFilters
  • When a category or tags value matches nothing, the notice names the closest catalog values with their entry counts, e.g. Vaccination → "Vaccinations" (89 datasets)

cdc_get_dataset_schema tool
  • Takes a four-by-four datasetId (e.g. bi63-dtpu). column_limit (default 100) and column_offset page wide schemas, reporting totalCount, truncated, and nextOffset
  • The dataset description is capped at 4,000 characters by default (descriptionTruncated and descriptionLength are set when cut); full_description: true returns the whole text
  • Columns carry fieldName, dataType, and description. rowCountSource says whether rowCount is live or Socrata's cached figure. A non-tabular asset fails with not_queryable

cdc_list_catalog_vocabulary tool
  • Every category comes back whole; the ~1,600 tags are ranked by entry count and paged with tag_limit (default 50) and tag_offset. filter (3+ characters) narrows both by word match, not fuzzy matching
  • Each value carries datasetCount; the response also reports vocabularySize, categoryCount, tagCount, truncated, nextOffset, and truncationCeiling (an upper bound on the counts of the tags after the page)

cdc_query_dataset tool
  • Clauses: select, where, group, having, order, and full-text search. Up to 5,000 rows per call (default 100), offset up to 1,000,000
  • For stable offset paging, set an order ending in a unique tie-breaker (:id on ungrouped rows, the grouped columns on a grouped query); the notice says so when it is missing
  • effectiveQuery echoes the SoQL clauses as sent; truncated and nextOffset report paging, with no totalCount. A chart or map ID fails with not_queryable

cdc_query_wonder tool
databaseCDC databaseYearsRace groupsmcd_icd10
underlying_1999_2020 (default)D76 — Underlying Cause of Death1999–20204 bridged—
provisionalD176 — Provisional Mortality Statistics2018 → current year6 single-raceyes
underlying_2018_2024D158 — Underlying Cause of Death, Single Race2018–20246 single-race—
multiple_1999_2020D77 — Multiple Cause of Death1999–20204 bridgedyes
multiple_2018_2024D157 — Multiple Cause of Death, Single Race2018–20246 single-raceyes
  • group_by takes 1–4 of year, age_group, sex, race (national only). cause_icd10 and mcd_icd10 take an ICD-10 code, a range (X40-X49), or a list of up to 50. age_groups takes NS (age not stated) alone or with all eleven known groups. limit and offset (max 10,000) page the table
  • Rows carry deaths, population, crude_rate, and age_adjusted_rate where age can be standardized. Cells CDC returns as Suppressed, Unreliable, or Not Applicable read null and are listed in cellNotes; messages reports rows CDC hid, and totalCount is exact
  • CDC rejects requests less than 15 seconds apart, so calls are queued one at a time and spaced 16 seconds apart

cdc://datasets resource
  • Top 50 catalog entries by popularity, each with id, name, assetType, category, columnCount, and updatedAt, plus the catalog totalCount
  • columnCount: 0 marks a non-tabular entry; cdc_discover_datasets searches and pages the full catalog

cdc://datasets/{datasetId} resource
  • Dataset metadata plus the first 100 columns as application/json, with columnCount and truncated; the description is capped at 4,000 characters
  • For more columns or the full description, use cdc_get_dataset_schema with column_offset or full_description: true

analyze_health_trend prompt
  • Arguments: topic required; timeRange and geography optional
  • Returns one user message that routes the question to cdc_query_wonder (national mortality) or the Socrata tools (everything else), then walks discover → inspect → baseline → compare → synthesize

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.

CDC-specific:

  • The Socrata SODA API v2.1 over the CDC Open Data portal (~1,080 datasets); no auth required, and an optional app token raises rate limits
  • CDC WONDER mortality data from five databases covering 1999 through the current year, reached over its XML request API
  • The three Socrata tools take a domain input, limited to data.cdc.gov (default) and chronicdata.cdc.gov; both serve the same catalog
  • category and tags must match the catalog's own values (categories case-sensitively, tags case-insensitively); cdc_list_catalog_vocabulary lists them
  • Socrata returns every value as a string, and a column like year is numeric in some datasets and text in others. Match WHERE literals to the column's dataType: numbers bare, strings single-quoted

Agent-friendly output:

  • Paging is reported explicitly: totalCount, truncated, nextOffset, and shown/cap. Both query tools cap each page at 200,000 characters, so a wide page can end short of limit
  • Typed errors with a recovery hint on every declared reason, such as not_queryable, page_out_of_range, and invalid_query
  • Upstream gaps stay visible: WONDER status tokens in cellNotes, hidden-row notices in messages, and rowCountSource on schema row counts
  • effectiveQuery echoes the SoQL clauses or a WONDER query summary, so a result can be reproduced

Getting started

Public Hosted Instance

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

{
  "mcpServers": {
    "cdc-health-mcp-server": {
      "type": "streamable-http",
      "url": "https://cdc.caseyjhand.com/mcp"
    }
  }
}
Self-Hosted / Local

Add the following to your MCP client configuration file.

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

Or with npx (no Bun required):

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

Or with Docker:

{
  "mcpServers": {
    "cdc-health-mcp-server": {
      "type": "stdio",
      "command": "docker",
      "args": ["run", "-i", "--rm", "-e", "MCP_TRANSPORT_TYPE=stdio", "ghcr.io/cyanheads/cdc-health-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
Installation
  1. Clone the repository:
git clone https://github.com/cyanheads/cdc-health-mcp-server.git
  1. Navigate into the directory:
cd cdc-health-mcp-server
  1. Install dependencies:
bun install
  1. Configure environment:
cp .env.example .env
# optionally set CDC_APP_TOKEN

Configuration

VariableDescriptionDefault
CDC_APP_TOKENSocrata app token; raises rate limits.none
CDC_BASE_URLSODA host for requests with no domain (the cdc://datasets/{datasetId} resource).https://data.cdc.gov
CDC_CATALOG_URLSocrata Discovery API base URL.https://api.us.socrata.com/api/catalog/v1
MCP_TRANSPORT_TYPETransport: stdio or http.stdio
MCP_HTTP_PORTHTTP server port.3010
MCP_SESSION_MODEHTTP session mode: stateless, stateful, or auto.stateless
MCP_AUTH_MODEAuthentication: none, jwt, or oauth.none
MCP_LOG_LEVELLog level (debug, info, warning, error, etc.).info
OTEL_ENABLEDEnable OpenTelemetry.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 cdc-health-mcp-server .
docker run --rm -p 3010:3010 cdc-health-mcp-server

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

Project structure

DirectoryPurpose
src/index.tscreateApp() entry point — registers tools/resources/prompts and inits services.
src/configServer-specific environment variable parsing and validation with Zod.
src/mcp-server/toolsTool definitions (*.tool.ts). Four Socrata tools and one WONDER tool.
src/mcp-server/resourcesResource definitions. Catalog overview and dataset detail.
src/mcp-server/promptsPrompt definitions. Health trend analysis workflow.
src/services/socrataSocrata service — catalog search, vocabularies, metadata, SoQL queries.
src/services/wonderCDC WONDER service — XML request builder, response parser, request spacing.
src/utilsShared helpers — HTML-to-text, table-cell escaping, vocabulary matching, response budget.
tests/Unit and integration tests mirroring src/.

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 in src/index.ts
  • 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.

Comments

Markdown supported

New to MCP?

From what the protocol is to installing your first server, these answers cover most first questions.

An open protocol that defines how AI applications connect to external tools and data in a uniform way. Clients talk to the model; MCP servers provide tools, resources and prompt templates. They exchange standard messages, so one server can be reused by many clients.