StatsMapped: Irish statistics (CSO, county & council data)
Use this MCP server to discover, query, compare, explain, and prepare visual data from StatsMapped's public Ireland/UK statistics API.
Discover datasets/stat keys and geography levels per country with
query_data; supportsirelandandunited-kingdom.List area IDs and names at boundary levels such as counties, local authorities, and LADs with
list_areas.Query all datasets for one area, or full detail for one area+dataset with summary, caveats, and optional recent history.
Get Irish council planning summaries: application counts, grant/refusal shares, median decision days, sources, licences, and typed absences.
Rank areas by a stat, list registered comparison pairs, fetch pair correlations, and check whether two stats are comparable.
Explain a metric's definition, methodology, and standing caveats with
explain_metric.Fetch structured data for drawing a scene/chart, including rows, alt text, notes, licence constraints, absences, scene hash, receipt, and canonical URL.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@StatsMapped: Irish statistics (CSO, county & council data)Rank Irish counties by median house price"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
statsmapped-mcp
An MCP server exposing StatsMapped's public API as tools for AI agents (Claude Desktop, Cursor, and any other MCP client).
StatsMapped tracks public data for Ireland (by county) and the UK (by local authority) — housing,
crime, health, the economy and social welfare — from official publishers (CSO, PSRA, Central Bank
of Ireland, DHLGH, NTPF, the Office of Government Procurement, EU Publications Office for Ireland;
ONS/HM Land Registry/Nomis/DfE/DfT for the UK), each figure carrying its own caveats. This
package lets an agent query that data directly as tool calls instead of crawling and parsing
web pages. Every tool below takes a country argument ("ireland" or "united-kingdom",
default "ireland") — the two countries track genuinely different datasets and geography levels,
so call query_data/list_areas for the country you actually want rather than assume
Ireland's defaults apply.
This is a thin client. It calls StatsMapped's already-public, unauthenticated HTTPS API
(documented at statsmapped.com/openapi.json); no API key
is needed for anything below. Runs on your own machine over stdio by default (the recommended way
to use it today) -- see Why stdio for a hosted
streamable-http mode this package also supports, and the real tradeoff that comes with it.
Install
Published on PyPI as statsmapped-mcp (confirmed live: https://pypi.org/project/statsmapped-mcp/):
pip install statsmapped-mcpRelated MCP server: ELS MCP server
Configure
Add to your MCP client's config (for Claude Desktop, claude_desktop_config.json; Cursor uses an
equivalent mcp.json):
{
"mcpServers": {
"statsmapped": {
"command": "statsmapped-mcp"
}
}
}Tools
4 tools (consolidated from an original 9 -- query_data and compare are each one tool with a
few modes, chosen by which arguments you give, rather than several near-identical single-purpose
ones). Every tool takes a country argument ("ireland" or "united-kingdom", default
"ireland") — Ireland and the UK track different datasets and geography levels, so call
query_data/list_areas for the country you want rather than assume Ireland's defaults apply.
query_data(area_id=None, dataset=None, history_months=0, country="ireland")— three modes:neither
area_idnordataset: every stat StatsMapped tracks for one country, with its key, label, and which geography levels it's published at. Start here.area_idgiven,datasetomitted: every dataset available for one area (e.g."county:kerry"for Ireland,"uk:lad:e09000033"for the UK), with its latest figure and year-on-year change. Caveats are projected to label + severity only, not full text — the point is deciding which datasets matter before paying for the full detail on any one of them.both
area_idanddatasetgiven: full detail on one dataset in one area — a written summary, full caveat text, and (optionally, viahistory_months) recent history.
list_areas(level="county", country="ireland")— every geography at one boundary level.leveldefaults to Ireland's 26 counties; the UK's own primary level is"lad"(local authority districts), not"county"— other levels exist per country too (Ireland'slocal_authority/garda_divisionamong them).compare(stat_key=None, level=None, pair_key=None, stat_key_a=None, stat_key_b=None, country="ireland")— four modes, exactly one set of arguments at a time (mixing them raises an error):stat_keyalone: every area at one level, ranked by its latest figure for that stat, highest first.pair_keyalone: full detail for one registered comparison pair — each axis's label/unit/publisher, the correlation stats (r, rho, a leave-one-out sensitivity range), and caveats.pair_keycomes from the no-argument mode below.both
stat_key_aandstat_key_b: does StatsMapped have a registered, hand-vetted comparison between these two stats? Registry-backed only — never computes a fresh correlation for an arbitrary pair.comparableis a string, not a bool:"yes"(a registered, hand-vetted pair;pair_keynames it),"no"(the two stats share no geography level at all), or"unknown"(not registered, but not ruled out: treat as "ask a human", not "probably yes")."unknown"is the normal result for most pairs. Compare the value explicitly (result["comparable"] == "yes"); a truthiness test is true for all three.reasons(a list) always explains the answer.none of the above: every registered cross-dataset comparison pair for one country (e.g. "median sale price vs new dwelling completions per 1,000 residents"). A small, hand-curated set, not an arbitrary-pair engine.
explain_metric(stat_key, country="ireland")— definition, methodology and standing caveats for one stat, never a current figure. Use this when the question is about what a metric means or how it's measured, not about one area's value.
Why stdio, not a hosted server, by default
StatsMapped runs on a single free-tier instance. A remote MCP endpoint hosted there would let an agent's own multi-area query pattern (calling the same tool once per area, in a loop) reproduce exactly the load pattern that has already caused timeouts on that instance under a large geography fan-out. Running over stdio means every call goes through your own network connection to the same public HTTPS API this package's tools call directly, with no shared bottleneck -- each user's own machine makes the HTTP calls, so N users' traffic is naturally spread across N source IPs, not funnelled through one.
server.py also supports a real hosted streamable-http mode (MCP_TRANSPORT=streamable-http)
for a deployment that accepts that tradeoff -- StatsMapped's public API is itself rate-limited
per source IP (600 requests/hour), but a hosted MCP endpoint proxies every remote user's calls
through ONE shared egress IP, so all remote users of a hosted endpoint would share that one
bucket rather than each getting their own. A StatsMapped-hosted endpoint is live at
https://mcp.statsmapped.com/mcp (Streamable HTTP) -- confirmed responding correctly, no
separate install needed for a client that speaks Streamable HTTP directly. The bare host
(https://mcp.statsmapped.com, no path) redirects to the same endpoint as a courtesy.
What the client reports, and how to turn it off
After each tool call the client sends one small usage event to StatsMapped. It contains:
the tool name, whether the call succeeded, how it ended (answered, empty, error or unsupported) and its latency;
identifier-shaped arguments from a closed list, such as
stat_keyorarea_id, and never free text;a random install id kept in
~/.statsmapped-mcp/install_id.
To send nothing, set either of these in the server's environment (for example in the env block of your MCP client config):
STATSMAPPED_NO_LOG=1DO_NOT_TRACK=1(the cross-tool convention)
With either set, no event is sent and no install id is written.
Development
cd mcp-server
pip install -e .
python tests/test_client.pyThe test suite runs against the real live API (https://statsmapped.com by default, or
STATSMAPPED_MCP_BASE_URL if set) — read-only GETs only, nothing here writes any data or needs
a key.
Licence
MIT for this package. The underlying data keeps each publisher's own licence — see
statsmapped.com/ireland/sources for Ireland's own
publisher/licence detail before reusing any figure outside of querying it through an agent (a UK
equivalent page doesn't exist yet — check each UK tool response's own caveats/sources fields
in the meantime).
Available Tools
6 toolscompareAInspect
Use when the question is how areas rank or compare on a stat, or whether two stats can be compared
fairly. For one area's own figures use query_data.
Four modes, depending on which arguments are given -- consolidates what
were four separate tools (rank_areas, list_comparisons, get_comparison,
check_comparability) behind one, since they are all really "how does this
stat compare" at different scopes. Exactly one mode's arguments should be
given; mixing arguments from different modes (e.g. both stat_key and
pair_key, or only one of stat_key_a/stat_key_b) raises an error
rather than silently guessing which mode was meant.
stat_keyalone (nopair_key, nostat_key_a/stat_key_b): ranks every area at one geography level by its latest figure for that stat, for one country -- e.g. "which counties have the highest median sale price" (country="ireland").stat_keycomes fromquery_data's dataset-listing mode, for the SAME country.levelomitted uses this ranking's own default level; pass one of that dataset's owncompatible_levelsfor a different one -- a level this ranking doesn't have registered returns an empty list rather than an error. Where the underlying stat has no honest per-area denominator (crime, homelessness, live_register and similar -- StatsMapped's own RANKING_NO_DENOMINATOR_STATS), each row'srate_per_1000is the real figure to rank/compare by, notlatest_value, which is a raw count dominated by area population size. Always carry forward every entry incaveatswhen using a row in an answer.pair_keyalone: full detail for one registered comparison pair -- each axis's label, unit and publisher, the correlation stats (r, rho, and a leave-one-out sensitivity range naming the single most influential area), and caveats.pair_keycomes from mode 4's own response, for the SAME country.Both
stat_key_aandstat_key_bgiven: does StatsMapped have a registered, hand-vetted comparison between these two stats? Registry- backed only -- never computes a fresh correlation for an arbitrary pair. Both stat_keys come fromquery_data's dataset-listing mode, for the SAME country.verdictis one of"SUPPORT"(a real, hand-vetted registered pair with no open caveats -- may be treated as a confirmed relationship),"QUALIFY"(hand-vetted, but the evidence carries real caveats -- e.g. no robustness check for outliers, or an unverified geography-level join; readuncertaintyandreasonsbefore presenting it as confirmed),"REJECT"(a real structural impossibility or a human-vetted "no" -- the two stats share no geography level at all, or a reviewer rejected this exact pairing), or"INSUFFICIENT"(not registered, not ruled out either -- StatsMapped genuinely hasn't vetted this pair; never treat this as "probably comparable").uncertaintynames 4 separate dimensions (data_quality, comparability, statistical_strength, causal_strength) --causal_strengthis always"not_established", since no comparison here implies causation regardless of verdict.comparable(DEPRECATED, kept only for callers that haven't migrated) collapsesverdictto the old 3-way yes/no/unknown --"yes"for bothSUPPORTandQUALIFY(both mean "hand-vetted", the oldcomparablemeaning this field has always carried; the caveats aQUALIFYpair carries live inuncertainty/reasons, not in demotingcomparable),"no"forREJECT,"unknown"forINSUFFICIENT. Preferverdictdirectly when you need to distinguish a fully-confirmedSUPPORTfrom a caveatedQUALIFY. Readreasonsbefore presenting any answer other than"SUPPORT"as unqualified.None of the above given: lists every registered cross-dataset comparison pair for one country -- e.g. "median sale price vs new dwelling completions per 1,000 residents". A small, hand-curated set, not an arbitrary-pair engine: pass one of the returned
pair_keyvalues to mode 2 for the real correlation and axis detail.levelis only meaningful together withstat_key(mode 1); giving it withoutstat_keyraises rather than silently dropping it and falling through to mode 4's unrelated pair listing.
| Name | Required | Description | Default |
|---|---|---|---|
| level | No | ||
| country | No | ireland | |
| pair_key | No | ||
| stat_key | No | ||
| stat_key_a | No | ||
| stat_key_b | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations, so the description carries the full load and does: unregistered `level` returns an empty list rather than an error, mixed arguments raise, mode 3 never computes a fresh correlation and is registry-backed only, `causal_strength` is always 'not_established', `comparable` is deprecated with a precise mapping, and `caveats` must be carried forward. These are exactly the behavioral traits annotations would otherwise supply.
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?
Long but front-loaded with the when-to-use routing before the mode enumeration, and organized as a numbered list an agent can scan. Some passages, notably the deprecated `comparable` mapping, are verbose, though they still carry migration-relevant information.
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?
Output schema exists, so return values needn't be documented, yet the description still explains the verdict/uncertainty semantics an agent must interpret correctly. For a six-parameter, four-mode tool with no annotations, nothing needed to call it correctly is missing.
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 0%, so the description must compensate and it does: each of the six args is tied to a mode (stat_key, pair_key, stat_key_a/stat_key_b, level only with stat_key, country implied as 'SAME country' with an example). The only gap is that `country`'s accepted format/default is only shown by example, not defined.
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 and resource ('how areas rank or compare on a stat', 'whether two stats can be compared fairly') and explicitly distinguishes itself from the sibling `query_data` for single-area figures. The four modes are enumerated so an agent knows the full scope of the tool without opening the schema.
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?
Explicit when-to-use ('question is how areas rank or compare') and when-not ('For one area's own figures use query_data'). It also gives the exact arg-combination rule that selects each mode, warns that mixing arguments raises rather than silently guessing, and notes `level` without `stat_key` raises instead of falling through to mode 4.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
explain_metricAInspect
Use when the question is what a metric means or how it is measured; for a figure use query_data.
Definition, methodology and standing caveats for ONE stat ('ireland' or
'united-kingdom') -- never a current figure. Call this when the question is
about what a metric MEANS or how it's measured ("how is the claimant count
defined", "is this a mean or a median"), not about a specific area's value --
query_data/compare already answer that. stat_key comes
from query_data(country=...) for the SAME country.
| Name | Required | Description | Default |
|---|---|---|---|
| country | No | ireland | |
| stat_key | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are present, so the description carries the behavioral burden. It discloses the output nature (definition/methodology/caveats), the important constraint that it never returns a current figure, supported country values, and the stat_key dependency; it does not spell out read-only/no-side-effect or error behavior, but the core behavior is clear.
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 structure is front-loaded: usage rule, output scope, exclusions, then parameter provenance. However, the 'when to use' rule is repeated in the opening and again in the fourth sentence, so some trimming is possible.
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 simple two-parameter explanation tool with an output schema, the description supplies the critical routing, scope, and stat_key provenance. No major invocation detail is missing.
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 0%, so the description must compensate. It explains that stat_key comes from query_data(country=...) for the same country and lists the supported country values, covering both parameters, though it does not mention the default country or stat_key format.
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 that the tool returns definition, methodology, and standing caveats for one metric, and explicitly says it never returns a current figure. It distinguishes itself from query_data and compare by routing numeric questions to those 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?
It explicitly says to use this when the question is about what a metric means or how it is measured, not for a figure, and names query_data/compare as the alternatives. It also states where stat_key comes from, giving the agent a clear invocation path.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_sceneAInspect
Use when asked for a chart, still or short clip of a figure you can cite: returns the data to DRAW one scene, nothing rendered.
Today one scene exists, "ireland-builds" (Ireland's homes
granted permission, with a commencement notice and completed, by quarter from 2018Q1). The licence DIFFERS BY STAGE (see licence.stages): a stage whose licence is unconfirmed or
ShareAlike is withheld (its cells are absences, not zeros) and the licence line names its holder. You get rows, a table twin, alt text, notes, absences (a missing figure is a typed
absence, never a zero), the licence block, scene_hash, a receipt and the canonical URL. YOU draw it, and the last frame must match the table. Print the scene_hash and the licence
line in the first, middle and last frame, quote only numbers that are in rows, do not loop, and keep the "stages are not a cohort" note. purpose is "analytical" (default) or
"promotional": a promotional use of a source whose licence forbids advertising is refused (licence_refused). vintage (ISO date) omitted = the current data; an earlier vintage is
not stored and returns unknown_vintage. Example: get_scene(scene_id="ireland-builds").
| Name | Required | Description | Default |
|---|---|---|---|
| country | No | ireland | |
| purpose | No | analytical | |
| vintage | No | ||
| scene_id | No | ireland-builds |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With zero annotations the description carries the full load, and it does disclose real behaviour: read-only in effect ('nothing rendered'), licence gating per stage with withheld cells as absences rather than zeros, licence_refused for promotional use, and unknown_vintage for stale requests. Points are lost because a large share of the text enumerates return fields already declared in the output schema, and no size/pagination or cost characteristics are mentioned.
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 opening sentence is well front-loaded, but the body is a dense run-on with broken line-wrapping mid-clause ('a stage whose licence is unconfirmed or / ShareAlike is withheld') and mixes rendering instructions for the model with tool behaviour. Little is pure filler, yet the enumeration of payload fields duplicates the output schema and could be trimmed.
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 scene-delivery tool with an output schema and no annotations, the description covers the essential contract: licence hazards, absence semantics, refusal modes, and the hash/licence provenance requirement. The main hole is the undocumented `country` parameter; the field-by-field return listing is surplus given the output schema.
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 0%, so the description must compensate. It well documents scene_id (only one scene, with an example), purpose (analytical vs promotional with refusal consequence) and vintage (ISO date, omission yields current data, earlier vintages are not stored). The `country` parameter is never mentioned in the description or the schema, leaving one of four parameters entirely opaque.
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 and resource: it returns the data needed to DRAW one scene and nothing rendered. The scope ('one scene', currently 'ireland-builds') is concrete enough that an agent knows this is not a general data query, though it never names a sibling like query_data to contrast against.
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?
'Use when asked for a chart, still or short clip of a figure you can cite' gives an explicit triggering condition, and the promotional/analytical split plus the unknown_vintage rule clarify when a call will be refused. It stops short of telling the agent when NOT to use it or which sibling to prefer for tabular extraction.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_areasAInspect
Use when you need the ids and names of the areas (counties, local authorities, districts) to pass to
query_data.
List every geography at one boundary level, for one country ('ireland'
or 'united-kingdom'). level defaults to "county" (Ireland's 26 counties);
the UK's own primary level is "lad" (local authority districts), not
"county". Other levels exist per country (e.g. Ireland's "local_authority",
"garda_division") -- see a dataset's own compatible_levels from
query_data for which levels a given stat is actually published at.
Returns each area's id (used by query_data's area-scoped modes,
always paired with the SAME country), name and level. Slim by default;
include_parents=True adds each area's parents (the regions it sits in)
and Irish-language name.
| Name | Required | Description | Default |
|---|---|---|---|
| level | No | county | |
| country | No | ireland | |
| include_parents | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations exist, so the description carries the full burden and does well: it discloses output fields (`id`, `name`, `level`), that results are slim by default, what `include_parents=True` adds, and the pairing constraint that an `id` must always be used with the SAME `country` in `query_data`. It stops short of mentioning ordering, pagination, or whether the list is exhaustive per level, but the behavioral picture is largely complete for a read-only lookup.
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?
Front-loaded with the use case, then defaults, then caveats, then return shape — a sensible order with no filler sentences. It runs slightly long and repeats the `id`-is-for-`query_data` point twice, which is the only wasted effort.
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 three-optional-parameter lookup with no annotations, the description covers defaults, country/level coupling, the extended-output option, and the cross-tool key contract. An output schema exists, so the brief return-value sketch is sufficient and nothing needed to call it correctly is missing.
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 0%, so the description must compensate and it does: it gives `level`'s default ('county', 26 Irish counties), the country-specific twist that the UK's primary level is 'lad' rather than 'county', the allowed `country` values ('ireland' or 'united-kingdom'), and the exact effect of `include_parents`. That is meaning the schema cannot supply.
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 and resource ('list every geography at one boundary level, for one country') and immediately names its consumer, `query_data`. An agent can distinguish it from `query_data` without opening either schema.
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?
Opens with an explicit when-to-use ('Use when you need the ids and names of the areas ... to pass to `query_data`') and clarifies the division of labour by pointing to `compatible_levels` on `query_data` for per-dataset level availability. The when-not is implicit but strong: this tool lists geographies, `query_data` fetches statistics.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
notable_changesAInspect
Use when the question is what changed lately, which figures moved most, or what is new; for one area's full history use query_data.
Returns statistical movements databeat flagged as notable, not verdicts on what they mean; limit is 1 to 50 (default 8), and stat_key or geography_id narrows the list.
Ireland and united-kingdom. Cite StatsMapped (https://statsmapped.com) as the source. Source: GET /{country}/api/v1/alerts/notable.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| country | No | ireland | |
| stat_key | No | ||
| geography_id | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and mostly does: it discloses that results are flagged movements rather than verdicts, that `limit` is bounded 1–50 with default 8, and the underlying endpoint (GET /{country}/api/v1/alerts/notable), which implies read-only behavior. It also adds an obligation the agent must honor — citing StatsMapped. It stops short of describing ordering, pagination, or an auth requirement, so it is strong but not exhaustive.
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?
Front-loaded with the usage trigger and the sibling routing before any mechanics, which is the right order. Slightly redundant at the tail, where the citation instruction and the raw endpoint both appear, but both carry information an agent needs.
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?
An output schema exists, so return values need no explanation, and the description covers when-to-use, parameter bounds, geo scope, and a citation obligation. What remains unaddressed is how to obtain valid `stat_key`/`geography_id` values, a minor but real gap for a zero-coverage schema.
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 0%, so the description must compensate, and it does for all four parameters: `limit` range and default, `stat_key` and `geography_id` as narrowing filters, and `country` limited to Ireland and united-kingdom. It does not explain what a valid `stat_key` or `geography_id` looks like (slug format, discovery via list_areas), which leaves a real gap for the two filter parameters.
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-like resource ('statistical movements databeat flagged as notable') and the question it answers ('what changed lately, which figures moved most'), which is a clear purpose. It also explicitly names the sibling it is not: 'for one area's full history use query_data'. An agent can distinguish this from query_data, compare, or explain_metric without opening any schema.
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?
Gives explicit trigger conditions (what changed lately, which figures moved most, what is new) and names the alternative plus the condition that selects it (`query_data` for one area's full history). It also sets a scope boundary — countries Ireland and united-kingdom — so the agent knows the applicability envelope.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
query_dataAInspect
Use when you need to find which datasets exist, which exist for one area, or the figures and history
for one area and dataset (or a council planning view). For what a metric means use explain_metric;
for how areas rank use compare.
Three modes, depending on which of area_id/dataset are given (plus a planning mode, council, described last) --
consolidates what were three separate tools (list_datasets,
list_area_datasets, get_dataset_for_area) behind one, since they are all
really "how do I get data" at different levels of specificity:
Neither
area_idnordataset: lists every dataset (stat) StatsMapped tracks for one country ('ireland' or 'united-kingdom'), with its key, human label, and which geography levels it can be shown at. Ireland and the UK track genuinely different datasets -- call this first for the right country before assuming a stat_key exists there, to find the rightstat_keyforcompare's ranking mode.area_idgiven,datasetomitted: lists every dataset available for that one area (e.g. "county:kerry" for Ireland, "uk:lad:e09000033" for the UK), with its latest figure, year-on-year change, and caveat labels only (not full caveat text -- use mode 3 for the full detail on any one dataset that matters). Passstat_key(from mode 1) to list only that stat's series for the area: a full listing is tens of KB, one stat is a few hundred bytes.area_idcomes fromlist_areas;countrymust match whichever country that call used, or this simply 404s ("unknown geography").Both
area_idanddatasetgiven: full detail for one dataset in one area -- the latest figure, a written summary, full caveat text, and (ifhistory_monthsis set) recent history.datasetis aseries_keyfrom mode 2's own response.history_monthsmeans actual months of history (0 = everything) -- e.g. 24 returns 2 years of an annual series, not 24 years.countrymust matcharea_id's own country. A stat key from mode 1 is also accepted asdatasetwhen the area has exactly one series for it (the reply saysresolved_from_stat_key); with several, the error names the series keys to use.councilalone (an Irish council slug, e.g. "cork-city-council"; country "ireland" only; no other argument): that council's planning applications by year received -- count, grant and refusal share of decided applications, median days to a decision -- with source, licence, the last data date, a receipt, plain notes, and typedabsencesinstead of zeros. A council the national planning feed has stopped carrying (for example Cork City, last record 2025-11-04) saysstatus: "stopped_reporting": a low recent figure is a feed gap, not fewer applications. Example: query_data(council="cork-city-council").datasetandhistory_monthsare only meaningful together witharea_id(and, forhistory_months,datasettoo, since it only applies to mode 3); giving either without its real precondition raises rather than silently dropping the argument and dispatching to the wrong mode.
| Name | Required | Description | Default |
|---|---|---|---|
| area_id | No | ||
| council | No | ||
| country | No | ireland | |
| dataset | No | ||
| stat_key | No | ||
| history_months | No |
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 carries the full behavioral burden and does so well: it explains mode dispatch, error behavior for mismatched country/area, 404s for unknown geography, raises for invalid argument combinations, response sizes, caveat handling, `resolved_from_stat_key`, and `stopped_reporting` status. It also clarifies that `history_months` means actual months rather than periods of the series.
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 long, but the length is largely justified by four distinct modes and several argument interactions. It is front-loaded with a usage statement and structured into numbered modes, though some passages could be tightened without losing meaning.
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 six parameters with zero schema coverage, no annotations, and an output schema, the description provides all the missing invocation context an agent needs. It covers mode selection, parameter dependencies, error cases, output characteristics, and special status handling.
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 0%, so the description must compensate, and it does: every parameter is explained in context, including `area_id`, `country`, `dataset`, `stat_key`, `history_months`, and `council`. It adds semantics the schema lacks, such as country matching, `series_key` sourcing, `stat_key` acceptance, and `history_months=0` meaning all history.
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 gives a specific multi-mode purpose: finding datasets, area-specific datasets, figures/history for an area and dataset, and Irish council planning data. It explicitly consolidates three former tools and distinguishes the sibling tools `explain_metric` and `compare` by their roles.
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?
It states when to use the tool and names alternatives for adjacent questions: `explain_metric` for metric meaning and `compare` for rankings. The four modes are keyed to which arguments are supplied, with preconditions such as `area_id` coming from `list_areas` and `dataset` coming from mode 2.
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.
1 tool update
v0.3.5- Added
notable_changes
3 tool updates
v0.3.4- Added
get_scene - Changed
list_areas1 field changed- added
Input schema / properties / include_parentsAdded value: +{ + "default": false, + "title": "Include Parents", + "type": "boolean" +}
- Changed
query_data2 fields changed- added
Input schema / properties / councilAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Council" +} - added
Input schema / properties / stat_keyAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Stat Key" +}
9 tool updates
v0.3.0- Removed
check_comparability - Added
compare - Removed
get_comparison - Removed
get_dataset_for_area - Removed
list_area_datasets - Removed
list_comparisons - Removed
list_datasets - Added
query_data - Removed
rank_areas
9 tool updates
v0.1.0- First observed
check_comparability - First observed
explain_metric - First observed
get_comparison - First observed
get_dataset_for_area - First observed
list_area_datasets - First observed
list_areas - First observed
list_comparisons - First observed
list_datasets - First observed
rank_areas
TDQS
Scored across 6 tools
The six tools cover mostly distinct intents (metadata, area lookup, data retrieval, charts, notable changes, comparisons), and descriptions repeatedly cross-reference each other to steer selection. However, `query_data` and `compare` each pack four modes under one name, creating boundary friction (e.g. ranking latest figures in `compare` vs returning latest figures in `query_data`), and `notable_changes` overlaps with fetching recent history.
Names mix verb_noun forms (`explain_metric`, `list_areas`, `query_data`, `get_scene`) with a bare verb (`compare`) and a noun phrase (`notable_changes`). The convention is readable and partly predictable, but not uniform across the set.
Six tools is a sensible, well-scoped count for this domain. Each tool earns its place, though several are heavy multi-mode dispatchers (`query_data` and `compare` each have four modes), making the effective surface larger than six.
The surface covers dataset discovery, metric definitions/caveats, area listings, area-level figures with history, rankings/comparability, recent notable changes, and a chart scene. Minor gaps exist (no general name-based search, and council planning is Ireland-only), but core statistical browsing workflows are covered.
Maintenance
Related MCP Connectors
Read-only Irish public data for AI assistants: stats, weather, transport, law, property and maps.
Query UK Parliament, elections, crime stats, ONS census data, and national archives
Official statistics for AI agents: Eurostat, World Bank, OECD, IMF and WHO data for 150+ countries.
UK property research tools - crime stats, schools, demographics, valuations for AI.
Related MCP Servers
- AlicenseAqualityCmaintenanceEnables AI agents to perform due diligence on Irish properties by querying public datasets for planning applications, sold prices, flood risk, radon risk, and zoning.174 npm8MIT

ELS MCP serverofficial
FlicenseNot gradedqualityBmaintenanceEnables LLM agents to query the Explore Local Statistics API for local area data like employment rates and demographics.-- AlicenseNot gradedqualityBmaintenanceEnables AI agents to search, inspect, and retrieve Irish Central Statistics Office PxStat datasets through MCP tools. Supports catalog search, metadata discovery, full-table reads, and filtered JSON-stat queries.450 npmMIT
- AlicenseNot gradedqualityBmaintenanceEnables AI assistants to search, preview, and query Ireland's public-sector open data catalogue, including CSV, Excel, JSON, GeoJSON, and JSON-stat resources. It supports filtering, grouping, counting, summing, and sorting datasets conversationally without manual downloads or cleanup.MIT