cdc-health-mcp-server
Server Details
Search and query CDC public health data — mortality, vaccinations, surveillance, behavioral risk.
- Status
- Healthy
- Last Tested
- Transport
- Streamable HTTP
- URL
- Repository
- cyanheads/cdc-health-mcp-server
- GitHub Stars
- 5
- Server Listing
- cdc-health-mcp-server
TDQS
Scored across 4 tools
The tools form a clean pipeline: discover_datasets finds IDs, get_dataset_schema inspects columns, query_dataset fetches data. cdc_query_wonder is explicitly distinguished as a separate CDC system with its own inputs, so no tool overlaps with another.
All four tools use a consistent cdc_ prefix with snake_case verb_noun structure (discover_datasets, get_dataset_schema, query_dataset, query_wonder). The pattern is predictable and self-describing.
Four tools is well-scoped for a CDC data-access server, and each earns its place: catalog discovery, schema inspection, dataset querying, and WONDER mortality querying. Nothing is redundant or missing from the count.
The surface covers the full discover→inspect→query lifecycle for Socrata datasets plus a dedicated WONDER path, with descriptions addressing auth-free access, paging, and edge cases. Minor gaps exist (e.g. no explicit category listing or export), but agents can work around them via search.
Available Tools
4 toolscdc_discover_datasetsCdc Discover DatasetsARead-onlyInspect
Search the CDC dataset catalog by keyword, category, or tag. Returns IDs, names, truncated descriptions, asset types, column counts, and update timestamps. The catalog also holds charts, maps, stories, files, and links; an entry whose columnCount is 0 is one of those and yields no data from the other tools. Use cdc_get_dataset_schema for the full column list of a chosen dataset.
| Name | Required | Description | Default |
|---|---|---|---|
| tags | No | Filter 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; the tags field on each result shows which values are in use. To narrow, combine tags with query or category, which intersect with the tag set. | |
| limit | No | Results to return (default 10, max 100). offset plus limit must not exceed 10000. | |
| order | No | Result 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 |
| query | No | Full-text search across dataset names and descriptions (e.g., "diabetes mortality", "lead exposure children"). | |
| domain | No | CDC 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 |
| offset | No | Pagination offset for browsing beyond first page (max 9999). offset plus limit must not exceed 10000; both CDC portals hold well under two thousand entries, so offsets near that ceiling page past the end of the catalog. | |
| category | No | Filter by domain category (e.g., "NNDSS", "Vaccinations", "Behavioral Risk Factors"). |
Output Schema
| Name | Required | Description |
|---|---|---|
| error | No | Present when the call failed. Absent on success. |
| notice | No | Guidance when the page came back empty — how to broaden a search that matched nothing, where to check tag values when a tag filter was applied, or the size of the result set when the offset ran past its end. |
| datasets | No | Matching datasets. |
| totalCount | No | Total matching datasets in the catalog (for pagination). |
| appliedFilters | No | Filters applied to this query; absent fields indicate no filter on that dimension. Query, category, and tags intersect with each other, but multiple tags union. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only provide readOnlyHint=true; the description adds important context about the catalog containing non-dataset assets and how to interpret columnCount=0. It also discloses that descriptions are truncated. This goes beyond the annotation without contradicting it.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three focused sentences: the first states purpose and returns, the second clarifies the columnCount nuance, and the third points to the schema tool. Every sentence earns its place, and the key information is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the output schema and 100% parameter coverage, the description provides sufficient context: it explains the return fields, the meaning of columnCount=0, and the relationship to sibling tools. The user has all necessary information to call this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
All 7 parameters have thorough schema descriptions (100% coverage). The description only paraphrases the search capability (keyword, category, tag) and adds no additional semantic detail beyond what the schema already provides. Baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states the action (search), the resource (CDC dataset catalog), and the method (by keyword, category, or tag). It also describes what is returned and explicitly notes that entries with columnCount 0 are not datasets, distinguishing it from the data-retrieval siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description says to use cdc_get_dataset_schema for full column lists and notes that columnCount 0 entries yield no data from other tools, implying when to use this discovery tool versus the data tools. It does not explicitly mention when to use cdc_query_dataset, but the intent is clear enough.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
cdc_get_dataset_schemaCdc Get Dataset SchemaARead-onlyInspect
Fetch the column schema for a CDC dataset — names, data types, descriptions, row count, and last-updated timestamp. Returns the first 100 columns by default; wide datasets continue via column_offset. Get dataset IDs from cdc_discover_datasets.
| Name | Required | Description | Default |
|---|---|---|---|
| domain | No | CDC Socrata host to fetch the dataset from. "data.cdc.gov" (default) and "chronicdata.cdc.gov" front the same catalog, so a four-by-four ID resolves on either and the default works whichever host the dataset was found on. | data.cdc.gov |
| datasetId | Yes | Four-by-four dataset identifier (e.g., "bi63-dtpu"). Obtain from cdc_discover_datasets. | |
| column_limit | No | Columns to return in this call (default 100, max 500). Every dataset under the default arrives whole; past it the response reports totalCount and a nextOffset to pass back as column_offset. Raise this to pull a wide schema in one call. | |
| column_offset | No | Index of the first column to return, for continuing past a previous call (default 0). Columns keep the order the dataset declares, so column_offset plus column_limit walks the schema without gaps or repeats. An offset at or past the column count returns an empty window rather than an error. |
Output Schema
| Name | Required | Description |
|---|---|---|
| cap | No | The column_limit that bounded this response. |
| name | No | Dataset display name from the catalog (e.g., "Provisional COVID-19 Deaths by Sex and Age"). |
| error | No | Present when the call failed. Absent on success. |
| shown | No | Number of columns returned in this response. |
| notice | No | Guidance when the response is a subset of the schema — which columns it covers, how to reach the rest, or that column_offset ran past the end. |
| columns | No | The requested window of dataset columns, with full types and descriptions. Bounded by column_limit/column_offset; the enrichment fields say how the window sits in the whole schema. |
| rowCount | No | Total number of rows when reported by upstream; omitted when unknown. |
| truncated | No | True when the returned columns are a subset of the schema. Absent means every column of the dataset is in this response. |
| updatedAt | No | Last data update timestamp when provided. |
| nextOffset | No | Value to pass as column_offset on the next call to continue after the last column returned. Present only when columns remain beyond this window. |
| totalCount | No | Total columns in the dataset schema, before column_limit/column_offset. |
| description | No | Dataset description when provided. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Even with readOnlyHint=true, the description discloses useful behavior beyond the annotation: it returns the first 100 columns by default and supports continuation via column_offset. It also mentions row count and timestamp details. It does not go into edge-case behavior, but the annotation already covers the safe, read-only nature.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two tight sentences with no wasted words. The what (fetch schema) is front-loaded, supported by return contents, then the pagination caveat and ID source are given in a logical order.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only, single-resource metadata tool, the description plus richly annotated schema covers what the tool does, how to paginate, where to get the required datasetId, and what the response includes. The output schema exists as well, so nothing is missing for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description adds a little cross-parameter context by connecting pagination to wide datasets, but the individual parameter descriptions already thoroughly explain defaults, offsets, and limits, so the description itself adds limited new meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: it fetches the column schema for a CDC dataset, and enumerates exactly what is returned (names, data types, descriptions, row count, last-updated timestamp). This clearly differentiates it from the sibling tools, especially cdc_query_dataset, which is about querying data rather than metadata.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear usage context by saying dataset IDs come from cdc_discover_datasets, which establishes the correct workflow. It does not explicitly name cdc_query_dataset as the alternative when row-level data is needed, but the schema-fetching purpose makes the choice reasonably unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
cdc_query_datasetCdc Query DatasetARead-onlyInspect
Execute a SoQL query against any CDC dataset. Supports filtering, aggregation, sorting, full-text search, and field selection. Use cdc_discover_datasets to find dataset IDs and cdc_get_dataset_schema to inspect columns before querying.
| Name | Required | Description | Default |
|---|---|---|---|
| group | No | SoQL GROUP BY clause. Requires aggregate functions in select. | |
| limit | No | Max rows to return (default 100, max 5000). Fewer come back when the page would cross the 200,000-character response budget; the response says so and gives a nextOffset to resume from. | |
| order | No | SoQL ORDER BY clause. Field name with optional ASC/DESC: "total_deaths DESC". Set one whenever paging with offset: SODA does not order results implicitly, so consecutive offsets without a deterministic order can skip or repeat rows. When the dataset has no natural unique column, Socrata's documented minimum tie-breaker is the system field `:id`, present on every dataset — order=":id". | |
| where | No | SoQL WHERE clause. Strings must be single-quoted: "state='California' AND year=2020". If a column name matches a SoQL keyword (group, select, where, order, limit, offset, having, search), wrap it in backticks: "`group`='By Year'". | |
| domain | No | CDC Socrata host to query. "data.cdc.gov" (default) and "chronicdata.cdc.gov" front the same catalog, so a four-by-four ID returns the same rows from either and the default works whichever host the dataset was found on. | data.cdc.gov |
| having | No | SoQL HAVING clause. Filters aggregated results. | |
| offset | No | Row offset for pagination (max 1,000,000). Pair with a deterministic order clause — an offset walk over unordered results can skip or repeat rows. | |
| search | No | Full-text search across all text columns. For precise filtering use the where parameter instead. | |
| select | No | SoQL SELECT clause — column names, aliases, or aggregates: "state, sum(deaths) as total_deaths". Omit for all columns. To enumerate distinct values of a column, set select to "{column}, count(*) as count" with group="{column}" and order="count DESC". | |
| datasetId | Yes | Four-by-four dataset identifier (e.g., "bi63-dtpu"). Obtain from cdc_discover_datasets. |
Output Schema
| Name | Required | Description |
|---|---|---|
| cap | No | The requested limit that bounded this response. |
| rows | No | Result rows with requested fields. Most values are strings (including numbers/dates); geo columns return GeoJSON objects. |
| error | No | Present when the call failed. Absent on success. |
| shown | No | Number of rows returned in this response. |
| notice | No | Guidance when no rows matched, when further rows remain, or when the response budget cut the page short — how to verify filters, resume paging, or broaden the query. |
| rowCount | No | Number of rows returned in this response. |
| truncated | No | True when rows exist beyond the ones returned, established by fetching one row more than the limit rather than inferred from the row count. Absent means this response is the complete remainder of the result set. |
| nextOffset | No | Offset to pass on the next call to resume immediately after the last row returned. Present only when further rows exist and the resume point is within the offset ceiling; a deterministic order clause is what makes the walk gap-free. |
| effectiveQuery | No | The SoQL clauses sent to Socrata, as `$clause=value` pairs joined by "&". Values read exactly as they were supplied — not URL-encoded — so a clause can be copied back into the matching parameter of another call. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
readOnlyHint=true already covers the safety profile, so the description does not need to state that this is a read operation. The main prose adds scope and capability context but does not directly disclose behaviors like response-budget truncation or the need for deterministic ordering; those details are present in the parameter descriptions rather than the main description.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three purposeful sentences: the first states the action and resource, the second summarizes query capabilities, and the third names the prerequisite sibling tools. It is front-loaded and contains no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex SoQL tool with 10 parameters, the definition is exceptionally complete. The schema covers defaults, limits, keyword backticks, deterministic pagination, response-budget behavior, domain equivalence, and a distinct-value recipe, while the output schema covers return structure and the description connects the prerequisite discovery/schema tools.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3 even without further narrative in the main description. The description's capability list loosely maps to parameters like where, group, order, search, and select, but it does not add substantive meaning beyond what the schema already explains.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Execute a SoQL query against any CDC dataset.' It also enumerates capabilities—filtering, aggregation, sorting, full-text search, and field selection—so the agent knows exactly what the tool does and can distinguish it from dataset discovery and schema inspection tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly points to cdc_discover_datasets for finding dataset IDs and cdc_get_dataset_schema for inspecting columns before querying, giving a clear workflow. It does not explicitly contrast with cdc_query_wonder, but the naming and SoQL focus make the choice reasonably clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
cdc_query_wonderCdc Query WonderARead-onlyInspect
Query CDC WONDER for national US mortality statistics — deaths, population, and crude/age-adjusted death rates — across its five mortality databases, selected with the database input: final underlying-cause data for 1999–2020 (the default) or 2018–2024, provisional data running from 2018 through the current year, and two multiple-cause databases covering the same two eras. Break results out by year, age group, sex, and/or race, and filter by ICD-10 cause of death, sex, age group, or year range; on a multiple-cause database, mcd_icd10 additionally matches a cause listed anywhere on the death certificate rather than only the one certified as underlying. Each database holds a different span of years (1999–2026 across all of them) and a request whose year_range falls outside the selected one's span is rejected with that span named. WONDER is a separate CDC system from the Socrata datasets the other cdc_* tools query. Data is national only — sub-national (state/county) breakdowns are not available through the API (CDC vital-statistics policy). Cause of death is a filter, not a grouping. Some measure cells come back as a CDC status token rather than a number — "Suppressed" (withheld for confidentiality), "Unreliable" (a rate from fewer than 20 deaths), or "Not Applicable" (no population denominator); those cells read null in rows and each one is listed in cellNotes with its token. CDC also drops whole rows before sending the table — strata with zero deaths, and strata whose death count is suppressed — so a stratum can be missing from rows entirely; messages carries CDC's statement whenever that happened. The whole table comes back by default; a broad grouping can run past a thousand rows, so set limit to take it a page at a time and follow the nextOffset the response reports. Paging shapes the response only — WONDER is asked once either way, and the figures, caveats and hidden-row notices are the same on every page. CDC rejects requests made less than 15 seconds apart across all five databases, so consecutive calls are spaced automatically and a follow-up call may wait about 16 seconds before it runs.
| Name | Required | Description | Default |
|---|---|---|---|
| sex | No | Filter by sex. | all |
| limit | No | Rows to return from the table CDC sent (1–5000). Omit to return the whole table. WONDER's request carries no limit of its own, so this pages a table already fetched in full rather than narrowing the query: the deaths, rates, caveats and hidden-row notices are the same whichever page is read. A four-dimension grouping can run past a thousand rows, so set this and follow nextOffset to walk them. | |
| offset | No | Index of the first row to return, for continuing past a previous call (default 0, max 10,000). Rows keep the order CDC returned them in, which is stable for a given query, so offset plus limit walks the table without gaps or repeats. An offset at or past the row total returns an empty page rather than an error. | |
| database | No | Which WONDER mortality database to query. "underlying_1999_2020" (D76) is final data for 1999–2020 and the default. "provisional" (D176) runs 2018 through the current year, updated weekly, and returns the most recent years labelled e.g. "2025 (provisional)". "underlying_2018_2024" (D158) is settled — not provisional — data for 2018–2024. "multiple_1999_2020" (D77) and "multiple_2018_2024" (D157) record every cause listed on the death certificate; without an mcd_icd10 filter they return the same figures as the underlying-cause database for the same era, so pick one only to use that filter. The two 1999–2020 databases report race in CDC's four bridged groups; the other three use the six single-race groups — figures broken out by race are not comparable between the two families. | underlying_1999_2020 |
| group_by | No | Dimensions to break results out by (1–4), in output-column order — e.g. ["year"], ["year","sex"], ["age_group","race"]. Results are always national. Cause of death is a filter (cause_icd10), not a grouping. "race" resolves to whichever race vocabulary the selected database uses — four bridged groups (Asian and Pacific Islander combined) on the 1999–2020 databases, six single-race groups plus a multiracial category on the others — so a race series from one family cannot be spliced onto one from the other. | |
| mcd_icd10 | No | Filter to deaths with this ICD-10 code recorded anywhere on the death certificate, whether or not it was the underlying cause — e.g. "died with a respiratory condition listed", a population no underlying-cause query can produce. Valid only when database is "multiple_1999_2020", "multiple_2018_2024", or "provisional"; the other databases record only the underlying cause and reject it. "999--999", the withheld-cause marker described under cause_icd10, is offered here too but only by "provisional". Combines with cause_icd10, which keeps meaning the underlying cause. Omit for all causes. | |
| age_groups | No | Restrict to deaths in any of the listed age groups — e.g. ["25-34","35-44"] covers both. "1" is the under-1-year group. "NS" is the group CDC puts a death in when the age was not recorded; it is not covered by any of the ten-year groups, so a filter listing all eleven of those still leaves those deaths out and returns fewer deaths than the same query unfiltered. List "NS" alongside them to match an unfiltered total, or on its own to count them. Omit for all ages, which includes them. | |
| year_range | No | Inclusive year range. These bounds span every database (1999–2026); the years the selected one actually holds are narrower, and a range outside them is rejected with that database's span named. Omit for all years the database holds. | |
| cause_icd10 | No | Filter to a specific ICD-10 underlying cause of death — the single condition CDC certified as having started the chain of events leading to death. Omit for all causes. Accepted by every database. "999--999" is not an ICD-10 code but CDC's own marker for deaths whose cause it is still withholding under the provisional database's six-month reporting lag; it counts that backlog, and only the "provisional" database offers it. |
Output Schema
| Name | Required | Description |
|---|---|---|
| cap | No | The requested limit that bounded this response. |
| rows | No | Result rows. Each carries the requested group-by dimensions plus deaths, population, crude_rate, and age_adjusted_rate (per 100,000) when age standardization is possible — it is omitted when age_group is a grouping dimension or age_groups selects a single group. Dimension values are CDC's own labels with only surrounding whitespace removed, so the same year keys identically across databases; nothing inside a label is changed, and on the provisional database a year reads "2025 (provisional)" or "2026 (provisional and partial)" rather than a bare year. A measure cell CDC returned as a status token instead of a number is null here; cellNotes names the cell and the token. When limit or offset is set these are one page of the table CDC sent, in its order; totalCount says how many rows the whole table holds. |
| error | No | Present when the call failed. Absent on success. |
| shown | No | Number of rows returned in this response. |
| notice | No | Guidance when no rows matched, when the returned rows are a page of a larger table or the offset ran past it, and a note when CDC returned a status token in place of a measure value. |
| caveats | No | CDC-provided caveats and footnotes: data revisions, population-estimate sources, suppression and rate-reliability rules. They describe the whole table CDC assembled, so they come back complete on every page rather than scoped to the rows returned. |
| database | No | WONDER dataset code the rows came from — e.g. "D76", "D176", "D157". |
| messages | No | Notices CDC attached to this table, verbatim. The ones that matter say rows were withheld before the table was sent — "Rows with zero Deaths are hidden." and "Rows with suppressed Deaths are hidden." A withheld row is absent from rows entirely, with nothing in the table marking the gap, so while this array is non-empty a stratum missing from rows may have been dropped rather than unobserved, and any count, ranking, or completeness claim drawn from rows is partial. These describe the whole table, so they come back complete on every page. Empty when CDC withheld no rows. |
| rowCount | No | Number of rows returned in this response — the page size when limit or offset is set. |
| cellNotes | No | One entry per measure cell CDC returned as a status token rather than a number, covering the rows in this response only. Those cells read null in rows, so this is what tells a withheld value apart from an unreliable one or a genuinely absent one. |
| truncated | No | True when rows remain past the ones returned. Absent means this response runs to the end of the table, which is also the case for an offset past it. |
| nextOffset | No | Offset to pass on the next call to resume immediately after the last row returned. Present only when further rows remain. |
| totalCount | No | Rows in the whole table CDC returned, before limit/offset. Exact rather than estimated — the table is parsed in full before a page is taken from it. |
| databaseTitle | No | CDC's own title for that database, e.g. "Underlying Cause of Death, 1999-2020". Names the era and record type the rows describe, so a result read on its own is self-describing. |
| effectiveQuery | No | Human-readable summary of the grouping and filters sent to WONDER. |
| suppressedCount | No | How many cellNotes carry the "Suppressed" token — cells CDC withheld for confidentiality. Counted over the rows in this response, so it tracks the page rather than the whole table. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations indicate readOnlyHint, but the description goes far beyond by detailing response behavior (paging, hidden rows, cellNotes, nextOffset), the impact of rate limiting, and database-specific quirks (e.g., race vocabulary mismatch, withheld-cause markers).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Though lengthy, every sentence carries essential information for a complex tool. The description is logically organized (purpose, data scope, paging, rate limits) and avoids redundancy, justified by the tool's many interacting parameters and quirks.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the output schema exists, the description adequately covers all aspects: input parameters, response shape (mentions rows, nextOffset, messages, cellNotes), and operational constraints. It leaves no gaps for an agent to understand how to call and interpret results.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, and the description enriches every parameter with nuanced semantics, such as how limit affects the already-fetched table, how NS age groups interact with filters, and the difference between underlying and multiple cause filters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Query), resource (CDC WONDER), and clearly distinguishes from siblings by focusing on national mortality statistics and explicitly noting it is a separate CDC system from the Socrata datasets used by other cdc_* tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit usage guidance: contrasts with other CDC tools, explains when to use each database (underlying vs provisional vs multiple), and gives practical advice on paging with limit/offset and the automatic spacing of calls.
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.
4 tool updates
- Changed
cdc_discover_datasets6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "datasets", + "totalCount", + "appliedFilters" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded value: +{ + "additionalProperties": {}, + "description": "Present when the call failed. Absent on success.", + "properties": { + "code": { + "description": "JSON-RPC error code for this failure.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "data": { + "additionalProperties": {}, + "properties": { + "reason": { + "description": "Machine-readable failure mode. Declared by this tool: `rate_limited`: Socrata API returns 429 Too Many Requests. `dataset_not_found`: Socrata returned 404 for the catalog endpoint itself — the Discovery API address is wrong or the service moved. `access_denied`: Socrata returned 403 — the catalog refused this request rather than failing to serve it. `upstream_error`: Socrata catalog API returned a 5xx server error. `page_out_of_range`: offset plus limit exceeds 10000, which Socrata's catalog rejects outright. `invalid_query`: Catalog API returned 400 — typically a malformed query or invalid filter value. Other values are possible when a failure originates below the handler.", + "examples": [ + "rate_limited", + "dataset_not_found", + "access_denied", + "upstream_error", + "page_out_of_range", + "invalid_query" + ], + "type": "string" + }, + "recovery": { + "additionalProperties": {}, + "description": "Actionable next step for the caller.", + "properties": { + "hint": { + "type": "string" + } + }, + "required": [ + "hint" + ], + "type": "object" + }, + "retryable": { + "description": "Whether retrying may succeed.", + "type": "boolean" + } + }, + "type": "object" + }, + "message": { + "description": "Human-readable description of what went wrong.", + "type": "string" + } + }, + "required": [ + "code", + "message" + ], + "type": "object" +} - removed
Output schema / requiredRemoved value: -[ - "datasets", - "totalCount", - "appliedFilters" -]
- Changed
cdc_get_dataset_schema6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "name", + "columns", + "totalCount" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded value: +{ + "additionalProperties": {}, + "description": "Present when the call failed. Absent on success.", + "properties": { + "code": { + "description": "JSON-RPC error code for this failure.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "data": { + "additionalProperties": {}, + "properties": { + "reason": { + "description": "Machine-readable failure mode. Declared by this tool: `dataset_not_found`: Dataset ID does not exist or has been retired. `not_queryable`: The ID names a catalog asset with no columns — a chart, map, story, file, or external link rather than a tabular dataset. `access_denied`: Socrata returned 403 — the asset is not readable through this endpoint or access is restricted. `invalid_query`: Socrata rejected the metadata request with a 400. `rate_limited`: Socrata API returns 429 Too Many Requests. `upstream_error`: Socrata metadata API returned a 5xx server error. Other values are possible when a failure originates below the handler.", + "examples": [ + "dataset_not_found", + "not_queryable", + "access_denied", + "invalid_query", + "rate_limited", + "upstream_error" + ], + "type": "string" + }, + "recovery": { + "additionalProperties": {}, + "description": "Actionable next step for the caller.", + "properties": { + "hint": { + "type": "string" + } + }, + "required": [ + "hint" + ], + "type": "object" + }, + "retryable": { + "description": "Whether retrying may succeed.", + "type": "boolean" + } + }, + "type": "object" + }, + "message": { + "description": "Human-readable description of what went wrong.", + "type": "string" + } + }, + "required": [ + "code", + "message" + ], + "type": "object" +} - removed
Output schema / requiredRemoved value: -[ - "name", - "columns", - "totalCount" -]
- Changed
cdc_query_dataset6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "rows", + "rowCount", + "effectiveQuery" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded value: +{ + "additionalProperties": {}, + "description": "Present when the call failed. Absent on success.", + "properties": { + "code": { + "description": "JSON-RPC error code for this failure.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "data": { + "additionalProperties": {}, + "properties": { + "reason": { + "description": "Machine-readable failure mode. Declared by this tool: `dataset_not_found`: Dataset ID does not exist or has been retired. `no_such_column`: WHERE/SELECT/GROUP/ORDER references a column that does not exist on this dataset. `type_mismatch`: Filter value type does not match the column data type (e.g., quoting a number). `invalid_query`: Socrata rejected the SoQL query for other syntax or semantic reasons. `access_denied`: Socrata returned 403 — typically an ID naming a chart, map, story, file, or external link rather than a tabular dataset. `rate_limited`: Socrata API returns 429 Too Many Requests. `upstream_error`: Socrata data API returned a 5xx server error. Other values are possible when a failure originates below the handler.", + "examples": [ + "dataset_not_found", + "no_such_column", + "type_mismatch", + "invalid_query", + "access_denied", + "rate_limited", + "upstream_error" + ], + "type": "string" + }, + "recovery": { + "additionalProperties": {}, + "description": "Actionable next step for the caller.", + "properties": { + "hint": { + "type": "string" + } + }, + "required": [ + "hint" + ], + "type": "object" + }, + "retryable": { + "description": "Whether retrying may succeed.", + "type": "boolean" + } + }, + "type": "object" + }, + "message": { + "description": "Human-readable description of what went wrong.", + "type": "string" + } + }, + "required": [ + "code", + "message" + ], + "type": "object" +} - removed
Output schema / requiredRemoved value: -[ - "rows", - "rowCount", - "effectiveQuery" -]
- Changed
cdc_query_wonder6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "rows", + "rowCount", + "database", + "databaseTitle", + "caveats", + "cellNotes", + "messages", + "suppressedCount", + "effectiveQuery", + "totalCount" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded value: +{ + "additionalProperties": {}, + "description": "Present when the call failed. Absent on success.", + "properties": { + "code": { + "description": "JSON-RPC error code for this failure.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "data": { + "additionalProperties": {}, + "properties": { + "reason": { + "description": "Machine-readable failure mode. Declared by this tool: `invalid_query`: The request does not fit the selected database — a year_range outside the years it holds, mcd_icd10 against a database that records only the underlying cause, or the withheld-cause marker against one that keeps no withheld backlog — or WONDER itself rejected it, e.g. an unknown ICD-10 code or a filter/grouping combination it does not allow. `rate_limited`: A request reached WONDER less than 15 seconds after the previous response finished, and WONDER returned 429. `upstream_error`: WONDER returned an unexpected response or was unreachable. Other values are possible when a failure originates below the handler.", + "examples": [ + "invalid_query", + "rate_limited", + "upstream_error" + ], + "type": "string" + }, + "recovery": { + "additionalProperties": {}, + "description": "Actionable next step for the caller.", + "properties": { + "hint": { + "type": "string" + } + }, + "required": [ + "hint" + ], + "type": "object" + }, + "retryable": { + "description": "Whether retrying may succeed.", + "type": "boolean" + } + }, + "type": "object" + }, + "message": { + "description": "Human-readable description of what went wrong.", + "type": "string" + } + }, + "required": [ + "code", + "message" + ], + "type": "object" +} - removed
Output schema / requiredRemoved value: -[ - "rows", - "rowCount", - "database", - "databaseTitle", - "caveats", - "cellNotes", - "messages", - "suppressedCount", - "effectiveQuery", - "totalCount" -]
3 tool updates
- Changed
cdc_get_dataset_schema10 fields changed- added
Input schema / properties / column_limitAdded value: +{ + "default": 100, + "description": "Columns to return in this call (default 100, max 500). Every dataset under the default arrives whole; past it the response reports totalCount and a nextOffset to pass back as column_offset. Raise this to pull a wide schema in one call.", + "maximum": 500, + "minimum": 1, + "type": "integer" +} - added
Input schema / properties / column_offsetAdded value: +{ + "default": 0, + "description": "Index of the first column to return, for continuing past a previous call (default 0). Columns keep the order the dataset declares, so column_offset plus column_limit walks the schema without gaps or repeats. An offset at or past the column count returns an empty window rather than an error.", + "maximum": 10000, + "minimum": 0, + "type": "integer" +} - added
Output schema / properties / capAdded value: +{ + "description": "The column_limit that bounded this response.", + "type": "number" +} - changed
Output schema / properties / columns / descriptionPrevious value: -"Dataset columns with types and descriptions."New value: +"The requested window of dataset columns, with full types and descriptions. Bounded by column_limit/column_offset; the enrichment fields say how the window sits in the whole schema." - added
Output schema / properties / nextOffsetAdded value: +{ + "description": "Value to pass as column_offset on the next call to continue after the last column returned. Present only when columns remain beyond this window.", + "type": "number" +} - added
Output schema / properties / noticeAdded value: +{ + "description": "Guidance when the response is a subset of the schema — which columns it covers, how to reach the rest, or that column_offset ran past the end.", + "type": "string" +} - added
Output schema / properties / shownAdded value: +{ + "description": "Number of columns returned in this response.", + "type": "number" +} - added
Output schema / properties / totalCountAdded value: +{ + "description": "Total columns in the dataset schema, before column_limit/column_offset.", + "type": "number" +} - added
Output schema / properties / truncatedAdded value: +{ + "description": "True when the returned columns are a subset of the schema. Absent means every column of the dataset is in this response.", + "type": "boolean" +} - changed
Output schema / requiredPrevious value: -[ - "name", - "columns" -]New value: +[ + "name", + "columns", + "totalCount" +]
- Changed
cdc_query_dataset6 fields changed- changed
Input schema / properties / limit / descriptionPrevious value: -"Max rows to return (default 100, max 5000)."New value: +"Max rows to return (default 100, max 5000). Fewer come back when the page would cross the 200,000-character response budget; the response says so and gives a nextOffset to resume from." - changed
Input schema / properties / offset / descriptionPrevious value: -"Row offset for pagination (max 1,000,000)."New value: +"Row offset for pagination (max 1,000,000). Pair with a deterministic order clause — an offset walk over unordered results can skip or repeat rows." - changed
Input schema / properties / order / descriptionPrevious value: -"SoQL ORDER BY clause. Field name with optional ASC/DESC: \"total_deaths DESC\"."New value: +"SoQL ORDER BY clause. Field name with optional ASC/DESC: \"total_deaths DESC\". Set one whenever paging with offset: SODA does not order results implicitly, so consecutive offsets without a deterministic order can skip or repeat rows. When the dataset has no natural unique column, Socrata's documented minimum tie-breaker is the system field `:id`, present on every dataset — order=\":id\"." - added
Output schema / properties / nextOffsetAdded value: +{ + "description": "Offset to pass on the next call to resume immediately after the last row returned. Present only when further rows exist and the resume point is within the offset ceiling; a deterministic order clause is what makes the walk gap-free.", + "type": "number" +} - changed
Output schema / properties / notice / descriptionPrevious value: -"Guidance when no rows matched or results were truncated — how to verify filters, paginate, or broaden the query."New value: +"Guidance when no rows matched, when further rows remain, or when the response budget cut the page short — how to verify filters, resume paging, or broaden the query." - changed
Output schema / properties / truncated / descriptionPrevious value: -"True when the result row count hit the requested limit and may be incomplete."New value: +"True when rows exist beyond the ones returned, established by fetching one row more than the limit rather than inferred from the row count. Absent means this response is the complete remainder of the result set."
- Changed
cdc_query_wonder16 fields changed- added
Input schema / properties / limitAdded value: +{ + "description": "Rows to return from the table CDC sent (1–5000). Omit to return the whole table. WONDER's request carries no limit of its own, so this pages a table already fetched in full rather than narrowing the query: the deaths, rates, caveats and hidden-row notices are the same whichever page is read. A four-dimension grouping can run past a thousand rows, so set this and follow nextOffset to walk them.", + "maximum": 5000, + "minimum": 1, + "type": "integer" +} - added
Input schema / properties / offsetAdded value: +{ + "default": 0, + "description": "Index of the first row to return, for continuing past a previous call (default 0, max 10,000). Rows keep the order CDC returned them in, which is stable for a given query, so offset plus limit walks the table without gaps or repeats. An offset at or past the row total returns an empty page rather than an error.", + "maximum": 10000, + "minimum": 0, + "type": "integer" +} - added
Output schema / properties / capAdded value: +{ + "description": "The requested limit that bounded this response.", + "type": "number" +} - changed
Output schema / properties / caveats / descriptionPrevious value: -"CDC-provided caveats and footnotes: data revisions, population-estimate sources, suppression and rate-reliability rules."New value: +"CDC-provided caveats and footnotes: data revisions, population-estimate sources, suppression and rate-reliability rules. They describe the whole table CDC assembled, so they come back complete on every page rather than scoped to the rows returned." - changed
Output schema / properties / cellNotes / descriptionPrevious value: -"One entry per measure cell CDC returned as a status token rather than a number. Those cells read null in rows, so this is what tells a withheld value apart from an unreliable one or a genuinely absent one."New value: +"One entry per measure cell CDC returned as a status token rather than a number, covering the rows in this response only. Those cells read null in rows, so this is what tells a withheld value apart from an unreliable one or a genuinely absent one." - changed
Output schema / properties / cellNotes / items / properties / row / descriptionPrevious value: -"Zero-based index into rows."New value: +"Zero-based index into rows — the rows in this response, so it is relative to the page when limit or offset is set." - changed
Output schema / properties / messages / descriptionPrevious value: -"Notices CDC attached to this table, verbatim. The ones that matter say rows were withheld before the table was sent — \"Rows with zero Deaths are hidden.\" and \"Rows with suppressed Deaths are hidden.\" A withheld row is absent from rows entirely, with nothing in the table marking the gap, so while this array is non-empty a stratum missing from rows may have been dropped rather than unobserved, and any count, ranking, or completeness claim drawn from rows is partial. Empty when CDC withheld no rows."New value: +"Notices CDC attached to this table, verbatim. The ones that matter say rows were withheld before the table was sent — \"Rows with zero Deaths are hidden.\" and \"Rows with suppressed Deaths are hidden.\" A withheld row is absent from rows entirely, with nothing in the table marking the gap, so while this array is non-empty a stratum missing from rows may have been dropped rather than unobserved, and any count, ranking, or completeness claim drawn from rows is partial. These describe the whole table, so they come back complete on every page. Empty when CDC withheld no rows." - added
Output schema / properties / nextOffsetAdded value: +{ + "description": "Offset to pass on the next call to resume immediately after the last row returned. Present only when further rows remain.", + "type": "number" +} - changed
Output schema / properties / notice / descriptionPrevious value: -"Guidance when no rows matched, and a note when CDC returned a status token in place of a measure value."New value: +"Guidance when no rows matched, when the returned rows are a page of a larger table or the offset ran past it, and a note when CDC returned a status token in place of a measure value." - changed
Output schema / properties / rowCount / descriptionPrevious value: -"Number of rows returned."New value: +"Number of rows returned in this response — the page size when limit or offset is set." - changed
Output schema / properties / rows / descriptionPrevious value: -"Result rows. Each carries the requested group-by dimensions plus deaths, population, crude_rate, and age_adjusted_rate (per 100,000) when age standardization is possible — it is omitted when age_group is a grouping dimension or age_groups selects a single group. Dimension values are CDC's own labels with only surrounding whitespace removed, so the same year keys identically across databases; nothing inside a label is changed, and on the provisional database a year reads \"2025 (provisional)\" or \"2026 (provisional and partial)\" rather than a bare year. A measure cell CDC returned as a status token instead of a number is null here; cellNotes names the cell and the token."New value: +"Result rows. Each carries the requested group-by dimensions plus deaths, population, crude_rate, and age_adjusted_rate (per 100,000) when age standardization is possible — it is omitted when age_group is a grouping dimension or age_groups selects a single group. Dimension values are CDC's own labels with only surrounding whitespace removed, so the same year keys identically across databases; nothing inside a label is changed, and on the provisional database a year reads \"2025 (provisional)\" or \"2026 (provisional and partial)\" rather than a bare year. A measure cell CDC returned as a status token instead of a number is null here; cellNotes names the cell and the token. When limit or offset is set these are one page of the table CDC sent, in its order; totalCount says how many rows the whole table holds." - added
Output schema / properties / shownAdded value: +{ + "description": "Number of rows returned in this response.", + "type": "number" +} - changed
Output schema / properties / suppressedCount / descriptionPrevious value: -"How many cellNotes carry the \"Suppressed\" token — cells CDC withheld for confidentiality."New value: +"How many cellNotes carry the \"Suppressed\" token — cells CDC withheld for confidentiality. Counted over the rows in this response, so it tracks the page rather than the whole table." - added
Output schema / properties / totalCountAdded value: +{ + "description": "Rows in the whole table CDC returned, before limit/offset. Exact rather than estimated — the table is parsed in full before a page is taken from it.", + "type": "number" +} - added
Output schema / properties / truncatedAdded value: +{ + "description": "True when rows remain past the ones returned. Absent means this response runs to the end of the table, which is also the case for an offset past it.", + "type": "boolean" +} - changed
Output schema / requiredPrevious value: -[ - "rows", - "rowCount", - "database", - "databaseTitle", - "caveats", - "cellNotes", - "messages", - "suppressedCount", - "effectiveQuery" -]New value: +[ + "rows", + "rowCount", + "database", + "databaseTitle", + "caveats", + "cellNotes", + "messages", + "suppressedCount", + "effectiveQuery", + "totalCount" +]
4 tool updates
- Changed
cdc_discover_datasets9 fields changed- changed
Input schema / properties / domain / descriptionPrevious value: -"CDC Socrata portal to search. \"data.cdc.gov\" (default) is the main CDC catalog; \"chronicdata.cdc.gov\" hosts chronic-disease and small-area datasets (PLACES, the Heart Disease & Stroke Atlas, Environmental Public Health Tracking)."New value: +"CDC 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." - changed
Input schema / properties / limit / descriptionPrevious value: -"Results to return (default 10, max 100)."New value: +"Results to return (default 10, max 100). offset plus limit must not exceed 10000." - changed
Input schema / properties / offset / descriptionPrevious value: -"Pagination offset for browsing beyond first page (max 9999)."New value: +"Pagination offset for browsing beyond first page (max 9999). offset plus limit must not exceed 10000; both CDC portals hold well under two thousand entries, so offsets near that ceiling page past the end of the catalog." - changed
Input schema / properties / tags / descriptionPrevious value: -"Filter by domain tags (e.g., [\"covid19\", \"surveillance\"])."New value: +"Filter 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; the tags field on each result shows which values are in use. To narrow, combine tags with query or category, which intersect with the tag set." - changed
Output schema / properties / appliedFilters / descriptionPrevious value: -"Filters applied to this query; absent fields indicate no filter on that dimension."New value: +"Filters applied to this query; absent fields indicate no filter on that dimension. Query, category, and tags intersect with each other, but multiple tags union." - changed
Output schema / properties / appliedFilters / properties / tags / descriptionPrevious value: -"Tag filters used."New value: +"Tag filters used — a dataset matched when it carried any one of them." - added
Output schema / properties / datasets / items / properties / assetTypeAdded value: +{ + "description": "Catalog asset type as Socrata reports it — \"dataset\", \"filter\", \"chart\", \"map\", \"story\", \"file\", or \"href\". Descriptive only: \"filter\" entries carry real columns and query normally, while \"chart\" and \"map\" entries do not. Read columnCount, not this field, to decide whether an entry is queryable.", + "type": "string" +} - changed
Output schema / properties / datasets / items / properties / columnCount / descriptionPrevious value: -"Number of columns in the dataset when reported by the catalog."New value: +"Number of columns in the dataset when reported by the catalog. A count of 0 means the entry is not tabular — cdc_get_dataset_schema and cdc_query_dataset return no usable data for it." - changed
Output schema / properties / notice / descriptionPrevious value: -"Guidance when no datasets matched — echoes the applied filters and suggests how to broaden the search."New value: +"Guidance when the page came back empty — how to broaden a search that matched nothing, where to check tag values when a tag filter was applied, or the size of the result set when the offset ran past its end."
- Changed
cdc_get_dataset_schema1 field changed- changed
Input schema / properties / domain / descriptionPrevious value: -"CDC Socrata portal hosting the dataset. Use the same portal you found the dataset on via cdc_discover_datasets: \"data.cdc.gov\" (default) or \"chronicdata.cdc.gov\"."New value: +"CDC Socrata host to fetch the dataset from. \"data.cdc.gov\" (default) and \"chronicdata.cdc.gov\" front the same catalog, so a four-by-four ID resolves on either and the default works whichever host the dataset was found on."
- Changed
cdc_query_dataset2 fields changed- changed
Input schema / properties / domain / descriptionPrevious value: -"CDC Socrata portal hosting the dataset. Must match the portal the dataset lives on: \"data.cdc.gov\" (default) or \"chronicdata.cdc.gov\" (PLACES and other chronic-disease/small-area datasets)."New value: +"CDC Socrata host to query. \"data.cdc.gov\" (default) and \"chronicdata.cdc.gov\" front the same catalog, so a four-by-four ID returns the same rows from either and the default works whichever host the dataset was found on." - changed
Output schema / properties / effectiveQuery / descriptionPrevious value: -"Assembled SoQL query string sent to the Socrata API."New value: +"The SoQL clauses sent to Socrata, as `$clause=value` pairs joined by \"&\". Values read exactly as they were supplied — not URL-encoded — so a clause can be copied back into the matching parameter of another call."
- Changed
cdc_query_wonder20 fields changed- changed
Input schema / properties / age_groups / descriptionPrevious value: -"Restrict to specific ten-year age groups — e.g. [\"25-34\",\"35-44\"]. \"1\" is the under-1-year group. Omit for all ages."New value: +"Restrict to deaths in any of the listed age groups — e.g. [\"25-34\",\"35-44\"] covers both. \"1\" is the under-1-year group. \"NS\" is the group CDC puts a death in when the age was not recorded; it is not covered by any of the ten-year groups, so a filter listing all eleven of those still leaves those deaths out and returns fewer deaths than the same query unfiltered. List \"NS\" alongside them to match an unfiltered total, or on its own to count them. Omit for all ages, which includes them." - changed
Input schema / properties / age_groups / items / enumPrevious value: -[ - "1", - "1-4", - "5-14", - "15-24", - "25-34", - "35-44", - "45-54", - "55-64", - "65-74", - "75-84", - "85+" -]New value: +[ + "1", + "1-4", + "5-14", + "15-24", + "25-34", + "35-44", + "45-54", + "55-64", + "65-74", + "75-84", + "85+", + "NS" +] - changed
Input schema / properties / cause_icd10 / anyOfPrevious value: -[ - { - "const": "", - "type": "string" - }, - { - "description": "ICD-10 underlying-cause code or chapter range. Ranges must match WONDER chapter boundaries exactly (an invalid code is rejected and named in the error) — valid examples: \"A00-B99\" (infectious), \"C00-C97\" (malignant neoplasms), \"I00-I99\" (circulatory), \"J00-J98\" (respiratory), \"V01-Y89\" (external causes), or a single code like \"I21\".", - "pattern": "^[A-Z][0-9]{2}(\\.[0-9]+)?(-[A-Z][0-9]{2}(\\.[0-9]+)?)?$", - "type": "string" - } -]New value: +[ + { + "const": "", + "type": "string" + }, + { + "const": "999--999", + "type": "string" + }, + { + "description": "ICD-10 underlying-cause code or chapter range. Ranges must match WONDER chapter boundaries exactly (an invalid code is rejected and named in the error) — valid examples: \"A00-B99\" (infectious), \"C00-C97\" (malignant neoplasms), \"I00-I99\" (circulatory), \"J00-J98\" (respiratory), \"V01-Y89\" (external causes), or a single code like \"I21\".", + "pattern": "^[A-Z][0-9]{2}(\\.[0-9]+)?(-[A-Z][0-9]{2}(\\.[0-9]+)?)?$", + "type": "string" + } +] - changed
Input schema / properties / cause_icd10 / descriptionPrevious value: -"Filter to a specific ICD-10 underlying cause of death. Omit for all causes."New value: +"Filter to a specific ICD-10 underlying cause of death — the single condition CDC certified as having started the chain of events leading to death. Omit for all causes. Accepted by every database. \"999--999\" is not an ICD-10 code but CDC's own marker for deaths whose cause it is still withholding under the provisional database's six-month reporting lag; it counts that backlog, and only the \"provisional\" database offers it." - added
Input schema / properties / databaseAdded value: +{ + "default": "underlying_1999_2020", + "description": "Which WONDER mortality database to query. \"underlying_1999_2020\" (D76) is final data for 1999–2020 and the default. \"provisional\" (D176) runs 2018 through the current year, updated weekly, and returns the most recent years labelled e.g. \"2025 (provisional)\". \"underlying_2018_2024\" (D158) is settled — not provisional — data for 2018–2024. \"multiple_1999_2020\" (D77) and \"multiple_2018_2024\" (D157) record every cause listed on the death certificate; without an mcd_icd10 filter they return the same figures as the underlying-cause database for the same era, so pick one only to use that filter. The two 1999–2020 databases report race in CDC's four bridged groups; the other three use the six single-race groups — figures broken out by race are not comparable between the two families.", + "enum": [ + "underlying_1999_2020", + "provisional", + "underlying_2018_2024", + "multiple_1999_2020", + "multiple_2018_2024" + ], + "type": "string" +} - changed
Input schema / properties / group_by / descriptionPrevious value: -"Dimensions to break results out by (1–4), in output-column order — e.g. [\"year\"], [\"year\",\"sex\"], [\"age_group\",\"race\"]. Results are always national. Cause of death is a filter (cause_icd10), not a grouping."New value: +"Dimensions to break results out by (1–4), in output-column order — e.g. [\"year\"], [\"year\",\"sex\"], [\"age_group\",\"race\"]. Results are always national. Cause of death is a filter (cause_icd10), not a grouping. \"race\" resolves to whichever race vocabulary the selected database uses — four bridged groups (Asian and Pacific Islander combined) on the 1999–2020 databases, six single-race groups plus a multiracial category on the others — so a race series from one family cannot be spliced onto one from the other." - added
Input schema / properties / mcd_icd10Added value: +{ + "anyOf": [ + { + "const": "", + "type": "string" + }, + { + "const": "999--999", + "type": "string" + }, + { + "description": "ICD-10 code or chapter range, same form as cause_icd10 — e.g. \"J00-J98\" (respiratory), \"E00-E89\" (endocrine/metabolic), \"S00-T98\" (injury and poisoning, a chapter the underlying-cause finder does not list), or a single code like \"I21\".", + "pattern": "^[A-Z][0-9]{2}(\\.[0-9]+)?(-[A-Z][0-9]{2}(\\.[0-9]+)?)?$", + "type": "string" + } + ], + "description": "Filter to deaths with this ICD-10 code recorded anywhere on the death certificate, whether or not it was the underlying cause — e.g. \"died with a respiratory condition listed\", a population no underlying-cause query can produce. Valid only when database is \"multiple_1999_2020\", \"multiple_2018_2024\", or \"provisional\"; the other databases record only the underlying cause and reject it. \"999--999\", the withheld-cause marker described under cause_icd10, is offered here too but only by \"provisional\". Combines with cause_icd10, which keeps meaning the underlying cause. Omit for all causes." +} - changed
Input schema / properties / year_range / descriptionPrevious value: -"Inclusive year range within 1999–2020. Omit for all years."New value: +"Inclusive year range. These bounds span every database (1999–2026); the years the selected one actually holds are narrower, and a range outside them is rejected with that database's span named. Omit for all years the database holds." - changed
Input schema / properties / year_range / properties / from / descriptionPrevious value: -"First year (1999–2020)."New value: +"First year (1999–2026 across all databases; the selected one holds a narrower span)." - changed
Input schema / properties / year_range / properties / from / maximumPrevious value: -2020New value: +2026 - changed
Input schema / properties / year_range / properties / to / descriptionPrevious value: -"Last year (1999–2020)."New value: +"Last year (1999–2026 across all databases; the selected one holds a narrower span)." - changed
Input schema / properties / year_range / properties / to / maximumPrevious value: -2020New value: +2026 - added
Output schema / properties / cellNotesAdded value: +{ + "description": "One entry per measure cell CDC returned as a status token rather than a number. Those cells read null in rows, so this is what tells a withheld value apart from an unreliable one or a genuinely absent one.", + "items": { + "additionalProperties": false, + "description": "One flagged measure cell: where it is and what CDC put there.", + "properties": { + "column": { + "description": "Measure column whose numeric value the token replaced.", + "type": "string" + }, + "row": { + "description": "Zero-based index into rows.", + "type": "number" + }, + "token": { + "description": "Token CDC returned in place of a number: \"Suppressed\" (withheld for confidentiality, fewer than 10 persons), \"Unreliable\" (rate from fewer than 20 deaths — published, not withheld), or \"Not Applicable\" (no population denominator).", + "type": "string" + } + }, + "required": [ + "row", + "column", + "token" + ], + "type": "object" + }, + "type": "array" +} - changed
Output schema / properties / database / descriptionPrevious value: -"WONDER database queried (D76 — Underlying Cause of Death, 1999–2020)."New value: +"WONDER dataset code the rows came from — e.g. \"D76\", \"D176\", \"D157\"." - added
Output schema / properties / databaseTitleAdded value: +{ + "description": "CDC's own title for that database, e.g. \"Underlying Cause of Death, 1999-2020\". Names the era and record type the rows describe, so a result read on its own is self-describing.", + "type": "string" +} - added
Output schema / properties / messagesAdded value: +{ + "description": "Notices CDC attached to this table, verbatim. The ones that matter say rows were withheld before the table was sent — \"Rows with zero Deaths are hidden.\" and \"Rows with suppressed Deaths are hidden.\" A withheld row is absent from rows entirely, with nothing in the table marking the gap, so while this array is non-empty a stratum missing from rows may have been dropped rather than unobserved, and any count, ranking, or completeness claim drawn from rows is partial. Empty when CDC withheld no rows.", + "items": { + "type": "string" + }, + "type": "array" +} - changed
Output schema / properties / notice / descriptionPrevious value: -"Guidance when no rows matched, or a note that CDC suppressed some cells."New value: +"Guidance when no rows matched, and a note when CDC returned a status token in place of a measure value." - changed
Output schema / properties / rows / descriptionPrevious value: -"Result rows. Each carries the requested group-by dimensions plus deaths, population, crude_rate, and — unless grouped by age_group — age_adjusted_rate (per 100,000). Suppressed measure cells (< 10 deaths) are null."New value: +"Result rows. Each carries the requested group-by dimensions plus deaths, population, crude_rate, and age_adjusted_rate (per 100,000) when age standardization is possible — it is omitted when age_group is a grouping dimension or age_groups selects a single group. Dimension values are CDC's own labels with only surrounding whitespace removed, so the same year keys identically across databases; nothing inside a label is changed, and on the provisional database a year reads \"2025 (provisional)\" or \"2026 (provisional and partial)\" rather than a bare year. A measure cell CDC returned as a status token instead of a number is null here; cellNotes names the cell and the token." - changed
Output schema / properties / suppressedCount / descriptionPrevious value: -"Number of measure cells CDC suppressed (< 10 deaths), returned as null."New value: +"How many cellNotes carry the \"Suppressed\" token — cells CDC withheld for confidentiality." - changed
Output schema / requiredPrevious value: -[ - "rows", - "rowCount", - "database", - "caveats", - "suppressedCount", - "effectiveQuery" -]New value: +[ + "rows", + "rowCount", + "database", + "databaseTitle", + "caveats", + "cellNotes", + "messages", + "suppressedCount", + "effectiveQuery" +]
1 tool update
- Added
cdc_query_wonder
2 tool updates
- Changed
cdc_discover_datasets1 field changed- added
Input schema / properties / orderAdded value: +{ + "default": "dataset_id", + "description": "Result 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.", + "enum": [ + "dataset_id", + "relevance" + ], + "type": "string" +}
- Changed
cdc_query_dataset2 fields changed- changed
Input schema / properties / offset / descriptionPrevious value: -"Row offset for pagination."New value: +"Row offset for pagination (max 1,000,000)." - changed
Input schema / properties / offset / maximumPrevious value: -9007199254740991New value: +1000000
3 tool updates
- Changed
cdc_discover_datasets6 fields changed- added
Input schema / properties / domainAdded value: +{ + "default": "data.cdc.gov", + "description": "CDC Socrata portal to search. \"data.cdc.gov\" (default) is the main CDC catalog; \"chronicdata.cdc.gov\" hosts chronic-disease and small-area datasets (PLACES, the Heart Disease & Stroke Atlas, Environmental Public Health Tracking).", + "enum": [ + "data.cdc.gov", + "chronicdata.cdc.gov" + ], + "type": "string" +} - added
Output schema / properties / datasets / items / properties / columnCountAdded value: +{ + "description": "Number of columns in the dataset when reported by the catalog.", + "type": "number" +} - removed
Output schema / properties / datasets / items / properties / columnNamesRemoved value: -{ - "description": "Available column field names when provided.", - "items": { - "type": "string" - }, - "type": "array" -} - added
Output schema / properties / datasets / items / properties / columnSampleAdded value: +{ + "description": "First 8 column field names as a preview. Call cdc_get_dataset_schema for the full column list with data types.", + "items": { + "type": "string" + }, + "type": "array" +} - removed
Output schema / properties / datasets / items / properties / columnTypesRemoved value: -{ - "description": "Column data types (parallel to columnNames) when provided.", - "items": { - "type": "string" - }, - "type": "array" -} - changed
Output schema / properties / datasets / items / properties / description / descriptionPrevious value: -"Dataset description when provided by the catalog."New value: +"Dataset description when provided by the catalog, truncated to 300 characters. Fetch the full text via cdc_get_dataset_schema."
- Changed
cdc_get_dataset_schema1 field changed- added
Input schema / properties / domainAdded value: +{ + "default": "data.cdc.gov", + "description": "CDC Socrata portal hosting the dataset. Use the same portal you found the dataset on via cdc_discover_datasets: \"data.cdc.gov\" (default) or \"chronicdata.cdc.gov\".", + "enum": [ + "data.cdc.gov", + "chronicdata.cdc.gov" + ], + "type": "string" +}
- Changed
cdc_query_dataset1 field changed- added
Input schema / properties / domainAdded value: +{ + "default": "data.cdc.gov", + "description": "CDC Socrata portal hosting the dataset. Must match the portal the dataset lives on: \"data.cdc.gov\" (default) or \"chronicdata.cdc.gov\" (PLACES and other chronic-disease/small-area datasets).", + "enum": [ + "data.cdc.gov", + "chronicdata.cdc.gov" + ], + "type": "string" +}
1 tool update
- Changed
cdc_query_dataset1 field changed- changed
Input schema / properties / where / descriptionPrevious value: -"SoQL WHERE clause. Strings must be single-quoted: \"state='California' AND year=2020\"."New value: +"SoQL WHERE clause. Strings must be single-quoted: \"state='California' AND year=2020\". If a column name matches a SoQL keyword (group, select, where, order, limit, offset, having, search), wrap it in backticks: \"`group`='By Year'\"."
1 tool update
- Changed
cdc_query_dataset4 fields changed- added
Output schema / properties / capAdded value: +{ + "description": "The requested limit that bounded this response.", + "type": "number" +} - changed
Output schema / properties / notice / descriptionPrevious value: -"Guidance when no rows matched — suggests how to verify filter values or broaden the WHERE clause."New value: +"Guidance when no rows matched or results were truncated — how to verify filters, paginate, or broaden the query." - added
Output schema / properties / shownAdded value: +{ + "description": "Number of rows returned in this response.", + "type": "number" +} - added
Output schema / properties / truncatedAdded value: +{ + "description": "True when the result row count hit the requested limit and may be incomplete.", + "type": "boolean" +}
1 tool update
- Changed
cdc_query_dataset1 field changed- changed
Input schema / properties / datasetId / descriptionPrevious value: -"Four-by-four dataset identifier (e.g., \"bi63-dtpu\")."New value: +"Four-by-four dataset identifier (e.g., \"bi63-dtpu\"). Obtain from cdc_discover_datasets."
2 tool updates
- Changed
cdc_discover_datasets3 fields changed- changed
Output schema / properties / appliedFilters / descriptionPrevious value: -"Filters that were applied to this query; absent fields indicate no filter on that dimension."New value: +"Filters applied to this query; absent fields indicate no filter on that dimension." - added
Output schema / properties / noticeAdded value: +{ + "description": "Guidance when no datasets matched — echoes the applied filters and suggests how to broaden the search.", + "type": "string" +} - changed
Output schema / properties / totalCount / descriptionPrevious value: -"Total matching datasets (for pagination)."New value: +"Total matching datasets in the catalog (for pagination)."
- Changed
cdc_query_dataset4 fields changed- added
Output schema / properties / effectiveQueryAdded value: +{ + "description": "Assembled SoQL query string sent to the Socrata API.", + "type": "string" +} - added
Output schema / properties / noticeAdded value: +{ + "description": "Guidance when no rows matched — suggests how to verify filter values or broaden the WHERE clause.", + "type": "string" +} - removed
Output schema / properties / queryRemoved value: -{ - "description": "Assembled SoQL query string sent to Socrata.", - "type": "string" -} - changed
Output schema / requiredPrevious value: -[ - "rows", - "rowCount", - "query" -]New value: +[ + "rows", + "rowCount", + "effectiveQuery" +]
3 tool updates
- Changed
cdc_discover_datasets2 fields changed- changed
Output schema / properties / appliedFilters / descriptionPrevious value: -"Filters applied to this search (echoed for diagnostics)."New value: +"Filters that were applied to this query; absent fields indicate no filter on that dimension." - changed
Output schema / properties / datasets / items / properties / name / descriptionPrevious value: -"Dataset name."New value: +"Dataset display name from the catalog (e.g., \"Provisional COVID-19 Deaths by Sex and Age\")."
- Changed
cdc_get_dataset_schema1 field changed- changed
Output schema / properties / name / descriptionPrevious value: -"Dataset name."New value: +"Dataset display name from the catalog (e.g., \"Provisional COVID-19 Deaths by Sex and Age\")."
- Changed
cdc_query_dataset4 fields changed- changed
Input schema / properties / limit / defaultPrevious value: -1000New value: +100 - changed
Input schema / properties / limit / descriptionPrevious value: -"Max rows to return (default 1000, max 5000)."New value: +"Max rows to return (default 100, max 5000)." - changed
Input schema / properties / search / descriptionPrevious value: -"Full-text search across all text columns (maps to $q). For precise filtering use where instead."New value: +"Full-text search across all text columns. For precise filtering use the where parameter instead." - changed
Output schema / properties / query / descriptionPrevious value: -"Assembled SoQL query string (for debugging)."New value: +"Assembled SoQL query string sent to Socrata."
2 tool updates
- Changed
cdc_discover_datasets1 field changed- added
Output schema / properties / datasets / items / descriptionAdded value: +"A single dataset catalog entry."
- Changed
cdc_get_dataset_schema1 field changed- added
Output schema / properties / columns / items / descriptionAdded value: +"A single column in the dataset schema."
3 tool updates
- Changed
cdc_discover_datasets11 fields changed- changed
Output schema / properties / datasets / items / properties / category / descriptionPrevious value: -"Domain category."New value: +"Domain category when provided." - changed
Output schema / properties / datasets / items / properties / columnNames / descriptionPrevious value: -"Available column field names."New value: +"Available column field names when provided." - removed
Output schema / properties / datasets / items / properties / columnNames / items / descriptionRemoved value: -"Column name" - changed
Output schema / properties / datasets / items / properties / columnTypes / descriptionPrevious value: -"Column data types (parallel to columnNames)."New value: +"Column data types (parallel to columnNames) when provided." - removed
Output schema / properties / datasets / items / properties / columnTypes / items / descriptionRemoved value: -"Column type" - changed
Output schema / properties / datasets / items / properties / description / descriptionPrevious value: -"Dataset description."New value: +"Dataset description when provided by the catalog." - changed
Output schema / properties / datasets / items / properties / pageViews / descriptionPrevious value: -"Total page views."New value: +"Total page views when provided." - changed
Output schema / properties / datasets / items / properties / tags / descriptionPrevious value: -"Domain tags."New value: +"Domain tags when provided." - removed
Output schema / properties / datasets / items / properties / tags / items / descriptionRemoved value: -"Tag" - changed
Output schema / properties / datasets / items / properties / updatedAt / descriptionPrevious value: -"Last data update timestamp."New value: +"Last data update timestamp when provided." - changed
Output schema / properties / datasets / items / requiredPrevious value: -[ - "id", - "name", - "description", - "category", - "tags", - "columnNames", - "columnTypes", - "updatedAt", - "pageViews" -]New value: +[ + "id", + "name" +]
- Changed
cdc_get_dataset_schema6 fields changed- changed
Output schema / properties / columns / items / properties / description / descriptionPrevious value: -"Column description."New value: +"Column description when provided." - changed
Output schema / properties / columns / items / requiredPrevious value: -[ - "fieldName", - "dataType", - "description" -]New value: +[ + "fieldName", + "dataType" +] - changed
Output schema / properties / description / descriptionPrevious value: -"Dataset description."New value: +"Dataset description when provided." - changed
Output schema / properties / rowCount / descriptionPrevious value: -"Total number of rows in the dataset."New value: +"Total number of rows when reported by upstream; omitted when unknown." - changed
Output schema / properties / updatedAt / descriptionPrevious value: -"Last data update timestamp."New value: +"Last data update timestamp when provided." - changed
Output schema / requiredPrevious value: -[ - "name", - "description", - "rowCount", - "updatedAt", - "columns" -]New value: +[ + "name", + "columns" +]
- Changed
cdc_query_dataset1 field changed- changed
Input schema / properties / select / descriptionPrevious value: -"SoQL SELECT clause. Column names, aliases, aggregates: \"state, sum(deaths) as total_deaths\". Omit for all columns."New value: +"SoQL SELECT clause — column names, aliases, or aggregates: \"state, sum(deaths) as total_deaths\". Omit for all columns. To enumerate distinct values of a column, set select to \"{column}, count(*) as count\" with group=\"{column}\" and order=\"count DESC\"."
Related MCP Connectors
CDC MCP — wraps CDC open data via Socrata API (data.cdc.gov)
Query US Census Bureau data: demographics, economics, and housing statistics.
County and tract-level health outcomes, behaviors, and preventive services from CDC PLACES
Search and query government open-data portals (Socrata SODA API).
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceProvides access to 73 CDC public health datasets covering disease surveillance, vaccination tracking, behavioral risk factors, environmental health, and outbreak detection across 18 surveillance systems through the Socrata Open Data API.2MIT
- AlicenseNot gradedqualityCmaintenanceEnables AI agents to query U.S. public-health datasets such as disease surveillance, mortality, behavioral risk factors, and flu activity through the Socrata API, using natural language or direct tool calls.16MIT
- AlicenseAqualityCmaintenanceQuery 2,500+ verified public datasets (World Bank, IMF, Eurostat, OECD, WHO) from your AI agent. Search, analyze, and visualize data, and publish charts — with verified SEC + official source data.283641MIT
- AlicenseNot gradedqualityAmaintenanceQuery WHO Global Health Observatory data — 3,059 indicators across 194 member states with country, region, year, and sex filters via MCP.3362Apache 2.0
Glama MCP Gateway
Add one secure layer between your agents and this server.