Skip to main content
Glama
dwain-barnes

UK ONS MCP Server

by dwain-barnes

UK ONS MCP Server

npm version License: MIT GitHub

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 Zod

  • Input validation and actionable, self-correcting error messages


Related MCP server: GovUK MCP Server

Requirements

  • Node.js >= 18.17 (uses the global fetch and AbortSignal.timeout)


The ONS observations endpoint requires a value for every dimension of a dataset, and allows exactly one wildcard *. The intended flow is:

  1. search_datasets — find a dataset id by keyword (e.g. "inflation" -> cpih01).

  2. get_dataset_dimensions — learn the required dimensions and see sample option codes.

  3. 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

list_datasets

Paginated list of all datasets (limit 1-1000, offset).

search_datasets

Keyword search over id/title/description/keywords.

get_dataset

Full metadata for one dataset by id.

get_dataset_dimensions

Dimensions of a dataset's latest version, with option counts and samples. Call before get_observation.

get_dimension_options

Page through the full list of valid option codes for one dimension.

get_observation

Retrieve observations. Every dimension needs a value; exactly one may be *.

get_latest_data

Latest observations with auto-filled time="*" / geography=UK defaults.

Resources

URI

Description

ons://popular_datasets

Curated, live-verified list of common dataset ids.

ons://api_info

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 build

Then 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.js

Development

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 API

The 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 GET requests 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 truncated flag 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 tools
get_datasetC

Get detailed information about a specific dataset

ParametersJSON Schema
NameRequiredDescriptionDefault
dataset_idYesThe ID of the dataset to retrieve

TDQS

C2.9/5.0
Behavior2/5

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.

Conciseness5/5

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.

Completeness2/5

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.

Parameters3/5

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.

Purpose4/5

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.

Usage Guidelines2/5

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

ParametersJSON Schema
NameRequiredDescriptionDefault
dataset_idYesThe ID of the dataset
geographyNoGeographic filter (e.g., K02000001 for UK)
time_periodNoTime period filter (e.g., 2023, Q1-2023)

TDQS

C2.9/5.0
Behavior2/5

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.

Conciseness5/5

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.

Completeness2/5

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.

Parameters3/5

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.

Purpose4/5

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.

Usage Guidelines2/5

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

ParametersJSON Schema
NameRequiredDescriptionDefault
dataset_idYesThe ID of the dataset
editionNoDataset editiontime-series
versionNoDataset versionlatest
dimensionsYesDimension filters as key-value pairs (e.g., {"geography": "K02000001", "time": "2023"})

TDQS

C2.9/5.0
Behavior2/5

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.

Conciseness4/5

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.

Completeness2/5

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.

Parameters3/5

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.

Purpose4/5

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.

Usage Guidelines2/5

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

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum number of datasets to return
offsetNoOffset for pagination

TDQS

B3.1/5.0
Behavior2/5

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.

Conciseness5/5

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.

Completeness3/5

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.

Parameters3/5

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.

Purpose4/5

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.

Usage Guidelines2/5

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

ParametersJSON Schema
NameRequiredDescriptionDefault
queryYesSearch query for datasets
limitNoMaximum number of results

TDQS

B3.3/5.0
Behavior2/5

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.

Conciseness5/5

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.

Completeness3/5

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.

Parameters3/5

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.

Purpose4/5

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.

Usage Guidelines3/5

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

A3.5/5.0
Disambiguation5/5

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.

Naming Consistency5/5

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.

Tool Count5/5

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.

Completeness4/5

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

ActivitySlowing
ResponsivenessUnresponsive

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

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables querying UK Office for National Statistics datasets and their editions through natural language, with no authentication required.
    14
    MIT
  • F
    license
    A
    quality
    D
    maintenance
    Enables AI assistants to query NHS public health datasets, including prescribing data, dataset exploration, and organisation lookup via the NHSBSA Open Data Portal.
    9
  • A
    license
    A
    quality
    B
    maintenance
    Provides 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.
    18
    MIT

Latest Blog Posts

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