A side-by-side look at the Aihw MCP and Genomics MCP 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 Genomics MCP 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.list_sources, search_datasets, describe_dataset.Rows where the two servers differ are marked.
| Spec | ||
|---|---|---|
| Category | Biology & Bioinformatics | Biology & Bioinformatics |
| Quality signal | 55/100 · Good | 59/100 · Good |
| Install command | Confirmed | Confirmed |
| Transport | Local subprocess (stdio) | Local subprocess (stdio) |
| Auth | Not declared | Not declared |
| Pricing | Not declared | Not declared |
| Required env vars | None listed | None listed |
| Verified owner | Community listing | Community listing |
| GitHub stars | 0 | 3 |
| Directory activity | 1 views 0 installs 0 upvotes | 1 views 0 installs 0 upvotes |
| Tools | 6 | 23 |
| Full listing | View Aihw MCP | View Genomics MCP |
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.list_sourcesList data and reference sources, their state and supported operations.search_datasetsSearch one archive/catalog for studies or datasets by text query.
Available for: ega, ena, encode, geo, ncbi_datasets.describe_datasetDescribe a study/dataset by native accession, with linked entities.
Available for: ega, ena, encode, geo, ncbi_datasets.list_filesList files of a study/dataset with format, size, checksums, index and readiness.
Available for: ega, ena, encode, geo, local, ncbi_datasets, s3.list_samplesList samples of a study/dataset as supplied by the source.
Available for: ega, ena, encode, geo, ncbi_datasets.get_sample_metadataGet one sample's metadata and phenotype values exactly as supplied by the source.
Available for: ega, ena, encode, geo, ncbi_datasets.fetch_fileStart a bounded download of a file (and index) to the local work dir. Returns a transfer job; files above the default limit need budget_bytes.
Available for: default.get_transfer_statusGet progress/result of a transfer started by fetch_file.
Available for: default.cancel_transferCancel a running transfer.
Available for: default.get_readsAlignments overlapping an interval from indexed BAM/CRAM. Flag filters follow samtools -f/-F. CRAM needs a matching reference unless self-contained.
Available for: bam, cram.get_coverageRead depth over an interval from indexed BAM/CRAM (default excludes UNMAP, SECONDARY, QCFAIL, DUP, like samtools depth).
Available for: bam, cram.get_pileupPer-position base counts over an interval from indexed BAM/CRAM.
Available for: bam, cram.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": {
"genomics-mcp": {
"command": "uvx",
"args": [
"rewire-genomics-mcp"
]
}
}
}