cyanheads avatar

Eurostat Mcp Server

cyanheads/eurostat-mcp-server

Wraps the Eurostat Statistics and TOC APIs to make 8,933 EU datasets searchable and queryable through MCP. You get five tools: keyword search across the catalogue, theme tree navigation, dataset metadata inspection, dimension value enumeration, and filtered data queries with NUTS geo-level support. The query tool decodes JSON-stat 2.0 responses into labeled observations and catches Eurostat's async-response warnings before they silently fail. Useful when you need programmatic access to EU economy, demography, trade, or regional statistics without manually navigating the web interface or writing your own API client. Ships with a public hosted instance at eurostat.caseyjhand.com and runs locally via stdio or HTTP.

GitHub stars
9
tools
8
transport
STDIO, HTTP
env vars
20
last updated
Nov 8, 2026

Install

From registry metadata
$ npx add-mcp https://eurostat.caseyjhand.com/mcp --name eurostat

Run in your terminal. add-mcp asks which agents to add it to (Claude Code, Codex, Cursor and more). Add -g to install it for every project.

Review the command, arguments and environment values before installing. MCP servers run with your local permissions.

Other ways

Claude Code

$ claude mcp add --transport http eurostat https://eurostat.caseyjhand.com/mcp

Run in your terminal. Add --scope user to make it available in every project.

Tools

Verified live · 8 tools

Verified live against the running server on Nov 6, 2026.

eurostat_search_datasetsSearch the Eurostat catalogue by keyword. Returns matching datasets with codes, descriptions, period coverage, and theme breadcrumbs. Use this to discover dataset codes before calling eurostat_get_dataset_info, then eurostat_query_dataset for a slice of a dataset or eurostat_d...3 params

Search the Eurostat catalogue by keyword. Returns matching datasets with codes, descriptions, period coverage, and theme breadcrumbs. Use this to discover dataset codes before calling eurostat_get_dataset_info, then eurostat_query_dataset for a slice of a dataset or eurostat_d...

Parameters* required
cursorstring
Opaque pagination cursor from a previous call's nextCursor. Omit for the first page; pass it back — with the same query — to fetch the next page of matches over a stable order. A cursor is bound to...
limitnumber
Page size — maximum datasets returned per page. Default 20; positive integers above 100 are clamped to 100 with a notice. To retrieve matches beyond one page, pass the returned nextCursor back as c...default: 20
query*string
Search terms — at least one non-whitespace token is required. Split on whitespace into tokens; every token must match (AND), case-insensitively, somewhere across the dataset label, theme breadcrumb...
eurostat_browse_themesNavigate the Eurostat theme tree. Without theme_code returns the top-level theme folders (Economy, Population, Transport, etc.) — the practical starting points. With a theme_code returns its immediate children: subtheme folders and datasets in that branch. Use this for structu...1 params

Navigate the Eurostat theme tree. Without theme_code returns the top-level theme folders (Economy, Population, Transport, etc.) — the practical starting points. With a theme_code returns its immediate children: subtheme folders and datasets in that branch. Use this for structu...

Parameters* required
theme_codestring
Folder code to expand (e.g., "economy", "reg"). Exact codes take precedence, then case-insensitive matching applies. Omit to list the top-level theme folders.
eurostat_get_dataset_infoFetch metadata for a Eurostat dataset: dimensions with valid values, time range, observation count, and last-update date. Call this before eurostat_query_dataset or eurostat_download_dataset to discover what dimension codes are valid (unit, na_item, geo, etc.); eurostat_downlo...1 params

Fetch metadata for a Eurostat dataset: dimensions with valid values, time range, observation count, and last-update date. Call this before eurostat_query_dataset or eurostat_download_dataset to discover what dimension codes are valid (unit, na_item, geo, etc.); eurostat_downlo...

Parameters* required
dataset_code*string
Dataset code (e.g., "nama_10_gdp", or "DS-045409" for a Comext collection). Use eurostat_search_datasets or eurostat_browse_themes to find codes.
eurostat_get_dimension_valuesList the valid values for a dimension in a Eurostat dataset, preserving value codes and labels exactly. Use this when eurostat_get_dataset_info returns more values than its sample, or to confirm exact filter codes before querying. Dimension identifiers match exactly first, the...7 params

List the valid values for a dimension in a Eurostat dataset, preserving value codes and labels exactly. Use this when eurostat_get_dataset_info returns more values than its sample, or to confirm exact filter codes before querying. Dimension identifiers match exactly first, the...

Parameters* required
canvas_idstring
Also stage the values on this dataframe canvas as a table with two columns, code and label, holding every value the dimension lists at the geo_level requested (country when it is omitted), whatever...
cursorstring
Opaque nextCursor from the previous page; omit for the first page. It resumes after that page's last code and is bound to dataset_code, dimension, geo_level and filter, so send those unchanged. Can...
dataset_code*string
Dataset code (e.g., "nama_10_gdp", or "DS-045409" for a Comext collection).
dimension*string
Dimension code to retrieve values for (e.g., "unit", "na_item", "geo"). Exact match first, then case-insensitive; TIME_PERIOD aliases time. Use eurostat_get_dataset_info to see available dimensions.
filterstring
Words to find, up to 500 characters: keeps only values whose code and label, joined by a space, contain every whitespace-separated word as a substring — in any order, ignoring case and accents ("pa...
geo_levelstring
NUTS hierarchy level filter — applies only when dimension is "geo"; passing it with any other dimension is rejected. Options: "aggregate" (EU/EA codes), "country" (2-letter codes, default), "nuts1"...one of aggregate · country · nuts1 · nuts2 · nuts3
limitnumber
Most values per page, default 25, maximum 1,000. Larger positive integers clamp with a notice when EUROSTAT_CLAMP_LIMITS is enabled. Fixed by the first call: with cursor, the cursor carries that li...default: 25
eurostat_query_datasetFetch statistical data from a Eurostat dataset with dimension filters. Returns a deterministic inline prefix of decoded observations with dimension codes and labels, numeric values, an OBS_FLAG status (e.g., "p" = provisional, "e" = estimated) and a separate CONF_STATUS confid...10 params

Fetch statistical data from a Eurostat dataset with dimension filters. Returns a deterministic inline prefix of decoded observations with dimension codes and labels, numeric values, an OBS_FLAG status (e.g., "p" = provisional, "e" = estimated) and a separate CONF_STATUS confid...

Parameters* required
canvas_idstring
Reuse an existing dataframe canvas, so a result staged by this call lands beside earlier ones and can be joined against them. Pass the canvasId a previous eurostat_query_dataset or eurostat_downloa...
dataset_code*string
Dataset code (e.g., "nama_10_gdp"). Required. A DS-* code — Comext detailed trade or PRODCOM, in any case — is served by the Comext host: filter freq on its trade flows, which mix annual and monthl...
filtersobject
Dimension filters as a map of dimension code → array of valid values. Example: {"unit": ["CP_MEUR"], "na_item": ["B1GQ"], "geo": ["DE", "FR"]}. An empty array is treated as no filter for that dimen...
geo_levelstring
Filter by NUTS hierarchy level. Mutually exclusive with a "geo" key in filters. Options: "aggregate" (EU/EA totals), "country" (41 member/candidate states), "nuts1" (127 major regions), "nuts2" (30...one of aggregate · country · nuts1 · nuts2 · nuts3
langstring
Language for labels in the response. Default is "EN". Options: "EN", "FR", "DE".one of EN · FR · DEdefault: EN
last_n_periodsnumber
Return only the N most recent dataset time positions. Selected periods without populated cells for this slice are disclosed in a notice on successful queries. N counts back from the dataset's lates...
preview_limitnumber
How many matched observations to return inline, from the deterministic start of the JSON-stat cell order. Default 25; positive integers above 500 are clamped to 500 with a notice. This changes only...default: 25
since_periodstring
Start of the time range, inclusive. Accepted forms: YYYY, YYYY-MM, YYYY-MM-DD, YYYY-Qn (1–4), YYYY-Sn (1–2), YYYY-Tn (1–3), YYYY-Mnn (01–12), YYYY-Wnn (a week the year has, up to 53) or YYYY-Dnnn (...
stageboolean
Stage every matched observation on a dataframe canvas, regardless of preview length or match size. Default false preserves automatic staging only above 5,000 observations. Ignored with an unavailab...default: false
until_periodstring
End of the time range, inclusive (e.g., "2024"), in the same forms as since_period. Omit for data through the latest available period. A bound that falls inside a period excludes it here too: "2023...
eurostat_download_datasetDownload a Eurostat dataset in bulk through the SDMX 2.1 TSV endpoint and stage it as a SQL table on the dataframe canvas — the route to a whole dataset, where eurostat_query_dataset is the route to a slice of one. The TSV wire format is roughly half the bytes of the JSON-stat...6 params

Download a Eurostat dataset in bulk through the SDMX 2.1 TSV endpoint and stage it as a SQL table on the dataframe canvas — the route to a whole dataset, where eurostat_query_dataset is the route to a slice of one. The TSV wire format is roughly half the bytes of the JSON-stat...

Parameters* required
canvas_idstring
Reuse an existing dataframe canvas so this download lands beside earlier results and can be joined against them. Pass the canvasId a previous eurostat_download_dataset or eurostat_query_dataset res...
dataset_code*string
Dataset code (e.g., "nama_10_gdp"). Required. A DS-* code — Comext detailed trade or PRODCOM, in any case — is served by the Comext host, which refuses an unfiltered download of its large collectio...
filtersobject
Dimension filters as a map of dimension code → array of accepted values, applied by Eurostat before the body is sent. Example: {"unit": ["CP_MEUR"], "na_item": ["B1G"], "geo": ["DE", "FR"]}. Omit a...
preview_limitnumber
How many rows to echo inline, from the start of the download. Default 25; positive integers above 500 are clamped to 500 with a notice. The full download is on the canvas table when one was staged;...default: 25
since_periodstring
Start of the period range, inclusive, sent as startPeriod. Accepted forms: YYYY, YYYY-MM, YYYY-MM-DD, YYYY-Qn (1–4), YYYY-Sn (1–2), YYYY-Tn (1–3), YYYY-Mnn (01–12), YYYY-Wnn (a week the year has, u...
until_periodstring
End of the period range, inclusive (e.g., "2024"), sent as endPeriod, in the same forms as since_period. Omit for data through the latest available period. A bound that falls inside a period exclud...
eurostat_dataframe_describeList the tables staged on a Eurostat dataframe canvas, with their row counts and column names and types. Call this before eurostat_dataframe_query to learn the table and column names to write SQL against. The canvas_id comes from a eurostat_query_dataset or eurostat_download_d...1 params

List the tables staged on a Eurostat dataframe canvas, with their row counts and column names and types. Call this before eurostat_dataframe_query to learn the table and column names to write SQL against. The canvas_id comes from a eurostat_query_dataset or eurostat_download_d...

Parameters* required
canvas_id*string
Canvas identifier returned as canvasId by eurostat_query_dataset, eurostat_download_dataset, or eurostat_get_dimension_values. Identifies the workspace holding the staged tables.
eurostat_dataframe_queryRun a read-only SQL SELECT against tables staged on a Eurostat dataframe canvas, reaching observations beyond an inline preview and aggregating or joining tables without re-fetching Eurostat. Call eurostat_dataframe_describe first for table and column names. Only a single SELE...2 params

Run a read-only SQL SELECT against tables staged on a Eurostat dataframe canvas, reaching observations beyond an inline preview and aggregating or joining tables without re-fetching Eurostat. Call eurostat_dataframe_describe first for table and column names. Only a single SELE...

Parameters* required
canvas_id*string
Canvas identifier returned as canvasId by eurostat_query_dataset, eurostat_download_dataset, or eurostat_get_dimension_values. Identifies the workspace holding the staged tables.
sql*string
A single read-only SELECT statement. Reference tables by the names eurostat_dataframe_describe reports. Example: SELECT geo, geo_label, AVG(obs_value) AS mean FROM df_a1b2c3d4 WHERE time >= '2020'...

Sponsors

Configuration

EUROSTAT_CLAMP_LIMITSdefault: true

Clamp positive integer preview/search/dimension limits to 500/100/1000 with a notice. False restores schemas rejecting over-cap inputs.

MCP_LOG_LEVELdefault: info

Sets the minimum log level for output (e.g., 'debug', 'info', 'warn').

EUROSTAT_BASE_URLdefault: https://ec.europa.eu/eurostat/api/dissemination

Eurostat API base URL. Override when using a mirror or proxy.

EUROSTAT_COMEXT_BASE_URLdefault: https://ec.europa.eu/eurostat/api/comext/dissemination

Base URL of the Comext dissemination host, which serves every DS-* dataset code (detailed trade and PRODCOM). Override when using a mirror or proxy.

EUROSTAT_REQUEST_TIMEOUT_MSdefault: 30000

Total allowance for one Eurostat request across retries, backoff and body consumption, in milliseconds.

EUROSTAT_METADATA_TIMEOUT_MSdefault: 120000

Total allowance for one dataset's SDMX dataflow structure across retries, backoff and body consumption, in milliseconds. Defaults to 120000; separate from EUROSTAT_REQUEST_TIMEOUT_MS for large structures.

EUROSTAT_TOC_CACHE_TTL_MSdefault: 43200000

How long a fetched catalogue TOC stays usable before the next catalogue call refreshes it, in milliseconds. Defaults to 12 hours.

EUROSTAT_BULK_TIMEOUT_MSdefault: 120000

Total allowance for one eurostat_download_dataset transfer across request retries, backoff and streaming body consumption, and for each download that builds the dimension value index, in milliseconds. Defaults to 120000.

EUROSTAT_BULK_MAX_BYTESdefault: 52428800

Byte budget for one eurostat_download_dataset transfer, counted on the decoded TSV rather than on the wire. Eurostat sends the body chunked with no Content-Length, so the budget is enforced while streaming and the transfer is aborted when it is reached. Defaults to 50 MiB.

CANVAS_PROVIDER_TYPEdefault: duckdb

Dataframe canvas backend. The default, 'duckdb', lists eurostat_dataframe_describe and eurostat_dataframe_query, stages query matches with stage=true or above 5,000 observations, and retains bulk downloads beyond their previews. Set to 'none' to disable the canvas and those tools

CANVAS_TEMP_PATH

Parent directory for DuckDB canvas spill files: a private 'mcp-canvas-XXXXXX' directory is created inside it, so it must be writable by the server process. Defaults to the OS temp directory.

CANVAS_TTL_MSdefault: 86400000

Sliding lifetime of a staged dataframe canvas in milliseconds; every call against it extends the window. Defaults to 24 hours.

CANVAS_DEFAULT_ROW_LIMITdefault: 10000

Maximum complete rows a single eurostat_dataframe_query returns before reporting truncated.

EUROSTAT_DATAFRAME_DROP_ENABLEDdefault: false

Set to 'true' to list eurostat_dataframe_drop, which removes one staged table from a dataframe canvas and leaves its other tables in place. Off by default because a drop cannot be undone; staged tables expire with their canvas either way. Has no effect with CANVAS_PROVIDER_TYPE=n

MCP_TRANSPORT_TYPEdefault: http

Selects the HTTP transport.

MCP_HTTP_HOSTdefault: 127.0.0.1

The hostname for the HTTP server.

MCP_HTTP_PORTdefault: 3010

The port to run the HTTP server on.

MCP_HTTP_ENDPOINT_PATHdefault: /mcp

The endpoint path for the MCP server.

MCP_PUBLIC_URL

Public origin override for deployments behind a TLS-terminating reverse proxy (e.g. https://mcp.example.com).

MCP_AUTH_MODEdefault: none

Authentication mode to use: 'none', 'jwt', or 'oauth'.

Readme

@cyanheads/eurostat-mcp-server

Search and query the Eurostat catalogue — EU economy, demography, trade, health, and NUTS regional data via MCP. STDIO or Streamable HTTP.

6 Tools (up to 9 with the dataframe canvas) • 2 Resources • 1 Skill

Details

Repository
github.com/cyanheads/eurostat-mcp-server
Categories
Search & Web Crawling, Data & Analytics
Package
@cyanheads/eurostat-mcp-server
Transport
STDIO, HTTP
Registry
MCP registry, active
Resources
1
Tools verified
Nov 6, 2026

More from cyanheads

Related Search & Web Crawling MCP servers

View all
1maxim-mazurok avatarMicrosoft Teams APImaxim-mazurok/teams-apiAI-native Microsoft Teams integration — read chats, send messages, search people9stars
2scrypster avatarMementoscrypster/mementoPersistent memory for AI tools. Local-first knowledge graph with hybrid search.9stars
3spuentesp avatarLainspuentesp/lainHigh-performance knowledge graph MCP server for AI coding agents with semantic search.9stars
4vaquill-ai avatarVaquillvaquill-ai/vaquill-mcpSearch US and Indian statutes, regulations, constitutions, and court rules.9stars
5jepto avatarJeptojepto/mcpLive Google Ads, GA4, Search Console, Meta Ads and GBP data in Claude, ChatGPT and any MCP client0stars
6mintmcp avatarGmailmintmcp/serversA MCP server for Gmail that lets you search, read, and draft emails and replies.0stars