UK ONS MCP Server
This server provides access to UK Office for National Statistics (ONS) data, enabling you to discover, search, and retrieve official government statistics — no API key required.
List Datasets: Browse the full ONS dataset catalogue with pagination support.
Search Datasets: Find datasets by keyword, title, description, or ID (e.g. search "inflation" to find
cpih01).Get Dataset Metadata: Retrieve detailed metadata for a specific dataset by its ID.
Discover Dimensions: Learn about a dataset's required dimensions, including option counts and sample codes — essential before querying observations.
Get Dimension Options: Page through the complete list of valid option codes for any specific dimension.
Retrieve Observations: Fetch specific data points by supplying values for all dimensions, with exactly one wildcard (
*) allowed to vary a single dimension.Get Latest Data: Quickly obtain the most recent observations using auto-filled defaults (
time=*,geography=K02000001for UK-wide), with optional filters.Access Curated Resources: Use
ons://popular_datasetsfor a list of common dataset IDs, andons://api_infofor API details and recommended workflow.
All operations are read-only GET requests against the public ONS API, with input validation and bounded responses.
Click on "Install 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., "@UK ONS MCP Serverwhat's the latest UK inflation rate?"
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.
UK ONS MCP Server
A Model Context Protocol (MCP) server for the UK Office for National Statistics (ONS) CMD API (https://api.beta.ons.gov.uk/v1).
Query official UK government statistics — inflation, GDP, wellbeing, trade, deaths and more — straight from your MCP-compatible assistant. No API key required.
Features
Direct ONS access — no authentication, no tokens
Browse & search the full published dataset catalogue
Dimension discovery — inspect a dataset's dimensions and valid option codes before querying
Real observations — pull data points filtered by geography, time and any other dimension
Latest-data shortcut that auto-fills sensible defaults
TypeScript, native
fetch, zero runtime deps beyond the MCP SDK and ZodInput validation and actionable, self-correcting error messages
Related MCP server: GovUK MCP Server
Requirements
Node.js >= 18.17 (uses the global
fetchandAbortSignal.timeout)
Recommended agent workflow
The ONS observations endpoint requires a value for every dimension of a dataset, and allows exactly one wildcard *. The intended flow is:
search_datasets— find a dataset id by keyword (e.g."inflation"->cpih01).get_dataset_dimensions— learn the required dimensions and see sample option codes.get_observation— request data, giving each dimension a value and using*for the one you want to vary.
get_latest_data is a convenience wrapper: it auto-fills time="*" and geography="K02000001" (UK) and any single-option dimension. If a dataset needs more choices, it returns the available options so you can switch to get_observation.
Available Tools
Tool | Purpose |
| Paginated list of all datasets ( |
| Keyword search over id/title/description/keywords. |
| Full metadata for one dataset by id. |
| Dimensions of a dataset's latest version, with option counts and samples. Call before |
| Page through the full list of valid option codes for one dimension. |
| Retrieve observations. Every dimension needs a value; exactly one may be |
| Latest observations with auto-filled |
Resources
URI | Description |
| Curated, live-verified list of common dataset ids. |
| API base URL, auth model and the recommended workflow. |
Example
Query CPIH (UK inflation) as a UK-wide time series:
// 1) discover dimensions
get_dataset_dimensions { "dataset_id": "cpih01" }
// -> dimensions: aggregate (122 options, e.g. CP00 "Overall Index"), geography, time
// 2) fetch the Overall Index across all time periods for the UK
get_observation {
"dataset_id": "cpih01",
"dimensions": { "time": "*", "geography": "K02000001", "aggregate": "CP00" }
}Omitting a required dimension returns a helpful error listing what is missing and sample codes to use, so an agent can retry without guessing.
Installation & configuration
Option A — npx (published package)
No install step; the client runs it on demand.
Claude Desktop (claude_desktop_config.json) or Claude Code (.mcp.json):
{
"mcpServers": {
"uk-ons": {
"command": "npx",
"args": ["-y", "uk_ons_mcp_server"]
}
}
}Option B — local build (from source)
git clone https://github.com/dwain-barnes/uk-ons-mcp-server.git
cd uk-ons-mcp-server
npm install
npm run buildThen point your client at the built entry point (use an absolute path):
{
"mcpServers": {
"uk-ons": {
"command": "node",
"args": ["/absolute/path/to/uk_ons_mcp_server/dist/index.js"]
}
}
}On Windows, use a full path such as C:\\Users\\you\\uk_ons_mcp_server\\dist\\index.js.
Claude Code can also add it from the CLI:
claude mcp add uk-ons -- node /absolute/path/to/uk_ons_mcp_server/dist/index.jsDevelopment
npm install
npm run build # compile TypeScript to dist/
npm start # run the built server on stdio
npm run dev # tsc --watch
npm run clean # remove dist/
npm test # build, then run the end-to-end smoke test against the live APIThe smoke test (test/smoke.mjs) spawns the built server over stdio with the MCP SDK client and checks all seven tools plus a resource end-to-end.
Security notes
Read-only. Every tool only performs
GETrequests against the public ONS API; nothing is written or mutated.No authentication or secrets. The ONS CMD API is open and keyless, so there are no tokens to store or leak.
Input validation. Dataset ids, editions, versions and dimension names are validated against a strict character set (
[A-Za-z0-9._-], max 100 chars) and every path/query value is URL-encoded before a request is made. Dimension values may additionally be the single wildcard*.Bounded responses. Observation results are capped (with a
truncatedflag and total count) to avoid overwhelming the model's context.
License
MIT — see LICENSE.
Disclaimer This project is unofficial and not endorsed by the UK Office for National Statistics. Data usage remains subject to ONS terms and the Open Government Licence.
Available Tools
5 toolsget_datasetC
Get detailed information about a specific dataset
| Name | Required | Description | Default |
|---|---|---|---|
| dataset_id | Yes | The ID of the dataset to retrieve |
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 of behavioral disclosure. It states the tool retrieves detailed information but does not specify whether this is a read-only operation, if it requires authentication, what format the output takes, or any rate limits. This leaves significant gaps in understanding the tool's behavior.
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 a single, efficient sentence that directly states the tool's purpose without unnecessary words. It is front-loaded and wastes no space, making it easy for an agent to parse quickly.
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 lack of annotations and output schema, the description is incomplete for a tool that retrieves detailed information. It does not explain what 'detailed information' includes, the response format, or error handling, leaving the agent with insufficient context to use the tool effectively beyond basic parameter input.
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, with the parameter 'dataset_id' fully documented in the schema. The description adds no additional meaning beyond implying retrieval of a 'specific dataset', which aligns with the schema but does not provide extra context like ID format or examples. Baseline 3 is appropriate as the schema handles the heavy lifting.
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 verb ('Get') and resource ('detailed information about a specific dataset'), making the purpose understandable. However, it does not explicitly differentiate from sibling tools like 'list_datasets' or 'search_datasets', which likely serve different purposes (listing vs. retrieving specific details).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to use this tool versus alternatives. It does not mention prerequisites, such as needing a dataset ID, or compare it to siblings like 'list_datasets' for browsing or 'get_observation' for different data types, leaving the agent without context for selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_latest_dataC
Get the latest available data for a dataset with optional filters
| Name | Required | Description | Default |
|---|---|---|---|
| dataset_id | Yes | The ID of the dataset | |
| geography | No | Geographic filter (e.g., K02000001 for UK) | |
| time_period | No | Time period filter (e.g., 2023, Q1-2023) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries full burden for behavioral disclosure. It states it 'gets' data (implying read-only) but doesn't mention authentication requirements, rate limits, error conditions, or what 'latest' means in terms of data freshness or update frequency. The description is minimal and lacks important operational context.
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 a single, efficient sentence that communicates the core functionality without unnecessary words. It's appropriately sized for a straightforward data retrieval tool and front-loads the essential 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?
For a data retrieval tool with no annotations and no output schema, the description is insufficient. It doesn't explain what 'latest' means operationally, what format the data returns in, whether there are pagination considerations, or how it differs from sibling tools. The description leaves too many contextual gaps for effective 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 description coverage is 100%, so the schema already documents all three parameters thoroughly. The description adds minimal value by mentioning 'optional filters' which aligns with the geography and time_period parameters, but doesn't provide additional context beyond what's in the schema descriptions.
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 action ('Get') and resource ('latest available data for a dataset'), making the purpose understandable. It distinguishes from siblings like 'get_dataset' by specifying 'latest' data rather than general dataset info, but doesn't explicitly contrast with 'get_observation' which might retrieve specific data points.
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 mentions 'optional filters' but provides no guidance on when to use this tool versus alternatives like 'get_observation' or 'search_datasets'. There's no indication of prerequisites, typical use cases, or scenarios where other tools would be more appropriate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_observationC
Get specific data observations with dimension filters
| Name | Required | Description | Default |
|---|---|---|---|
| dataset_id | Yes | The ID of the dataset | |
| edition | No | Dataset edition | time-series |
| version | No | Dataset version | latest |
| dimensions | Yes | Dimension filters as key-value pairs (e.g., {"geography": "K02000001", "time": "2023"}) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries full burden but offers minimal behavioral insight. It mentions 'Get' (implying read-only) and 'dimension filters' but doesn't disclose permissions, rate limits, pagination, error conditions, or what 'observations' contain. For a data retrieval tool with 4 parameters and nested objects, this leaves significant gaps in understanding how it behaves.
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 a single, efficient sentence that directly states the tool's purpose. It's appropriately front-loaded with the core action. However, it could be slightly more specific (e.g., mentioning it returns data points rather than just 'observations').
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 data retrieval tool with 4 parameters (including nested objects), no annotations, and no output schema, the description is inadequate. It doesn't explain what 'observations' are (e.g., data points, records), how results are structured, or any behavioral aspects like pagination or error handling. The agent would struggle to use this effectively without trial and error.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema fully documents all 4 parameters. The description adds marginal value by implying 'dimensions' are used for filtering, but doesn't provide additional syntax, format examples, or constraints beyond what the schema already states. Baseline 3 is appropriate when schema does the heavy lifting.
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 action ('Get') and resource ('specific data observations') with additional context about 'dimension filters'. It distinguishes from siblings like 'get_dataset' (metadata) and 'list_datasets' (listing) by focusing on actual data retrieval with filtering. However, it doesn't explicitly differentiate from 'get_latest_data' which might also retrieve 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 provides no guidance on when to use this tool versus alternatives like 'get_latest_data' or 'search_datasets'. It mentions 'dimension filters' but doesn't explain when filtering is needed versus other retrieval methods. No prerequisites, exclusions, or comparative context is provided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_datasetsB
List available ONS datasets with metadata
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum number of datasets to return | |
| offset | No | Offset for pagination |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It mentions metadata is included, which is helpful, but doesn't describe important behavioral aspects like whether this is a read-only operation (implied but not stated), what format the metadata includes, whether results are paginated (schema shows pagination parameters but description doesn't mention this), or any rate limits or authentication requirements. For a listing tool with zero annotation coverage, this leaves significant gaps.
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 a single, efficient sentence that communicates the core purpose without any wasted words. It's appropriately sized for a listing tool and front-loads the essential information. Every word earns its place, making it easy for an AI agent to quickly understand what the tool does.
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 this is a relatively simple listing tool with 2 parameters and no output schema, the description provides the basic purpose but lacks important context. It doesn't explain what 'metadata' includes, doesn't mention the pagination behavior (though parameters suggest it), and doesn't differentiate from sibling tools. While adequate for understanding the tool's basic function, there are clear gaps that could help an agent use it more effectively.
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 schema description coverage is 100%, with both parameters ('limit' and 'offset') well-documented in the schema itself. The description doesn't add any parameter-specific information beyond what's already in the schema. According to the scoring rules, when schema coverage is high (>80%), the baseline is 3 even with no param info in the description, which applies here.
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 verb ('List') and resource ('ONS datasets with metadata'), making the purpose immediately understandable. It distinguishes from siblings like 'get_dataset' (retrieves specific dataset) and 'search_datasets' (filters datasets), though it doesn't explicitly mention these distinctions. The description is specific enough to understand what the tool does without being tautological.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to use this tool versus alternatives like 'search_datasets' or 'get_dataset'. It doesn't mention any prerequisites, context for usage, or limitations. While the purpose is clear, there's no explicit or implied guidance about when this specific listing tool should be selected over other dataset-related tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_datasetsB
Search for datasets by name or description
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | Search query for datasets | |
| limit | No | Maximum number of results |
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 of behavioral disclosure. It states the tool searches datasets, but doesn't describe how results are returned (e.g., format, pagination), whether it's read-only (implied but not stated), performance characteristics, or error handling. For a search tool with zero annotation coverage, this leaves significant gaps in understanding its behavior.
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 a single, efficient sentence that directly states the tool's purpose without unnecessary words. It's front-loaded with the core action and resource, making it easy to parse. Every word earns its place, with no redundancy or fluff.
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 moderate complexity (search operation with 2 parameters), 100% schema coverage, and no output schema, the description is minimally adequate. It covers the basic purpose but lacks details on behavioral traits (e.g., result format, read-only nature) and usage guidelines versus siblings. Without annotations or output schema, more context would be beneficial for full understanding.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, with clear documentation for both parameters ('query' and 'limit'). The description adds no additional meaning beyond what the schema provides—it mentions searching by name or description, but the schema already describes 'query' as a search query for datasets. Baseline 3 is appropriate when the schema does the heavy lifting.
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 verb ('search') and resource ('datasets'), and specifies the searchable fields ('by name or description'). It distinguishes from siblings like 'get_dataset' (retrieves specific dataset) and 'list_datasets' (likely lists all without filtering). However, it doesn't explicitly differentiate from 'get_latest_data' or 'get_observation', which might be related but not identical search operations.
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 searching datasets by name or description, but provides no explicit guidance on when to use this tool versus alternatives like 'list_datasets' (which might list all datasets without filtering) or 'get_dataset' (which retrieves a specific dataset by ID). There's no mention of prerequisites, exclusions, or comparative scenarios.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
TDQS
Each tool has a clearly distinct purpose: list_datasets and search_datasets handle dataset discovery, get_dataset retrieves metadata, get_latest_data provides filtered current data, and get_observation targets specific data points. There is no overlap or ambiguity between these functions.
All tools follow a consistent verb_noun pattern with snake_case (get_dataset, get_latest_data, get_observation, list_datasets, search_datasets). The naming is predictable and follows a clear convention throughout.
With 5 tools, this server is well-scoped for accessing UK ONS data. The count is appropriate, covering dataset discovery, metadata retrieval, and data access without being too sparse or bloated.
The toolset provides strong coverage for data retrieval and discovery in the ONS domain, including listing, searching, and accessing datasets and observations. A minor gap is the lack of update or administrative tools, but this is reasonable for a read-only data access server.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Query UK Parliament, elections, crime stats, ONS census data, and national archives
UK Office for National Statistics dataset catalogue + Beta JSON API
UK ONS MCP — Office for National Statistics (no auth)
Access European statistics: GDP, unemployment, inflation, population data.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceEnables querying UK Office for National Statistics datasets and their editions through natural language, with no authentication required.14MIT
- AlicenseBqualityDmaintenanceProvides access to 27 UK government data sources and services, enabling queries about transport, business, healthcare, and more via natural language.331MIT
- FlicenseAqualityDmaintenanceEnables AI assistants to query NHS public health datasets, including prescribing data, dataset exploration, and organisation lookup via the NHSBSA Open Data Portal.9
- AlicenseAqualityBmaintenanceProvides access to UK economic, social, and labour-market statistics via the ONS beta and Nomis APIs, enabling discovery and retrieval of time series, datasets, and census data.18MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/dwain-barnes/uk-ons-mcp-server'
If you have feedback or need assistance with the MCP directory API, please join our Discord server