A side-by-side look at the Aihw MCP and Cms MCP servers: transport, auth, tools, quality signals, and the config to install either one in Claude, Cursor, Windsurf or VS Code.
Verdict: choose Aihw MCP for biology & bioinformatics work as a local process; choose Cms for biology & bioinformatics as a local process. You can also run both side by side in one mcpServers block.
search_datasets, describe_dataset, get_data.search_datasets, get_dataset, dataset_info.Rows where the two servers differ are marked.
| Spec | ||
|---|---|---|
| Category | Biology & Bioinformatics | Biology & Bioinformatics |
| Quality signal | 55/100 · Good | 56/100 · Good |
| Install command | Confirmed | Confirmed |
| Transport | Local subprocess (stdio) | Local subprocess (stdio) |
| Auth | Not declared | No auth required |
| Pricing | Not declared | Free |
| Required env vars | None listed | None listed |
| Verified owner | Community listing | Community listing |
| GitHub stars | 0 | 1 |
| Directory activity | 1 views 0 installs 0 upvotes | 1 views 0 installs 0 upvotes |
| Tools | 6 | 3 |
| Full listing | View Aihw MCP | View Cms |
search_datasetsFuzzy-search the curated AIHW dataset catalog.
All datasets ship hand-curated in v0.1: long-term mortality (GRIM),
regional mortality (MORT), cancer incidence and mortality, health
expenditure, youth justice detention, and the public hospitals
register.
Examples:
# Find a dataset that gives deaths by cause
results = await search_datasets("mortality cause of death")
# → [{id: 'GRIM_DEATHS', name: 'GRIM — long-term mortality', ...}]
# Discover what's available on cancer
results = await search_datasets("cancer")
Returns:
List of DatasetSummary (id, name, description, update_frequency,
is_curated), ranked by relevance.describe_datasetDescribe a dataset's filterable dimensions, returnable measures, units, and source.
Use this before calling get_data on a new dataset — it tells you the
valid filter keys ('sex', 'year', 'state'), the valid filter values
('Females', 'Males', 'Persons'), the measure aliases ('deaths',
'crude_rate_per_100000'), and the canonical source URL.
Returns:
DatasetDetail with id, name, description, period_coverage, list of
dimensions, list of measures (each with key, source_column, unit,
description), and source_url + download_url.get_dataQuery a curated AIHW dataset and return observations.
Examples:
# Deaths from diabetes, all years and sexes
resp = await get_data(
"GRIM_DEATHS",
filters={"cause_of_death": "Diabetes"},
measures="deaths",
)
# Breast cancer incidence in females over time
resp = await get_data(
"CANCER_INCIDENCE_MORTALITY",
filters={"cancer_type": "Breast cancer", "sex": "Female", "type": "Incidence"},
)
# Public hospitals in NSW with peer group "Principal referral"
resp = await get_data(
"PUBLIC_HOSPITALS",
filters={"state": "NSW", "peer_group_name": "Principal referral"},
)
Returns:
DataResponse with records (or csv), unit, period bounds, row_count,
source URL, and CC-BY attribution.latestReturn the most recent observation(s) per measure for a dataset.
For transposed time-series tables this trims to the most-recent period.
For wide datasets with a real period, "latest" means the most recent
period(s) — keeping ALL entities/dimensions at that period, not an
arbitrary N rows. For wide single-year tables with no period variation
(most AIHW datasets) it returns the same shape as get_data, capped at
`limit` rows so a large register (e.g. PUBLIC_HOSPITALS) doesn't blow
the response budget. Truncated responses set DataResponse.truncated_at
to the original row count.
When the curated YAML declares a `headline_slice`, those filter values
are applied automatically so the no-filter call returns ONE canonical
headline row (e.g. HEALTH_EXPENDITURE → national total, all areas, all
sources). User-supplied filters override the headline_slice per-key —
`latest("HEALTH_EXPENDITURE", filters={"state": "NSW"})` keeps the
area/source defaults and returns the NSW latest-year total.
Examples:
# Latest year of GRIM data for All causes combined
resp = await latest("GRIM_DEATHS", filters={"cause_of_death": "All causes combined"})
# All ~700 public hospitals (default cap of 50 would otherwise apply)
resp = await latest("PUBLIC_HOSPITALS", limit=1000)top_nReturn the N rows with the largest (or smallest) value of a measure.
This is the most common agent workflow: "show me the top 10 X by Y".
Without this tool, an agent would call get_data, receive the full table,
and then sort/slice locally — wasting tokens and turns. top_n does the
rank server-side and returns only the requested rows.
Examples:
# Top 10 causes of death in 2023 (Persons)
top_n("GRIM_DEATHS", "deaths", n=10,
filters={"sex": "Persons", "year": "2023"})
# 20 SA3 regions with the highest age-standardised mortality
top_n("MORT_GEOGRAPHY", "age_standardised_rate_per_100000",
filters={"category": "Statistical Area Level 3 (SA3)",
"sex": "Persons", "year": "2023"}, n=20)
# 5 lowest-funded health expenditure areas in NSW
top_n("HEALTH_EXPENDITURE", "real_expenditure_millions",
filters={"state": "NSW", "financial_year": "2022-23"},
n=5, direction="bottom")
Returns:
DataResponse with at most `n` records, sorted by `measure` value
in the requested direction. Other fields (period, unit, attribution)
match a regular get_data call.list_curatedList every curated dataset ID in this version of aihw-mcp.
These are the datasets where get_data accepts plain-English filter keys
and returns aliased, well-typed measure columns. Each ID is documented
via describe_dataset.
Returns:
Sorted list of dataset IDs.search_datasetsFind CMS dataset IDs + titles by keyword. CMS publishes Medicare/Medicaid open data (provider data, spending, enrollment, drug pricing, quality measures, hospitals, nursing homes, ACOs, etc.). Searches the CMS DCAT catalog client-side over each dataset title/description/keywords. Returns the datase…get_datasetPull rows from a CMS dataset by datasetId (UUID from search_datasets). Returns an array of row objects whose keys are the dataset columns. Supports paging (size/offset), full-text keyword search across the dataset, and exact-match column filters via filters: {COLUMN: VALUE} (column names match the…dataset_infoMetadata for a CMS dataset by datasetId: title, description, total row count, last-modified date, themes/keywords, and downloadable resources (CSV files, data dictionaries). Use after search_datasets to inspect a dataset before pulling rows.Paste either block (or both) into your client config, e.g. claude_desktop_config.json or ~/.cursor/mcp.json. We only show a config when the install command is confirmed.
{
"mcpServers": {
"aihw-mcp": {
"command": "uvx",
"args": [
"--upgrade",
"aihw-mcp"
]
}
}
}
{
"mcpServers": {
"cms-3": {
"command": "npx",
"args": [
"-y",
"@pipeworx/mcp-cms"
]
}
}
}