Australian Institute of Health and Welfare
This server provides plain-English, structured access to Australian Institute of Health and Welfare (AIHW) statistics via six MCP tools.
search_datasets — fuzzy-search the curated AIHW catalog by keyword.
describe_dataset — explore a dataset's filterable dimensions, measures, units, and source URLs.
get_data — query datasets with filters, measures, period ranges, and output formats (records, series, csv).
latest — quickly retrieve the most recent observation(s) per measure.
top_n — rank rows by a measure and return top or bottom N results.
list_curated — enumerate all curated dataset IDs.
Coverage includes long-term mortality (GRIM), regional mortality (MORT), cancer incidence/mortality, health expenditure, youth justice detention, and public hospitals. It supports time-series filtering, multi-value filters, canonical state/postcode aliases, and includes source URLs and CC-BY attribution in every response.
aihw-mcp
mcp-name: io.ausdata/aihw-mcp
MCP server for Australian Institute of Health and Welfare statistics. Plain-English access to long-term mortality (GRIM), regional mortality (MORT), cancer incidence and mortality (ACIM), national health expenditure, youth justice detention, and the public hospitals register — all from a single uvx command.
Hosted access? For cross-source queries, webhooks, an always-on REST API, and a uniform response envelope across all 9 sources, see ausdata.io — free tier available (500 calls/mo, no card).
"How have diabetes deaths changed since 1980?"
"What's the age-standardised mortality rate in the Sydney - Inner West SA3?"
"Show me breast cancer incidence in women aged 50–54 over time."
"How much did Australia spend on public hospitals in 2022-23?"
"How many young people are in detention in NSW vs VIC?"
"List all Principal referral hospitals in Queensland."
"Top 5 causes of death in 2023."Sister to abs-mcp (Australian Bureau of Statistics), rba-mcp (Reserve Bank of Australia), ato-mcp (Australian Taxation Office), and au-weather-mcp (Australian weather). The five together cover the macro / regulator / tax / health / climate layer of Australian official data.
Install
# Run on demand via uvx (recommended)
uvx --upgrade aihw-mcp
# Or install permanently
pip install aihw-mcpClaude Desktop
Add to claude_desktop_config.json:
{
"mcpServers": {
"aihw": { "command": "uvx", "args": ["--upgrade", "aihw-mcp"] }
}
}Why
--upgrade?uvx aihw-mcp(without the flag) uses whatever wheel is cached and never adopts new PyPI releases on its own.--upgrademakes uvx check PyPI on each launch and pull a newer release if one exists. To verify which version is currently serving you, look at theserver_versionfield on anyDataResponse.
Claude Code / Cursor
claude mcp add aihw --command uvx --args -- --upgrade aihw-mcpRelated MCP server: aemo-mcp
Auto-updating data
Beyond the wheel-level --upgrade, the server has a second auto-update path inside the data layer: when AIHW refreshes GRIM with another year of deaths data or publishes a new MORT release, aihw-mcp resolves the new resource URL via data.gov.au's CKAN API at fetch time and uses the freshest match. Hard-coded YAML URLs are the safe fallback if discovery fails. You do not need to wait for a new wheel release to get new yearly data — just delete ~/.aihw-mcp/cache.db to force a refresh, or wait for the 7-day TTL to expire.
What it exposes
Six tools, all plain-English in, structured out:
Tool | Purpose |
| Fuzzy-search the curated catalog by keyword |
| List a dataset's filterable dimensions and returnable measures |
| Query with |
| Last observation per measure (shortcut) |
| Rank rows by a measure, return top (or bottom) N |
| Enumerate the curated dataset IDs |
Every response is the same shape — dataset_id, dataset_name, query, period, unit, row_count, records, aihw_url, attribution, server_version — across every curated dataset.
Time-series datasets (GRIM, MORT, ACIM, Health Expenditure, Youth Justice) accept start_period and end_period on get_data — e.g. start_period="2000", end_period="2010" narrows GRIM to that decade. latest() returns the most-recent observation per measure, sorted by the dataset's declared period dimension (not by source row order). Error messages include fuzzy "did you mean?" suggestions when you typo a filter or measure name.
Curated datasets (6 in v0.1)
ID | What it is | Period | Coverage |
| National long-term mortality: deaths × cause × year × sex × age band | 1907 → present | ~370k rows, 3 measures |
| Regional mortality: deaths + premature/avoidable deaths × State / SA3 / SA4 / PHN | 2019 → present | ~15k rows, 15 measures |
| Cancer incidence + mortality counts × year × sex × type × 5-year age band | 1968 → present | ~9k rows, 19 age columns |
| Real expenditure by financial year × state × area × source (Government / non-Govt) | 1997-98 → present | ~7k rows, AUD millions |
| Avg nightly youth-detention pop × quarter × state × sex × Indigenous × legal status | 2008 → present | ~42k rows |
| Directory of every public hospital × state × peer group × remoteness × LHN | 2016-17 reference | ~700 hospitals |
Adding a new dataset is a single YAML drop into src/aihw_mcp/data/curated/ — see CONTRIBUTING.md.
Example queries (paste into Claude)
Cross-source compatibility. The
statefilter on HEALTH_EXPENDITURE, PUBLIC_HOSPITALS, YOUTH_JUSTICE_DETENTION, and other location-aware datasets accepts canonical state codes ("NSW"), full names ("New South Wales"), case-insensitive variants ("nsw"), ISO 3166-2 ("AU-NSW"), and 4-digit postcodes ("2000"→ NSW). Powered byaus-identity— the same input format works across abs-mcp, ato-mcp, apra-mcp, aihw-mcp, and asic-mcp.
Public-health research: "For GRIM_DEATHS, give me the deaths and age-standardised rate for 'Diabetes' for Persons every year from 1980 to the latest, so I can chart the trajectory."
Health-tech / regional analysis: "Using MORT_GEOGRAPHY, list the 10 SA3 regions with the highest age-standardised mortality rate for Persons in the most recent year."
Oncology: "From CANCER_INCIDENCE_MORTALITY, give me Breast cancer incidence in Females across the 50–54 age band for every available year, plus the same age band's mortality."
Health-policy: "From HEALTH_EXPENDITURE, what was the real spend on 'Public hospitals' in NSW in 2022-23, broken down by broad source (Government vs Non-government)?"
Criminal-justice tech: "Using YOUTH_JUSTICE_DETENTION, compare the average nightly youth-detention population in NSW vs VIC in 'Jun qtr 2017', for both Indigenous and Total."
Hospital-tech / market intel: "From PUBLIC_HOSPITALS, list every 'Principal referral' hospital with their state and Local Hospital Network. Then count how many there are per state."
Each prompt resolves to one or two get_data / top_n calls. The response includes the source URL so the agent can cite it back.
Architecture
Same shape as the sister packages — client → cache → parsing → shaping → server:
client.pywrapshttpxwith a SQLite-backed disk cache (per-resource TTL).parsing.pyreads CSV (viapandas) and XLSX (viaopenpyxl/pandas). Header rows + sheet names live in the curated YAML so future format quirks are a YAML edit, not a code change.curated.pyloads dataset specs fromdata/curated/*.yaml— each one declares its dimensions, measures, dimension value enums, source/download URLs, format, and parse layout.shaping.pytransforms the parsed DataFrame intoDataResponse(records / series / csv).server.pyis the FastMCP entrypoint — six tools, full input validation with helpful "Try X" hints on error.
Cache lives under ~/.aihw-mcp/cache.db. Most AIHW datasets refresh once a year; the TTLs are tuned for that cadence.
Attribution
Data sourced from the Australian Institute of Health and Welfare (AIHW) via data.gov.au. Licensed under Creative Commons Attribution 3.0 Australia (CC BY 3.0 AU). The MCP server is MIT-licensed; the data carries the upstream CC-BY 3.0 AU licence, which is echoed in every response's attribution field.
Sister MCPs (Australian Public Data portfolio)
Want all 9 sources behind one REST API? The hosted gateway at ausdata.io adds cross-source joins, full history, webhooks, and HMAC-signed responses on top of these MCPs — free tier (500 calls/mo, no card).
abs-mcp — Australian Bureau of Statistics (CPI, unemployment, ERP, building approvals)
rba-mcp — Reserve Bank of Australia (cash rate, lending stats, exchange rates)
ato-mcp — Australian Taxation Office (tax stats, ACNC charities)
apra-mcp — Australian Prudential Regulation Authority (banking, insurance, super)
aihw-mcp — this one. National mortality, regional health, cancer, expenditure, youth justice, hospitals.
asic-mcp — Australian Securities and Investments Commission (company registers)
aemo-mcp — Australian Energy Market Operator (NEM dispatch, spot prices, generation)
au-weather-mcp — Open-Meteo (Bureau of Meteorology aggregator)
wgea-mcp — Workplace Gender Equality Agency
aus-identity — Postcode / state / ABN normalisation helper used by all sisters
The portfolio is designed to compose: an agent can ask for "unemployment + cash rate + median income + mortality + climate" for postcode 2000 and one shot fans out across multiple MCPs.
Roadmap (next iterations)
v0.2: MORT_TABLE_2 (deaths by leading cause × region); intercountry adoptions; AIHW mental-health data tables (XLSX path)
v0.3: hosted version with x402 per-call paywall; programmatic SEO pages
v0.4: listing on MCPay + Apify; paid tier for high-volume agent users
CHANGELOG tracks every release.
Development
git clone https://github.com/Bigred97/aihw-mcp.git
cd aihw-mcp
uv venv
uv pip install -e ".[dev]"
pytest # unit tests, no network
pytest -m live # integration tests against data.gov.auIssues, ideas, and contributions welcome: github.com/Bigred97/aihw-mcp/issues.
Available Tools
6 toolsdescribe_datasetA
Describe 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.
| Name | Required | Description | Default |
|---|---|---|---|
| dataset_id | Yes | Curated dataset ID. Use the search endpoint or search tool to discover, or the list-curated endpoint/tool to enumerate. Case-insensitive. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| name | Yes | |
| measures | No | |
| dimensions | No | |
| is_curated | Yes | |
| source_url | Yes | |
| description | Yes | |
| download_url | No | |
| period_coverage | No | |
| update_frequency | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It discloses the return structure in detail, but does not explicitly state that the tool is read-only or discuss any side effects, auth requirements, or rate limits.
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 concise (three sentences), well-structured, and front-loaded with the main action. Every sentence adds value, with no wasted words.
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 presence of an output schema, the description adequately covers the return format and use case. It lacks mention of edge cases or error scenarios, but for a simple descriptive tool, it is nearly complete.
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% with examples and case-insensitivity. The description adds no additional parameter meaning beyond what the schema already provides, so baseline 3 is appropriate.
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 clearly states the tool's purpose: 'Describe a dataset's filterable dimensions, returnable measures, units, and source.' It uses specific verbs and resource nouns, and distinguishes itself from siblings by positioning it as a prerequisite for 'get_data'.
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 says 'Use this before calling get_data on a new dataset', providing clear context for when to use. However, it does not explicitly mention when not to use it or compare with alternatives like 'search_datasets'.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_dataA
Query 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.
| Name | Required | Description | Default |
|---|---|---|---|
| format | No | Response shape. 'records' (default): flat list of observations. 'series': grouped by measure. 'csv': pandas CSV string in `csv` field. | records |
| filters | No | Dimension filters. Keys are plain-English aliases from the dataset's describe_dataset response. Values are matched against the source data; pass a list to OR across values. Examples: {'sex': 'female'}, {'year': '2023'}, {'cause_of_death': ['Diabetes', 'Stroke']}. | |
| measures | No | Which measure(s) to return. Plain-English keys from describe_dataset. Omit to return all measures. | |
| dataset_id | Yes | Curated dataset ID. Use the search or list-curated endpoint/tool to discover. | |
| end_period | No | Inclusive end period. Same format as start_period. | |
| start_period | No | Inclusive start period for transposed time-series datasets. Ignored for wide single-year tables. Format: 'YYYY' or 'YYYY-MM' or AIHW FY 'YYYY-YY'. Bare int years like 2010 are coerced to '2010' automatically. |
Output Schema
| Name | Required | Description |
|---|---|---|
| csv | No | |
| unit | No | |
| query | No | |
| stale | No | |
| period | No | |
| source | No | |
| records | No | |
| aihw_url | Yes | Click-through URL for this dataset's source page. aihw-mcp legacy name — prefer source_url (canonical) for new code. Both fields are populated identically. |
| row_count | No | |
| dataset_id | Yes | |
| source_url | Yes | Canonical click-through URL. Same value as aihw_url; both populated for backward compat. |
| attribution | No | |
| dataset_name | Yes | |
| retrieved_at | Yes | |
| stale_reason | No | |
| truncated_at | No | |
| server_version | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided; description covers return structure and filter behavior (OR across list values) but lacks info on rate limits, auth, or error handling. Decent but not comprehensive.
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?
Concise summary, illustrative examples, and return description—every element earns its place. Front-loaded purpose.
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?
Covers all key parameters (dataset_id, filters, measures, format, periods) and references describe_dataset for more detail. Output schema is mentioned, making it complete for a data query tool.
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?
100% schema coverage gives baseline 3; description adds value with examples, notes on plain-English aliases, and period formats, slightly exceeding schema alone.
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 clearly states it queries a curated AIHW dataset and returns observations, with specific verb and resource. Examples differentiate from siblings like search_datasets and latest.
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?
Examples imply usage, but no explicit when-to-use or when-not-to-use compared to siblings. No alternatives mentioned.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
latestA
Return the most recent observation(s) per measure for a dataset.
For transposed time-series tables this trims to the most-recent period. For wide single-year tables (most AIHW datasets) it returns the same shape as get_data — there is only one period in those tables.
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"})
| Name | Required | Description | Default |
|---|---|---|---|
| filters | No | Same filter shape as get_data. Useful for narrowing to one entity. | |
| measures | No | Same as get_data. | |
| dataset_id | Yes | Curated dataset ID. |
Output Schema
| Name | Required | Description |
|---|---|---|
| csv | No | |
| unit | No | |
| query | No | |
| stale | No | |
| period | No | |
| source | No | |
| records | No | |
| aihw_url | Yes | Click-through URL for this dataset's source page. aihw-mcp legacy name — prefer source_url (canonical) for new code. Both fields are populated identically. |
| row_count | No | |
| dataset_id | Yes | |
| source_url | Yes | Canonical click-through URL. Same value as aihw_url; both populated for backward compat. |
| attribution | No | |
| dataset_name | Yes | |
| retrieved_at | Yes | |
| stale_reason | No | |
| truncated_at | No | |
| server_version | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so description carries full burden. It discloses key behaviors: trimming to most-recent period, headline_slice defaults, user overrides. Does not cover auth or rate limits, but overall good.
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?
Description is front-loaded with main purpose, then explains nuances. Examples are helpful. Could be slightly more concise, but well-structured.
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 output schema exists and moderate complexity, description is thorough. Explains headline_slice, table type behavior, and provides examples. Complete for agent use.
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%, so baseline 3. Description adds little beyond schema for parameters, only notes that filters are same shape as get_data and gives examples. No extra detail for measures.
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?
Description states the tool returns the most recent observation(s) per measure for a dataset. It distinguishes from siblings like get_data by focusing on latest data and explains behavior for different table types.
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?
Explains when to use for transposed vs wide tables, and how headline_slice applies. Provides examples. Lacks explicit when-not-to-use but context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_curatedA
List 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.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, but the description discloses that the output is a sorted list of dataset IDs and characterizes the data (curated, with specific filter behavior). This is adequate for a simple read-only tool, though it lacks details on caching or live-fetching.
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 only four sentences, each serving a purpose: stating the action, explaining the concept, pointing to related tool, and declaring the output format. No redundant or vague language.
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 tool's simplicity (no parameters, clear output), the description covers its role and relationship to siblings. It could mention error cases or performance notes, but for a list command this level is sufficient.
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?
The tool has zero parameters, so the input schema coverage is 100%. Per guidelines, baseline 4 applies, and the description adds no parameter information as none is needed.
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 explicitly states the action (List) and the resource (every curated dataset ID), and distinguishes from siblings by explaining the meaning of 'curated'—datasets accepting plain-English filters—which sets it apart from describe_dataset and get_data.
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 hints at when to use this tool (to find curated datasets) and directs users to describe_dataset for documentation, but does not explicitly state when not to use it or compare directly to search_datasets.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_datasetsA
Fuzzy-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.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum number of results to return, ranked by relevance. | |
| query | Yes | Free-text search query. Matches against dataset IDs, names, descriptions, and curated search keywords. Case-insensitive. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description fully carries the burden. It discloses the return type and catalog contents, implying a read-only search operation. While it doesn't discuss authentication or rate limits, the provided context about fuzzy matching and ranked results adds value.
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 concise and well-structured, starting with the core purpose, followed by catalog context, usage examples, and return type. Every sentence contributes meaningfully.
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?
The description is largely complete for a simple search tool, covering purpose, examples, return format, and catalog contents. An output schema exists, so detailed return specs are not needed. Missing discussion on error handling or empty results, but overall sufficient.
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%, so baseline is 3. The description's examples illustrate typical queries but add no substantial new semantics beyond the schema's parameter descriptions and examples for 'query' and 'limit'.
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 clearly states 'Fuzzy-search the curated AIHW dataset catalog' with a specific verb and resource. Examples and return type further clarify the tool's function, and it distinguishes itself from siblings like describe_dataset and get_data.
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 implies usage for discovering datasets via free-text queries but lacks explicit guidance on when to use this tool versus alternatives like list_curated or top_n. No when-not-to-use or exclusion criteria are provided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
top_nA
Return 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.
| Name | Required | Description | Default |
|---|---|---|---|
| n | No | How many top (or bottom) rows to return. | |
| filters | No | Optional dimension filters, same shape as get_data. | |
| measure | Yes | Plain-English measure key to rank by. Use the describe endpoint or describe tool to see available measures. | |
| direction | No | 'top' returns the N rows with the LARGEST measure values (highest deaths, biggest expenditure, etc.). 'bottom' returns the SMALLEST. | top |
| dataset_id | Yes | Curated dataset ID. Use the search or list-curated endpoint/tool to discover. |
Output Schema
| Name | Required | Description |
|---|---|---|
| csv | No | |
| unit | No | |
| query | No | |
| stale | No | |
| period | No | |
| source | No | |
| records | No | |
| aihw_url | Yes | Click-through URL for this dataset's source page. aihw-mcp legacy name — prefer source_url (canonical) for new code. Both fields are populated identically. |
| row_count | No | |
| dataset_id | Yes | |
| source_url | Yes | Canonical click-through URL. Same value as aihw_url; both populated for backward compat. |
| attribution | No | |
| dataset_name | Yes | |
| retrieved_at | Yes | |
| stale_reason | No | |
| truncated_at | No | |
| server_version | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It explains that the tool performs server-side ranking, returns at most n records sorted by measure, and that other fields match get_data. The read-only nature is implied. It could be more explicit about idempotency or side effects, but overall the behavioral traits are adequately disclosed.
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 highly concise: a single sentence defining the tool, a paragraph explaining its value, three clear examples, and a returns summary. Every sentence serves a purpose, and the structure is front-loaded with the most critical information. No redundancy.
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 tool's complexity (5 parameters, no annotations, sibling tools present), the description is complete. The output schema is available (as per context), so detailed return value explanation is unnecessary. The description covers purpose, usage, examples, and behavioral traits sufficiently.
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?
The input schema has 100% description coverage, so the baseline is 3. The description adds value by providing examples and usage guidance for each parameter, such as suggesting the describe tool for measure discovery and clarifying direction. This goes beyond the schema's basic descriptions, earning a 4.
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 clearly states the function: 'Return the N rows with the largest (or smallest) value of a measure.' It uses a specific verb (return) and resource (rows), and distinguishes itself from sibling tools like get_data by explaining that it avoids retrieving full tables. The purpose is unambiguous and well-defined.
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 identifies the primary use case: 'show me the top 10 X by Y' and contrasts with get_data to highlight efficiency. It provides multiple examples illustrating typical usage. While it doesn't explicitly state when not to use, the context is clear. A slight enhancement could be mentioning to use describe_dataset for measure discovery, but the parameter description already hints at that.
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.
6 tool updates
v0.4.17- Added
describe_dataset - Added
get_data - Added
latest - Added
list_curated - Added
search_datasets - Added
top_n
6 tool updates
v0.4.15- Removed
describe_dataset - Removed
get_data - Removed
latest - Removed
list_curated - Removed
search_datasets - Removed
top_n
6 tool updates
v0.1.0- First observed
describe_dataset - First observed
get_data - First observed
latest - First observed
list_curated - First observed
search_datasets - First observed
top_n
TDQS
Scored across 6 tools
Each tool has a clearly distinct purpose: describe_dataset explains schema, get_data queries data, latest returns most recent observations, list_curated lists dataset IDs, search_datasets searches catalog, top_n ranks rows. No ambiguity.
All tool names use consistent snake_case pattern (describe_dataset, get_data, latest, list_curated, search_datasets, top_n). No mixing of conventions.
6 tools is well-scoped for a dataset querying server. Each tool covers a necessary function without redundancy.
The tool surface covers full read lifecycle: discovery (list, search, describe), query (get, latest, top_n). No obvious gaps for the intended purpose.
Maintenance
Related MCP Connectors
Hosted MCP server exposing US hospital procedure cost data to AI assistants
WHO GHO MCP — World Health Organization Global Health Observatory (free, no auth)
Hosted MCP server for finding authoritative primary data sources and official portals.
UK NIHR (National Institute for Health and Care Research) open-data MCP.
Related MCP Servers
- AlicenseAqualityAmaintenanceOne-call Australian workplace gender data plumbing via WGEA — cited responses for workforce, pay-gap and inclusion analysis, not a data broker.6122 PyPIMIT
- AlicenseAqualityBmaintenanceOne-call Australian energy-market plumbing via AEMO — cited, structured responses for market data and analysis, not a data broker.5172 PyPIMIT
- AlicenseAqualityBmaintenanceCited Australian stats via the ausdata.io gateway — stable AU.* series IDs, source_url + retrieved_at on every response. Free tier. Not a data broker; upgrade for Embed / signed / webhooks.2839 npm2MIT
- AlicenseNot gradedqualityDmaintenanceAn MCP server that provides comprehensive medical information by querying authoritative APIs including FDA, WHO, PubMed, RxNorm, and Australia's PBS, enabling drug searches, health statistics, medical literature, drug nomenclature, and PBS subsidy queries.62 npmMIT