Eurostat Mcp Server
БесплатноПоддерживаетсяSearch and query the Eurostat catalogue — EU economy, demography, trade, health, and NUTS regional data via MCP. STDIO or Streamable HTTP.
Описание
Search and query the Eurostat catalogue — EU economy, demography, trade, health, and NUTS regional data via MCP. STDIO or Streamable HTTP.
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.
Public Hosted Server: https://eurostat.caseyjhand.com/mcp
Overview
EU statistics from the Eurostat catalogue — economy, demography, trade, health, and NUTS regional data. Search and browse the catalogue by keyword or theme, inspect dataset dimensions, and query a slice or bulk-download a whole dataset from any MCP client. Runs as a stdio process, a local Streamable HTTP server, or the public hosted endpoint above.
Tools
Two of the eight are listed only when the dataframe canvas is enabled (CANVAS_PROVIDER_TYPE=duckdb).
| Tool | Description |
|---|---|
eurostat_search_datasets |
Search the Eurostat catalogue by keyword — returns codes, descriptions, period coverage, and theme breadcrumbs |
eurostat_browse_themes |
Navigate the Eurostat theme hierarchy — list root themes or drill into subthemes and datasets |
eurostat_get_dataset_info |
Fetch dataset metadata: dimensions with sample values, time range, observation count, and last-update date |
eurostat_get_dimension_values |
List all valid codes for one dataset dimension, with NUTS hierarchy filtering for geo |
eurostat_query_dataset |
Fetch a bounded preview of decoded observations with dimension filters, NUTS geo-level, and time-range controls |
eurostat_download_dataset |
Download a whole dataset via the SDMX bulk endpoint and stage every observation on the dataframe canvas |
eurostat_dataframe_describe |
List the tables staged on a dataframe canvas, with row counts and column types — canvas only |
eurostat_dataframe_query |
Run a read-only SQL SELECT across staged tables — canvas only |
Resources
| Resource | Description |
|---|---|
eurostat://dataset/{dataset_code} |
Dataset metadata (dimensions, time range, observation count, last-updated) by URI, for cache-injectable context |
Capability reference
eurostat_search_datasets tool
- Tokenized keyword match — whitespace-separated tokens are ANDed case-insensitively across each dataset's label, theme breadcrumb, and code, so word order and theme-named queries resolve without a verbatim label match
- Returns
code,label,type(dataset/table), period coverage, observation count, and theme breadcrumb per result - One row per dataset code — Eurostat files some datasets under multiple theme branches; matches are deduplicated so
totalMatchesand page slots count unique targets - Cursor pagination:
limit(1–100, default 20) sets page size,totalMatchesreports the full count, and passingnextCursorback ascursorpages through every match. A cursor is bound to its originating query and catalogue snapshot — reusing one with a different query, or after the catalogue refreshes, returnsinvalid_cursorinstead of a silently shifted page nextStepon each result names the next tool to call- Catalogue TOC is cached in memory for 12 hours (
EUROSTAT_TOC_CACHE_TTL_MS), refreshed on the next call past that age
eurostat_browse_themes tool
- Without
theme_code: returns the top-level theme folders (Economy, Population, Transport, etc.) - With
theme_code: returns immediate children — subtheme folders and datasets in that branch - Each entry carries
code,label,type(folder/dataset/table), data period, and observation count where available - Returns a breadcrumb
parentPathfrom root to the current node, plus anextStephint suited to the level - One branch per folder code — Eurostat files a few folder codes under several branches; a code resolves to the branch listed first in the catalogue (never fewer children than the ones it shadows), and
otherPlacementsnames those so the ambiguity is visible
eurostat_get_dataset_info tool
- Returns all dimensions with their codes, labels, and up to 10 sample values each
- Dimension values reflect the full dataset-available set (including every period for
time), not just what appears in populated observations - Reports overall time range and total observation count, each omitted — not zeroed — when Eurostat does not report it
- For a dimension with more than 10 values, call
eurostat_get_dimension_valuesfor the full list metadataUrllinks to the ESMS metadata page when Eurostat provides one
eurostat_get_dimension_values tool
- Returns the complete dataset-available set of codes and labels for any dimension, from the same content constraint
eurostat_get_dataset_infouses - For
geo, NUTS hierarchy filtering viageo_level:aggregate,country(default),nuts1,nuts2,nuts3— an empty level reportsno_resultsrather than implying the dataset lacks data, and pairinggeo_levelwith any other dimension is rejected - Verify codes here before
eurostat_query_datasetoreurostat_download_dataset— an invalid dimension value returns no data silently from the former and a rejected fault from the latter
eurostat_query_dataset tool
- Dimension filters as
{dimension_code: [values]}; ageofilter andgeo_level(NUTS:aggregate/country/nuts1/nuts2/nuts3) are mutually exclusive, as aresince_period/until_periodandlast_n_periods; an empty filter array is dropped rather than applied preview_limit(1–500, default 50) bounds only the inline prefix of decoded observations — it never changesobsCount,missingObsCount,timeRange, or what gets staged. There is deliberately no cursor or offset; filters and period controls are the only way to shrink the match itself- Each observation carries dimension code/label pairs, a nullable
value, an optional OBS_FLAGstatus(e.g.p=provisional,e=estimated), and a separate optionalCONF_STATUSconfStatusmarker — usually why a value is null truncatedis true only when the match exceeds the 5,000-observation staging threshold, independent ofpreview_limit. With the dataframe canvas enabled, a match above that threshold is staged whole as a SQL table (canvasId/tableName/stagedRowCount) — calleurostat_dataframe_describebeforeeurostat_dataframe_query; without a canvas those fields are absent and narrowing the query is the only way to reach the restcanvas_idreuses an existing canvas so a result can be joined against earlier ones; an oversized unfiltered query is caught by async-response detection and returned as an actionable, non-retryable error instead of timing out- Fetches a slice — for a whole dataset,
eurostat_download_datasetreads the SDMX bulk endpoint instead, at roughly half the bytes
eurostat_download_dataset tool
- TSV bulk body runs 48–63% of the JSON-stat bytes
eurostat_query_datasetreads for the same data — measured across four datasets from 1.1M to 12.8M observations - Filters take the same
{dimension_code: [values]}map, applied server-side; the positional key needs every dimension in the dataset's own order, so a filter naming one the dataset lacks is rejected with the real dimension list rather than sent malformed - No
last_n_periodshere — onlysince_period/until_periodactually shrink the response, since the TSV layout keeps a column per period regardless of selector - Byte budget (
EUROSTAT_BULK_MAX_BYTES, default 50 MiB) is enforced while streaming — Eurostat sends noContent-Length, so a transfer stopped mid-flight returns its rows withbudgetExceeded: trueinstead of an error - Failure modes are typed: an async queue ticket (Eurostat's too-costly-to-serve-inline response) is a non-retryable error; XML SOAP faults map to
not_found(100),filter_arity(140), andinvalid_dimension(150 — also covers an out-of-coverage period range), each with a recovery hint naming the next tool - With the dataframe canvas enabled, every observation is staged as a SQL table (
canvasId/tableName/stagedRowCount), streamed row by row — calleurostat_dataframe_describebeforeeurostat_dataframe_query. Without a canvas, onlypreview_limitrows (default 50, max 500) survive the call;rowCount/missingCount/periodRangestill describe the whole download
eurostat_dataframe_describe tool
- Lists tables staged on the canvas (from
canvas_id, returned byeurostat_query_datasetoreurostat_download_dataset) with row counts, column names, types, and nullability — call before writing SQL, since the two stagers write different dimension columns - Also reports the canvas's and each table's
expiresAt; every call against a canvas slides its lifetime forward (CANVAS_TTL_MS, default 24h) - Errors
canvas_disabledwhen this deployment runs without a canvas,canvas_not_foundwhen the ID is unknown or expired
eurostat_dataframe_query tool
- Runs a single read-only
SELECTagainst staged tables; statement chaining, non-SELECTverbs, and functions that read files or external data are rejected with a typed error eurostat_query_datasettables carry a code column per dimension plus a_labelcompanion;eurostat_download_datasettables carry code columns only (no labels) plus atimecolumn — both write the same five measure columns (obs_value,obs_flag,obs_flag_label,conf_status,conf_status_label) with matching codes, so tables from either stager join on dimension codes andtime- A confidential cell reads
obs_flag = NULLwithconf_status = 'C'on either table — JSON-stat folds the two into one string (|C) thateurostat_query_datasetsplits before staging - Results are bounded by
CANVAS_DEFAULT_ROW_LIMIT(default 10,000);truncated: truemeans add aLIMIT, an aggregate, or a narrowerWHERE. 64-bit integer results —COUNT(*)included — arrive as strings so values outside the JSON number range survive intact - The DuckDB binding ships with the server —
CANVAS_PROVIDER_TYPE=duckdbis the only switch — except the one-click.mcpbbundle, which strips native bindings to stay portable; use the npm, Docker, or from-source install for SQL analytics
eurostat://dataset/{dataset_code} resource
- Same payload as
eurostat_get_dataset_info, addressable as a resource URI for cache-injectable context dataset_codecomes fromeurostat_search_datasetsoreurostat_browse_themes
Features
Built on @cyanheads/mcp-ts-core: stdio and Streamable HTTP transports, pluggable auth (none / jwt / oauth), swappable storage (in-memory, filesystem, Supabase, Cloudflare KV/R2/D1), structured logging with optional OpenTelemetry tracing.
Eurostat-specific:
- NUTS hierarchy geo-level filtering (
aggregate/country/nuts1/nuts2/nuts3) acrosseurostat_query_datasetandeurostat_get_dimension_values - OBS_FLAG (provisional, estimated, etc.) and CONF_STATUS (confidentiality) decoded into separate fields from Eurostat's combined encoding, consistent whether the observation came from JSON-stat or the bulk TSV
- Async-response detection across every data-fetching tool — Eurostat's over-limit HTTP-200 warnings and HTTP-413/SOAP faults are classified into one typed, non-retryable error with filter guidance instead of surfacing as a timeout
- SDMX 2.1 TSV bulk downloads at roughly half the JSON-stat byte cost, with a mid-transfer byte budget
- Optional DuckDB dataframe canvas stages a query match above 5,000 observations, or a whole bulk download, as a queryable SQL table
Agent-friendly output:
- Structured error contracts — every declared failure carries a typed
reasonand arecovery.hintnaming the exact next tool to call, not just an error string - Next-step hints —
eurostat_search_datasetsandeurostat_browse_themesresponses carry anextStepfield pointing at the right follow-up call - Omitted-vs-unknown fields — counts and period bounds Eurostat doesn't report (
obsCount,timeRange.start/end,lastUpdated) are omitted from the response rather than defaulted to zero or blank - Truncation and staging notices — a response that exceeds an inline cap carries an enrichment notice naming the exact
eurostat_dataframe_describe→eurostat_dataframe_queryfollow-up
Getting started
Public Hosted Instance
A public instance is available at https://eurostat.caseyjhand.com/mcp — no installation required. Point any MCP client at it via Streamable HTTP:
{
"mcpServers": {
"eurostat-mcp-server": {
"type": "streamable-http",
"url": "https://eurostat.caseyjhand.com/mcp"
}
}
}
Self-Hosted / Local
Add the following to your MCP client configuration file.
{
"mcpServers": {
"eurostat-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/eurostat-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info"
}
}
}
}
Or with npx (no Bun required):
{
"mcpServers": {
"eurostat-mcp-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@cyanheads/eurostat-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info"
}
}
}
}
Or with Docker:
{
"mcpServers": {
"eurostat-mcp-server": {
"type": "stdio",
"command": "docker",
"args": ["run", "-i", "--rm", "-e", "MCP_TRANSPORT_TYPE=stdio", "ghcr.io/cyanheads/eurostat-mcp-server:latest"]
}
}
}
For Streamable HTTP, set the transport and start the server:
MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 bun run start:http
# Server listens at http://localhost:3010/mcp
Prerequisites
- Bun v1.4.0 or higher. No API key required — Eurostat's dissemination API is public.
Installation
- Clone the repository:
git clone https://github.com/cyanheads/eurostat-mcp-server.git
- Navigate into the directory:
cd eurostat-mcp-server
- Install dependencies:
bun install
Configuration
All configuration is validated at startup via Zod schemas in src/config/server-config.ts. Key environment variables:
| Variable | Description | Default |
|---|---|---|
MCP_TRANSPORT_TYPE |
Transport: stdio or http |
stdio |
MCP_HTTP_PORT |
HTTP server port | 3010 |
MCP_HTTP_ENDPOINT_PATH |
HTTP endpoint path | /mcp |
MCP_PUBLIC_URL |
Public origin override for TLS-terminating reverse-proxy deployments | none |
MCP_AUTH_MODE |
Authentication: none, jwt, or oauth |
none |
MCP_LOG_LEVEL |
Log level (debug, info, warning, error, etc.) |
info |
MCP_GC_PRESSURE_INTERVAL_MS |
Opt-in Bun-only forced-GC pressure loop (ms). Recommended starting point if heap growth is observed: 60000. |
0 (disabled) |
LOGS_DIR |
Directory for log files (Node.js only) | <project-root>/logs |
STORAGE_PROVIDER_TYPE |
Storage backend: in-memory, filesystem, supabase, cloudflare-kv/r2/d1 |
in-memory |
EUROSTAT_BASE_URL |
Eurostat API base URL | https://ec.europa.eu/eurostat/api/dissemination |
EUROSTAT_REQUEST_TIMEOUT_MS |
HTTP request timeout in ms | 30000 |
EUROSTAT_TOC_CACHE_TTL_MS |
Catalogue TOC cache lifetime in ms — the first search or browse call past this age refreshes it | 43200000 (12 hours) |
EUROSTAT_BULK_TIMEOUT_MS |
HTTP timeout for one eurostat_download_dataset transfer in ms — held separate because a bulk body streams for minutes |
120000 (2 minutes) |
EUROSTAT_BULK_MAX_BYTES |
Byte budget for one bulk download, counted on the decoded TSV and enforced while streaming | 52428800 (50 MiB) |
CANVAS_PROVIDER_TYPE |
duckdb enables the dataframe canvas: lists the two dataframe tools, lets eurostat_query_dataset stage a match above 5,000 observations, and lets eurostat_download_dataset retain a bulk download |
none |
CANVAS_TEMP_PATH |
Directory DuckDB writes canvas spill files to. Must be writable by the server process | <os tmpdir>/mcp-canvas |
CANVAS_TTL_MS |
Sliding lifetime of a staged canvas in ms; every call against it extends the window | 86400000 (24 hours) |
CANVAS_DEFAULT_ROW_LIMIT |
Max rows one eurostat_dataframe_query returns before reporting truncated |
10000 |
OTEL_ENABLED |
Enable OpenTelemetry | false |
See .env.example for the full list of optional overrides.
Running the server
Local development
Build and run the production version:
# One-time build bun run rebuild # Run the built server bun run start:http # or bun run start:stdioRun checks and tests:
bun run devcheck # Lints, formats, type-checks, and more bun run test # Runs the test suite bun run lint:mcp # Validates MCP definitions against spec
Docker
docker build -t eurostat-mcp-server .
docker run --rm -p 3010:3010 eurostat-mcp-server
The Dockerfile defaults to HTTP transport, stateless session mode, and logs to /var/log/eurostat-mcp-server. OpenTelemetry peer dependencies are installed by default — build with --build-arg OTEL_ENABLED=false to omit them.
Project structure
| Directory | Purpose |
|---|---|
src/index.ts |
createApp() entry point — registers tools and resources and inits services. |
src/mcp-server/tools |
Tool definitions (*.tool.ts). Six tools for discovery and data access, plus two canvas-gated dataframe tools. |
src/mcp-server/resources |
Resource definitions. Dataset metadata resource. |
src/services/eurostat-catalogue |
Catalogue service — fetches and parses the Eurostat TOC TXT file; TTL-bounded in-memory cache. |
src/services/eurostat-data |
Data service — dataset-scoped SDMX metadata parser plus Statistics API querying, JSON-stat 2.0 decoding, async-response detection, and dataframe row source. |
src/services/canvas-accessor.ts |
Module-level accessor for the optional DataCanvas, plus the acquire helper that names the misconfigured path on a permission failure. |
src/config |
Server-specific environment variable parsing and validation with Zod. |
tests/ |
Unit and integration tests, mirroring the src/ structure. |
Development guide
See CLAUDE.md for development guidelines and architectural rules. The short version:
- Handlers throw, framework catches — no
try/catchin tool logic - Use
ctx.logfor logging,ctx.statefor storage - Register new tools and resources in the
createApp()arrays - Wrap external API calls: validate raw → normalize to domain type → return output schema; never fabricate missing fields
Contributing
Issues are welcome. Run checks and tests before submitting:
bun run devcheck
bun run test
License
This project is licensed under the Apache 2.0 License. See the LICENSE file for details.
Установить Eurostat Mcp Server в Claude Desktop, Claude Code, Cursor
unyly install eurostat-mcp-serverСтавит в Claude Desktop, Claude Code, Cursor и VS Code — сам разбирается с npx, uvx и сборкой из исходников.
Впервые? Поставь CLI: curl -fsSL https://unyly.org/install | sh
Или настроить вручную
Выполни в терминале:
claude mcp add eurostat-mcp-server --env MCP_LOG_LEVEL="" --env MCP_TRANSPORT_TYPE="" -- npx -y @cyanheads/eurostat-mcp-serverПошаговые гайды: как установить Eurostat Mcp Server
FAQ
Eurostat Mcp Server MCP бесплатный?
Да, Eurostat Mcp Server MCP бесплатный — установка в пару кликов через Unyly без оплаты.
Нужен ли API-ключ для Eurostat Mcp Server?
Да, требуются переменные окружения: MCP_LOG_LEVEL, MCP_TRANSPORT_TYPE. Unyly подставит их в конфиг при установке.
Eurostat Mcp Server — hosted или self-hosted?
Self-hosted: сервер запускается локально на твоей машине командой из раздела установки.
Как установить Eurostat Mcp Server в Claude Desktop, Claude Code или Cursor?
Открой Eurostat Mcp Server на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.
Изменения
Версии и запрашиваемые доступы со временем.
- Новая версия опубликована
- Новая версия опубликована
- Новая версия опубликована
- Новая версия опубликована
- Новая версия опубликована
Похожие MCP
GitHub
PRs, issues, code search, CI status
автор: GitHubFilesystem
Secure file operations with configurable access controls.
Memory
Knowledge graph-based persistent memory system.
Template MCP Server
A CLI tool to create a new Model Context Protocol server project with TypeScript support, dual transport options, and an extensible structure
автор: mcpdotdirectAmap Maps Mcp Server
MCP server for using the AMap Maps API
автор: duxiaohuiSupabase
Database, auth and storage
автор: SupabaseEverything
Reference / test server with prompts, resources, and tools.
Git
Tools to read, search, and manipulate Git repositories.
Sequential Thinking
Dynamic and reflective problem-solving through thought sequences.
Time
Time and timezone conversion capabilities.
Compare Eurostat Mcp Server with
Не уверен что выбрать?
Найди свой стек за 60 секунд
Автор?
Embed-бейдж для README
Похожее
Все в категории development
