@cyanheads/eurostat-mcp-server 0.6.5 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +1 -1
- package/CLAUDE.md +1 -1
- package/README.md +70 -85
- package/changelog/0.7.x/0.7.0.md +33 -0
- package/dist/mcp-server/tools/definitions/eurostat-dataframe-describe.tool.d.ts +1 -1
- package/dist/mcp-server/tools/definitions/eurostat-dataframe-describe.tool.js +1 -1
- package/dist/mcp-server/tools/definitions/eurostat-dataframe-describe.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/eurostat-dataframe-query.tool.d.ts +2 -2
- package/dist/mcp-server/tools/definitions/eurostat-dataframe-query.tool.js +2 -2
- package/dist/mcp-server/tools/definitions/eurostat-dataframe-query.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/eurostat-download-dataset.tool.d.ts +9 -6
- package/dist/mcp-server/tools/definitions/eurostat-download-dataset.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/eurostat-download-dataset.tool.js +61 -21
- package/dist/mcp-server/tools/definitions/eurostat-download-dataset.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/eurostat-get-dimension-values.tool.js +1 -1
- package/dist/mcp-server/tools/definitions/eurostat-get-dimension-values.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/eurostat-query-dataset.tool.d.ts +7 -1
- package/dist/mcp-server/tools/definitions/eurostat-query-dataset.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/eurostat-query-dataset.tool.js +129 -14
- package/dist/mcp-server/tools/definitions/eurostat-query-dataset.tool.js.map +1 -1
- package/dist/services/eurostat-bulk/eurostat-bulk-service.d.ts +3 -0
- package/dist/services/eurostat-bulk/eurostat-bulk-service.d.ts.map +1 -1
- package/dist/services/eurostat-bulk/eurostat-bulk-service.js +21 -2
- package/dist/services/eurostat-bulk/eurostat-bulk-service.js.map +1 -1
- package/dist/services/eurostat-data/eurostat-data-service.d.ts +15 -1
- package/dist/services/eurostat-data/eurostat-data-service.d.ts.map +1 -1
- package/dist/services/eurostat-data/eurostat-data-service.js +78 -3
- package/dist/services/eurostat-data/eurostat-data-service.js.map +1 -1
- package/dist/services/eurostat-data/types.d.ts +26 -0
- package/dist/services/eurostat-data/types.d.ts.map +1 -1
- package/dist/services/eurostat-data/types.js.map +1 -1
- package/dist/services/eurostat-periods.d.ts +68 -0
- package/dist/services/eurostat-periods.d.ts.map +1 -0
- package/dist/services/eurostat-periods.js +204 -0
- package/dist/services/eurostat-periods.js.map +1 -0
- package/package.json +2 -2
- package/server.json +3 -3
package/AGENTS.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Agent Protocol
|
|
2
2
|
|
|
3
3
|
**Server:** @cyanheads/eurostat-mcp-server
|
|
4
|
-
**Version:** 0.
|
|
4
|
+
**Version:** 0.7.0
|
|
5
5
|
**Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.13.6`
|
|
6
6
|
**Engines:** Bun ≥1.4.0, Node ≥24.0.0
|
|
7
7
|
**MCP SDK:** `@modelcontextprotocol/server` `^2.0.0`
|
package/CLAUDE.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Agent Protocol
|
|
2
2
|
|
|
3
3
|
**Server:** @cyanheads/eurostat-mcp-server
|
|
4
|
-
**Version:** 0.
|
|
4
|
+
**Version:** 0.7.0
|
|
5
5
|
**Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.13.6`
|
|
6
6
|
**Engines:** Bun ≥1.4.0, Node ≥24.0.0
|
|
7
7
|
**MCP SDK:** `@modelcontextprotocol/server` `^2.0.0`
|
package/README.md
CHANGED
|
@@ -7,9 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
<div align="center">
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
[](./CHANGELOG.md) [](./LICENSE) [](https://github.com/users/cyanheads/packages/container/package/eurostat-mcp-server) [](https://modelcontextprotocol.io/) [](https://www.npmjs.com/package/@cyanheads/eurostat-mcp-server) [](https://www.typescriptlang.org/) [](https://bun.sh/)
|
|
10
|
+
[](./CHANGELOG.md) [](./LICENSE) [](https://github.com/users/cyanheads/packages/container/package/eurostat-mcp-server) [](https://modelcontextprotocol.io/) [](https://www.npmjs.com/package/@cyanheads/eurostat-mcp-server) [](https://www.typescriptlang.org/) [](https://bun.sh/)
|
|
13
11
|
|
|
14
12
|
</div>
|
|
15
13
|
|
|
@@ -31,7 +29,7 @@
|
|
|
31
29
|
|
|
32
30
|
## Overview
|
|
33
31
|
|
|
34
|
-
EU statistics from the Eurostat catalogue
|
|
32
|
+
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, then query a slice or bulk-download a whole dataset. Runs as a stdio process, a local Streamable HTTP server, or the public hosted endpoint above.
|
|
35
33
|
|
|
36
34
|
### Tools
|
|
37
35
|
|
|
@@ -45,99 +43,83 @@ Two of the eight are listed only when the dataframe canvas is enabled (`CANVAS_P
|
|
|
45
43
|
| `eurostat_get_dimension_values` | List all valid codes for one dataset dimension, with NUTS hierarchy filtering for `geo` |
|
|
46
44
|
| `eurostat_query_dataset` | Fetch a bounded preview of decoded observations with dimension filters, NUTS geo-level, and time-range controls |
|
|
47
45
|
| `eurostat_download_dataset` | Download a whole dataset via the SDMX bulk endpoint and stage every observation on the dataframe canvas |
|
|
48
|
-
| `eurostat_dataframe_describe` | List the tables staged on a dataframe canvas, with row counts and column types
|
|
49
|
-
| `eurostat_dataframe_query` | Run a read-only SQL SELECT across staged tables
|
|
46
|
+
| `eurostat_dataframe_describe` | List the tables staged on a dataframe canvas, with row counts and column types |
|
|
47
|
+
| `eurostat_dataframe_query` | Run a read-only SQL SELECT across staged tables |
|
|
50
48
|
|
|
51
49
|
### Resources
|
|
52
50
|
|
|
53
51
|
| Resource | Description |
|
|
54
52
|
|:---|:---|
|
|
55
|
-
| `eurostat://dataset/{dataset_code}` | Dataset metadata (dimensions, time range, observation count, last-updated) by URI
|
|
53
|
+
| `eurostat://dataset/{dataset_code}` | Dataset metadata (dimensions, time range, observation count, last-updated) by URI |
|
|
54
|
+
|
|
55
|
+
The same metadata is available through `eurostat_get_dataset_info` for tool-only clients.
|
|
56
56
|
|
|
57
57
|
## Capability reference
|
|
58
58
|
|
|
59
59
|
### `eurostat_search_datasets` <sub>tool</sub>
|
|
60
60
|
|
|
61
|
-
-
|
|
62
|
-
-
|
|
63
|
-
-
|
|
64
|
-
- Cursor pagination: `limit` (1–100, default 20) sets page size, `totalMatches` reports the full count, and passing `nextCursor` back as `cursor` pages 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, returns `invalid_cursor` instead of a silently shifted page
|
|
65
|
-
- `nextStep` on each result names the next tool to call
|
|
66
|
-
- Catalogue TOC is cached in memory for 12 hours (`EUROSTAT_TOC_CACHE_TTL_MS`), refreshed on the next call past that age
|
|
61
|
+
- `query` tokens are ANDed case-insensitively across each dataset's label, theme breadcrumb, and code; `limit` 1–100 (default 20), paged by passing `nextCursor` back as `cursor`
|
|
62
|
+
- Results carry `code`, `label`, `type` (`dataset` / `table`), period coverage, `obsCount`, `lastUpdated`, and `themePath`; `totalMatches` counts every match
|
|
63
|
+
- Fails as `no_match`, or `invalid_cursor` when a cursor is reused with a different query or after the catalogue refreshes
|
|
67
64
|
|
|
68
65
|
---
|
|
69
66
|
|
|
70
67
|
### `eurostat_browse_themes` <sub>tool</sub>
|
|
71
68
|
|
|
72
|
-
-
|
|
73
|
-
-
|
|
74
|
-
-
|
|
75
|
-
- Returns a breadcrumb `parentPath` from root to the current node, plus a `nextStep` hint suited to the level
|
|
76
|
-
- 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 `otherPlacements` names those so the ambiguity is visible
|
|
69
|
+
- Omit `theme_code` for the top-level theme folders; pass a folder code for its immediate children
|
|
70
|
+
- Items carry `code`, `label`, `type` (`folder` / `dataset` / `table`), and `hasChildren`, with a `parentPath` breadcrumb; `otherPlacements` names other branches that file the same folder code
|
|
71
|
+
- Fails as `not_found` for an unknown code, `not_a_folder` for a dataset or table code
|
|
77
72
|
|
|
78
73
|
---
|
|
79
74
|
|
|
80
75
|
### `eurostat_get_dataset_info` <sub>tool</sub>
|
|
81
76
|
|
|
82
|
-
-
|
|
83
|
-
-
|
|
84
|
-
- Reports overall time range and total observation count, each omitted — not zeroed — when Eurostat does not report it
|
|
85
|
-
- For a dimension with more than 10 values, call `eurostat_get_dimension_values` for the full list
|
|
86
|
-
- `metadataUrl` links to the ESMS metadata page when Eurostat provides one
|
|
77
|
+
- One `dataset_code`; returns every dimension with `valuesCount` and up to 10 `sampleValues`, plus `timeRange`, `obsCount`, `lastUpdated`, and the ESMS `metadataUrl`
|
|
78
|
+
- Fails as `not_found`, or a non-retryable `async_response` when Eurostat won't serve the metadata inline
|
|
87
79
|
|
|
88
80
|
---
|
|
89
81
|
|
|
90
82
|
### `eurostat_get_dimension_values` <sub>tool</sub>
|
|
91
83
|
|
|
92
|
-
-
|
|
93
|
-
- For `geo`,
|
|
94
|
-
-
|
|
84
|
+
- `dataset_code` plus `dimension`; returns every dataset-available code/label pair in `values`, with `totalCount`
|
|
85
|
+
- For `geo`, `geo_level` picks a NUTS level (`aggregate`, `country` by default, `nuts1`, `nuts2`, `nuts3`)
|
|
86
|
+
- Fails as `not_found` for an unknown dataset or dimension, `no_results` for a NUTS level with no values, `conflicting_params` for `geo_level` on any other dimension, or a non-retryable `async_response`
|
|
95
87
|
|
|
96
88
|
---
|
|
97
89
|
|
|
98
90
|
### `eurostat_query_dataset` <sub>tool</sub>
|
|
99
91
|
|
|
100
|
-
-
|
|
101
|
-
-
|
|
102
|
-
-
|
|
103
|
-
- `truncated` is true only when the match exceeds the 5,000-observation staging threshold, independent of `preview_limit`. With the dataframe canvas enabled, a match above that threshold is staged whole as a SQL table (`canvasId` / `tableName` / `stagedRowCount`) — call `eurostat_dataframe_describe` before `eurostat_dataframe_query`; without a canvas those fields are absent and narrowing the query is the only way to reach the rest
|
|
104
|
-
- `canvas_id` reuses 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
|
|
105
|
-
- Fetches a slice — for a whole dataset, `eurostat_download_dataset` reads the SDMX bulk endpoint instead, at roughly half the bytes
|
|
92
|
+
- `dataset_code` plus `filters` (`{dimension_code: [values]}`, codes in any case), `geo_level`, and either `since_period` / `until_period` (`YYYY`, `YYYY-MM`, `YYYY-MM-DD`, `YYYY-Qn`, `YYYY-Sn`, `YYYY-Tn`, `YYYY-Mnn`, `YYYY-Wnn`, `YYYY-Dnnn`; extra leading zeros after the letter are dropped, so `2020-Q01` is sent as `2020-Q1`, and `YYYY-A1` is sent as `YYYY`) or `last_n_periods`, which counts back from the dataset's latest period rather than the slice's; `preview_limit` 1–500 (default 50) sets the inline row count; `lang` is `EN`, `FR`, or `DE`
|
|
93
|
+
- Each observation carries code/label pairs per dimension, a nullable `value`, an OBS_FLAG `status`, and a CONF_STATUS `confStatus`; `obsCount`, `missingObsCount`, and `timeRange` cover the whole match, `truncated` is true above 5,000 observations, and `unmatchedValues` names filter values that matched nothing
|
|
94
|
+
- Fails as `not_found`, `no_results` (naming the filter values that matched nothing and, up to the newest 24 with a full count, the selected periods that carry no value), `invalid_dimension`, `invalid_period` (a malformed or non-existent period, or a `since_period` that starts after `until_period` ends, rejected before any request), `conflicting_params` (`geo` filter with `geo_level`, or a period range with `last_n_periods`), a non-retryable `async_response` for a query too large to serve inline, or `canvas_not_found` for an unknown or expired `canvas_id`
|
|
106
95
|
|
|
107
96
|
---
|
|
108
97
|
|
|
109
98
|
### `eurostat_download_dataset` <sub>tool</sub>
|
|
110
99
|
|
|
111
|
-
-
|
|
112
|
-
-
|
|
113
|
-
-
|
|
114
|
-
- Byte budget (`EUROSTAT_BULK_MAX_BYTES`, default 50 MiB) is enforced while streaming — Eurostat sends no `Content-Length`, so a transfer stopped mid-flight returns its rows with `budgetExceeded: true` instead of an error
|
|
115
|
-
- 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), and `invalid_dimension` (150 — also covers an out-of-coverage period range), each with a recovery hint naming the next tool
|
|
116
|
-
- With the dataframe canvas enabled, every observation is staged as a SQL table (`canvasId` / `tableName` / `stagedRowCount`), streamed row by row — call `eurostat_dataframe_describe` before `eurostat_dataframe_query`. Without a canvas, only `preview_limit` rows (default 50, max 500) survive the call; `rowCount` / `missingCount` / `periodRange` still describe the whole download
|
|
100
|
+
- `dataset_code` plus the same `filters` map and `since_period` / `until_period` in the same period forms (no `last_n_periods`: the TSV keeps a column per period unless a range drops it); `preview_limit` 1–500 (default 50)
|
|
101
|
+
- Returns `rowCount` (echoed as `totalCount`), `missingCount`, `periodRange`, and `bytesRead` for the whole download; the `EUROSTAT_BULK_MAX_BYTES` budget (default 50 MiB) stops a transfer mid-stream and returns what arrived with `budgetExceeded: true`
|
|
102
|
+
- Fails as `not_found`, `invalid_dimension` (including a range wholly outside the dataset's coverage), `invalid_period` (a malformed or non-existent period, or a `since_period` that starts after `until_period` ends, rejected before any request), `filter_arity`, a non-retryable `async_queued` when Eurostat queues the extraction, `no_results` (including a range inside the dataset's coverage that misses the filtered series), `upstream_fault`, or `canvas_not_found` for an unknown or expired `canvas_id`
|
|
117
103
|
|
|
118
104
|
---
|
|
119
105
|
|
|
120
106
|
### `eurostat_dataframe_describe` <sub>tool</sub>
|
|
121
107
|
|
|
122
|
-
-
|
|
123
|
-
-
|
|
124
|
-
- Errors `canvas_disabled` when this deployment runs without a canvas, `canvas_not_found` when the ID is unknown or expired
|
|
108
|
+
- `canvas_id` from a staging response; lists each table's `name`, `rowCount`, and typed columns, plus canvas and table `expiresAt` (sliding `CANVAS_TTL_MS`, default 24h); fails as `canvas_not_found` for an unknown or expired ID, or `canvas_disabled` on a deployment without a canvas
|
|
109
|
+
- `eurostat_query_dataset` tables carry a code and a `_label` column per dimension; `eurostat_download_dataset` tables carry codes only, plus `time`. Both share `obs_value`, `obs_flag`, `obs_flag_label`, `conf_status`, and `conf_status_label`, so they join on dimension codes and `time`
|
|
125
110
|
|
|
126
111
|
---
|
|
127
112
|
|
|
128
113
|
### `eurostat_dataframe_query` <sub>tool</sub>
|
|
129
114
|
|
|
130
|
-
-
|
|
131
|
-
- `
|
|
132
|
-
- A confidential cell reads `obs_flag = NULL` with `conf_status = 'C'` on either table — JSON-stat folds the two into one string (`|C`) that `eurostat_query_dataset` splits before staging
|
|
133
|
-
- Results are bounded by `CANVAS_DEFAULT_ROW_LIMIT` (default 10,000); `truncated: true` means add a `LIMIT`, an aggregate, or a narrower `WHERE`. 64-bit integer results — `COUNT(*)` included — arrive as strings so values outside the JSON number range survive intact
|
|
134
|
-
- The DuckDB binding ships with the server — `CANVAS_PROVIDER_TYPE=duckdb` is the only switch — except the one-click `.mcpb` bundle, which strips native bindings to stay portable; use the npm, Docker, or from-source install for SQL analytics
|
|
115
|
+
- One read-only `SELECT` per call; chained statements, other verbs, and functions that read files or external data are rejected
|
|
116
|
+
- Returns `columns`, `rows`, `rowCount`, and `truncated`, which is true past `CANVAS_DEFAULT_ROW_LIMIT` (default 10,000) rows; 64-bit integers, `COUNT(*)` included, arrive as strings. Fails as `missing_table`, `canvas_not_found`, or `canvas_disabled`
|
|
135
117
|
|
|
136
118
|
---
|
|
137
119
|
|
|
138
120
|
### `eurostat://dataset/{dataset_code}` <sub>resource</sub>
|
|
139
121
|
|
|
140
|
-
- Same payload as `eurostat_get_dataset_info`,
|
|
122
|
+
- Same payload as `eurostat_get_dataset_info`, returned as `application/json`
|
|
141
123
|
- `dataset_code` comes from `eurostat_search_datasets` or `eurostat_browse_themes`
|
|
142
124
|
|
|
143
125
|
## Features
|
|
@@ -146,18 +128,18 @@ Built on [`@cyanheads/mcp-ts-core`](https://github.com/cyanheads/mcp-ts-core): s
|
|
|
146
128
|
|
|
147
129
|
Eurostat-specific:
|
|
148
130
|
|
|
149
|
-
-
|
|
150
|
-
-
|
|
151
|
-
-
|
|
152
|
-
-
|
|
153
|
-
-
|
|
131
|
+
- The Statistics API (JSON-stat 2.0) for slices, the SDMX 2.1 TSV bulk endpoint for whole datasets at roughly half the bytes, and the catalogue TOC cached in memory for 12 hours
|
|
132
|
+
- NUTS geo-level filtering (`aggregate` / `country` / `nuts1` / `nuts2` / `nuts3`) on `eurostat_query_dataset` and `eurostat_get_dimension_values`
|
|
133
|
+
- OBS_FLAG (provisional, estimated, and so on) and CONF_STATUS (confidentiality) decoded into separate fields, with the same codes from JSON-stat and the bulk TSV
|
|
134
|
+
- Eurostat's too-large-to-serve responses (HTTP-200 async warnings, HTTP 413, SOAP queue tickets) come back as non-retryable `async_response` or `async_queued` errors with filter guidance, not timeouts
|
|
135
|
+
- Inline rows are capped by `preview_limit` (at most 500). With `CANVAS_PROVIDER_TYPE=duckdb`, a query match above 5,000 observations, or any bulk download, is staged whole as a SQL table (`canvasId` / `tableName` / `stagedRowCount`) for the dataframe tools, and `canvas_id` stages the next result beside earlier ones for joins. The `.mcpb` bundle strips the native DuckDB binding, so SQL analytics need the npm, Docker, or from-source install
|
|
154
136
|
|
|
155
137
|
Agent-friendly output:
|
|
156
138
|
|
|
157
|
-
-
|
|
158
|
-
- Next-step hints
|
|
159
|
-
-
|
|
160
|
-
-
|
|
139
|
+
- Typed error contracts: every declared failure carries a `reason` and a `recovery.hint` naming the next tool to call
|
|
140
|
+
- Next-step hints: `eurostat_search_datasets` and `eurostat_browse_themes` return a `nextStep` pointing at the follow-up call
|
|
141
|
+
- Unknown stays unknown: counts and period bounds Eurostat doesn't report (`obsCount`, `timeRange.start` / `end`, `lastUpdated`) are omitted rather than zeroed
|
|
142
|
+
- Effective-query echo: `appliedFilters` on `eurostat_query_dataset` and `appliedQuery` (with the SDMX `url`) on `eurostat_download_dataset`, plus a `notice` when the inline preview omits rows, naming the staged table when there is one; `eurostat_query_dataset`'s `notice` also names any filter value that matched nothing
|
|
161
143
|
|
|
162
144
|
## Getting started
|
|
163
145
|
|
|
@@ -237,7 +219,8 @@ MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 bun run start:http
|
|
|
237
219
|
|
|
238
220
|
### Prerequisites
|
|
239
221
|
|
|
240
|
-
- [Bun v1.4.0](https://bun.sh/) or higher
|
|
222
|
+
- [Bun v1.4.0](https://bun.sh/) or higher (or Node.js v24+).
|
|
223
|
+
- No API key: Eurostat's dissemination API is public.
|
|
241
224
|
|
|
242
225
|
### Installation
|
|
243
226
|
|
|
@@ -259,32 +242,32 @@ cd eurostat-mcp-server
|
|
|
259
242
|
bun install
|
|
260
243
|
```
|
|
261
244
|
|
|
262
|
-
|
|
245
|
+
4. **Configure environment (optional, every setting has a default):**
|
|
263
246
|
|
|
264
|
-
|
|
247
|
+
```sh
|
|
248
|
+
cp .env.example .env
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
## Configuration
|
|
265
252
|
|
|
266
253
|
| Variable | Description | Default |
|
|
267
254
|
|:---|:---|:---|
|
|
268
|
-
| `
|
|
269
|
-
| `
|
|
270
|
-
| `
|
|
271
|
-
| `
|
|
272
|
-
| `
|
|
273
|
-
| `
|
|
274
|
-
| `
|
|
275
|
-
| `
|
|
276
|
-
| `
|
|
277
|
-
| `
|
|
278
|
-
| `
|
|
279
|
-
| `
|
|
280
|
-
| `
|
|
281
|
-
| `
|
|
282
|
-
| `
|
|
283
|
-
| `
|
|
284
|
-
| `CANVAS_TEMP_PATH` | Directory DuckDB writes canvas spill files to. Must be writable by the server process | `<os tmpdir>/mcp-canvas` |
|
|
285
|
-
| `CANVAS_TTL_MS` | Sliding lifetime of a staged canvas in ms; every call against it extends the window | `86400000` (24 hours) |
|
|
286
|
-
| `CANVAS_DEFAULT_ROW_LIMIT` | Max rows one `eurostat_dataframe_query` returns before reporting `truncated` | `10000` |
|
|
287
|
-
| `OTEL_ENABLED` | Enable OpenTelemetry | `false` |
|
|
255
|
+
| `EUROSTAT_BASE_URL` | Eurostat API base URL. | `https://ec.europa.eu/eurostat/api/dissemination` |
|
|
256
|
+
| `EUROSTAT_REQUEST_TIMEOUT_MS` | HTTP request timeout, in ms. | `30000` |
|
|
257
|
+
| `EUROSTAT_TOC_CACHE_TTL_MS` | Catalogue TOC cache lifetime, in ms; the first search or browse call past it refreshes the TOC. | `43200000` (12 h) |
|
|
258
|
+
| `EUROSTAT_BULK_TIMEOUT_MS` | Timeout for one `eurostat_download_dataset` transfer, in ms. | `120000` (2 min) |
|
|
259
|
+
| `EUROSTAT_BULK_MAX_BYTES` | Byte budget for one bulk download, counted on the decoded TSV and enforced while streaming. | `52428800` (50 MiB) |
|
|
260
|
+
| `CANVAS_PROVIDER_TYPE` | `duckdb` enables the dataframe canvas: lists the two dataframe tools and turns on staging. | `none` |
|
|
261
|
+
| `CANVAS_TTL_MS` | Sliding lifetime of a staged canvas, in ms. | `86400000` (24 h) |
|
|
262
|
+
| `CANVAS_DEFAULT_ROW_LIMIT` | Max rows one `eurostat_dataframe_query` returns before reporting `truncated`. | `10000` |
|
|
263
|
+
| `MCP_TRANSPORT_TYPE` | Transport: `stdio` or `http`. | `stdio` |
|
|
264
|
+
| `MCP_HTTP_PORT` | HTTP server port. | `3010` |
|
|
265
|
+
| `MCP_SESSION_MODE` | HTTP session mode: `stateless`, `stateful`, or `auto`. The server declares `stateless`; a set value overrides it. | `stateless` |
|
|
266
|
+
| `MCP_AUTH_MODE` | Authentication: `none`, `jwt`, or `oauth`. | `none` |
|
|
267
|
+
| `MCP_LOG_LEVEL` | Log level (`debug`, `info`, `warning`, `error`, etc.). The Docker image sets `info`. | `debug` |
|
|
268
|
+
| `LOGS_DIR` | Directory for log files (Node.js only). | `<project-root>/logs` |
|
|
269
|
+
| `STORAGE_PROVIDER_TYPE` | Storage backend: `in-memory`, `filesystem`, `supabase`, `cloudflare-kv/r2/d1`. | `in-memory` |
|
|
270
|
+
| `OTEL_ENABLED` | Enable [OpenTelemetry](https://github.com/cyanheads/mcp-ts-core/tree/main/docs/telemetry). | `false` |
|
|
288
271
|
|
|
289
272
|
See [`.env.example`](./.env.example) for the full list of optional overrides.
|
|
290
273
|
|
|
@@ -324,12 +307,14 @@ The Dockerfile defaults to HTTP transport, stateless session mode, and logs to `
|
|
|
324
307
|
|
|
325
308
|
| Directory | Purpose |
|
|
326
309
|
|:---|:---|
|
|
327
|
-
| `src/index.ts` | `createApp()` entry point — registers tools and
|
|
328
|
-
| `src/mcp-server/tools` | Tool definitions (`*.tool.ts`). Six
|
|
310
|
+
| `src/index.ts` | `createApp()` entry point — registers tools and the resource, inits services, gates the dataframe tools on the canvas. |
|
|
311
|
+
| `src/mcp-server/tools` | Tool definitions (`*.tool.ts`). Six discovery and data tools, plus two canvas-gated dataframe tools. |
|
|
329
312
|
| `src/mcp-server/resources` | Resource definitions. Dataset metadata resource. |
|
|
330
|
-
| `src/services/eurostat-catalogue` | Catalogue service — fetches and parses the Eurostat TOC
|
|
331
|
-
| `src/services/eurostat-data` |
|
|
332
|
-
| `src/services/
|
|
313
|
+
| `src/services/eurostat-catalogue` | Catalogue service — fetches and parses the Eurostat TOC, with a TTL-bounded in-memory cache. |
|
|
314
|
+
| `src/services/eurostat-data` | Statistics API service — SDMX metadata parsing, JSON-stat 2.0 decoding, async-response detection, canvas row source. |
|
|
315
|
+
| `src/services/eurostat-bulk` | SDMX 2.1 TSV bulk service — streaming download, byte budget, SOAP fault mapping, canvas row source. |
|
|
316
|
+
| `src/services/eurostat-codelists.ts` | OBS_FLAG and CONF_STATUS codelists and the measure column names both stagers write. |
|
|
317
|
+
| `src/services/canvas-accessor.ts` | Accessor for the optional DataCanvas and the acquire helper canvas-touching tools share. |
|
|
333
318
|
| `src/config` | Server-specific environment variable parsing and validation with Zod. |
|
|
334
319
|
| `tests/` | Unit and integration tests, mirroring the `src/` structure. |
|
|
335
320
|
|
|
@@ -339,7 +324,7 @@ See [`CLAUDE.md`](./CLAUDE.md) for development guidelines and architectural rule
|
|
|
339
324
|
|
|
340
325
|
- Handlers throw, framework catches — no `try/catch` in tool logic
|
|
341
326
|
- Use `ctx.log` for logging, `ctx.state` for storage
|
|
342
|
-
- Register new tools and resources in the `createApp()` arrays
|
|
327
|
+
- Register new tools and resources in the `createApp()` arrays in `src/index.ts`
|
|
343
328
|
- Wrap external API calls: validate raw → normalize to domain type → return output schema; never fabricate missing fields
|
|
344
329
|
|
|
345
330
|
## Contributing
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
summary: "Both data tools now reject malformed, non-existent, and inverted period ranges as invalid_period before any request; eurostat_query_dataset explains an empty match and names filter values that matched nothing; eurostat_download_dataset reports totalCount instead of truncated."
|
|
3
|
+
breaking: true
|
|
4
|
+
security: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 0.7.0 — 2026-09-25
|
|
8
|
+
|
|
9
|
+
## Added
|
|
10
|
+
|
|
11
|
+
- **`invalid_period` on `eurostat_query_dataset` and `eurostat_download_dataset`** ([#47](https://github.com/cyanheads/eurostat-mcp-server/issues/47), [#53](https://github.com/cyanheads/eurostat-mcp-server/issues/53)). `since_period`/`until_period` are checked in the handler before any request: the literal must be an accepted form, every month, quarter, semester, trimester, week, and day it names must exist, and `since_period` must not start after `until_period` ends. Cross-frequency pairs such as `2020-06` to `2020` stay valid.
|
|
12
|
+
- **`unmatchedValues` on `eurostat_query_dataset`** ([#52](https://github.com/cyanheads/eurostat-mcp-server/issues/52)) — filter values that matched nothing, keyed by dimension and spelled as sent. `notice` and the text output name them too; omitted when every value matched.
|
|
13
|
+
- **`no_results` diagnosis on `eurostat_query_dataset`** ([#48](https://github.com/cyanheads/eurostat-mcp-server/issues/48)) — read from the empty reply with no extra request: `data.unmatchedValues`, and `data.matchedPeriods` (the newest 24 selected periods, none carrying a value) with `data.matchedPeriodCount`. The message and hint name the cause: an unmatched value, a range outside the dataset's coverage (with its oldest and latest period), `last_n_periods` counting back past the slice's latest period, or a combination that carries no data.
|
|
14
|
+
|
|
15
|
+
## Changed
|
|
16
|
+
|
|
17
|
+
- **Breaking: `eurostat_download_dataset` enrichment drops `truncated`, `shown`, and `cap`, and adds `totalCount`** ([#49](https://github.com/cyanheads/eurostat-mcp-server/issues/49)), equal to `rowCount`. A preview shorter than the download is disclosed as a `notice` sentence; `budgetExceeded` remains the only signal that the download is incomplete.
|
|
18
|
+
- **Breaking: period literals that name a component that does not exist fail as `invalid_period`** ([#47](https://github.com/cyanheads/eurostat-mcp-server/issues/47), [#53](https://github.com/cyanheads/eurostat-mcp-server/issues/53)) instead of reaching Eurostat, which rolled some into a neighbouring period (`2020-13`, `2020-Q5`, `2021-W53`, `2021-02-29`). An inverted range (`since_period` `2024-01` with `until_period` `2020-01`), which Eurostat answered with data outside it, fails the same way.
|
|
19
|
+
- **Breaking: period faults move to `invalid_period`** ([#47](https://github.com/cyanheads/eurostat-mcp-server/issues/47)) from `conflicting_params` on `eurostat_query_dataset` and from `filter_arity` on `eurostat_download_dataset`. Bulk fault 140 is split on its fault string: `TIME_PERIOD_FILTER_SPEC_INVALID` maps to `invalid_period`, `INVALID_QUERY_NB_FILTERS` stays `filter_arity`.
|
|
20
|
+
- **Breaking: an upper-case filter key with `geo_level` fails as `conflicting_params`** ([#54](https://github.com/cyanheads/eurostat-mcp-server/issues/54)); `GEO` previously bypassed the check.
|
|
21
|
+
- **Filter keys match dimension codes in any case** on both data tools ([#54](https://github.com/cyanheads/eurostat-mcp-server/issues/54)). `eurostat_download_dataset` places `GEO` at `geo` instead of rejecting it, and keys that differ only in case pool their values.
|
|
22
|
+
- **Period literals are sent in canonical form** and echoed that way in `appliedFilters`/`appliedQuery`: extra leading zeros after the letter are dropped (`2020-Q01` → `2020-Q1`), a day of the year is sent as three digits (`2026-D1` → `2026-D001`), and `YYYY-A1` is sent as `YYYY`.
|
|
23
|
+
- **`eurostat_dataframe_describe` and `eurostat_dataframe_query` recovery hints** name both staging tools for an unknown or expired canvas or table.
|
|
24
|
+
- **Tool descriptions and docs**: `last_n_periods` states it counts back from the dataset's latest period, not the slice's; `eurostat_get_dimension_values` states how each data tool reports an invalid code — named in `unmatchedValues` or the `no_results` error by `eurostat_query_dataset`, a fault on `eurostat_download_dataset`; the README capability reference, Features list, and configuration table are rewritten to match current behavior.
|
|
25
|
+
|
|
26
|
+
## Fixed
|
|
27
|
+
|
|
28
|
+
- **`eurostat_download_dataset`'s no-canvas notice** ([#49](https://github.com/cyanheads/eurostat-mcp-server/issues/49)) no longer recommends a narrower query when every row came back inline, and names the `preview_limit` that returns them all when the download holds 500 rows or fewer.
|
|
29
|
+
- **`eurostat_download_dataset`'s `no_results` hint** ([#47](https://github.com/cyanheads/eurostat-mcp-server/issues/47)) also names a `since_period`/`until_period` range that misses the filtered series — one inside the dataset's coverage, which downloads as an empty table (a range wholly outside it fails as `invalid_dimension`).
|
|
30
|
+
|
|
31
|
+
## Dependencies
|
|
32
|
+
|
|
33
|
+
- `@socketsecurity/bun-security-scanner` (dev) `^1.1.2` → `^1.1.3`
|
|
@@ -33,7 +33,7 @@ export declare const eurostatDataframeDescribe: import("@cyanheads/mcp-ts-core")
|
|
|
33
33
|
readonly reason: "canvas_not_found";
|
|
34
34
|
readonly code: JsonRpcErrorCode.NotFound;
|
|
35
35
|
readonly when: "The canvas_id is unknown or its lifetime has elapsed.";
|
|
36
|
-
readonly recovery: "Re-run
|
|
36
|
+
readonly recovery: "Re-run the tool that staged it (eurostat_query_dataset or eurostat_download_dataset) and use the canvasId it returns.";
|
|
37
37
|
readonly thrownBy: "service";
|
|
38
38
|
}], {
|
|
39
39
|
readonly notice: z.ZodOptional<z.ZodString>;
|
|
@@ -61,7 +61,7 @@ export const eurostatDataframeDescribe = tool('eurostat_dataframe_describe', {
|
|
|
61
61
|
reason: 'canvas_not_found',
|
|
62
62
|
code: JsonRpcErrorCode.NotFound,
|
|
63
63
|
when: 'The canvas_id is unknown or its lifetime has elapsed.',
|
|
64
|
-
recovery: 'Re-run
|
|
64
|
+
recovery: 'Re-run the tool that staged it (eurostat_query_dataset or eurostat_download_dataset) and use the canvasId it returns.',
|
|
65
65
|
thrownBy: 'service',
|
|
66
66
|
},
|
|
67
67
|
],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eurostat-dataframe-describe.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/eurostat-dataframe-describe.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAEzE,MAAM,CAAC,MAAM,yBAAyB,GAAG,IAAI,CAAC,6BAA6B,EAAE;IAC3E,KAAK,EAAE,8BAA8B;IACrC,WAAW,EACT,g9BAAg9B;IACl9B,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE;IAC/E,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;QACd,SAAS,EAAE,cAAc,CAAC,QAAQ,CAChC,oJAAoJ,CACrJ;KACF,CAAC;IACF,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,8CAA8C,CAAC;QAC7E,SAAS,EAAE,CAAC;aACT,MAAM,EAAE;aACR,QAAQ,CACP,mFAAmF,CACpF;QACH,MAAM,EAAE,CAAC;aACN,KAAK,CACJ,CAAC;aACE,MAAM,CAAC;YACN,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,iCAAiC,CAAC;YAC5D,IAAI,EAAE,CAAC;iBACJ,IAAI,CAAC,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;iBACvB,QAAQ,CAAC,8CAA8C,CAAC;YAC3D,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uBAAuB,CAAC;YACtD,SAAS,EAAE,CAAC;iBACT,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CACP,uHAAuH,CACxH;YACH,OAAO,EAAE,CAAC;iBACP,KAAK,CACJ,CAAC;iBACE,MAAM,CAAC;gBACN,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC;gBACzC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,6CAA6C,CAAC;gBACxE,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,iCAAiC,CAAC;aAClE,CAAC;iBACD,QAAQ,CAAC,0BAA0B,CAAC,CACxC;iBACA,QAAQ,CAAC,+BAA+B,CAAC;SAC7C,CAAC;aACD,QAAQ,CAAC,yCAAyC,CAAC,CACvD;aACA,QAAQ,CACP,+GAA+G,CAChH;KACJ,CAAC;IACF,UAAU,EAAE;QACV,MAAM,EAAE,CAAC;aACN,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,+EAA+E,CAAC;KAC7F;IAED,MAAM,EAAE;QACN;YACE,MAAM,EAAE,iBAAiB;YACzB,IAAI,EAAE,gBAAgB,CAAC,kBAAkB;YACzC,IAAI,EAAE,mFAAmF;YACzF,SAAS,EAAE,KAAK;YAChB,QAAQ,EACN,uGAAuG;SAC1G;QACD;YACE,MAAM,EAAE,kBAAkB;YAC1B,IAAI,EAAE,gBAAgB,CAAC,QAAQ;YAC/B,IAAI,EAAE,uDAAuD;YAC7D,QAAQ,EACN,
|
|
1
|
+
{"version":3,"file":"eurostat-dataframe-describe.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/eurostat-dataframe-describe.tool.ts"],"names":[],"mappings":"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"}
|
|
@@ -24,13 +24,13 @@ export declare const eurostatDataframeQuery: import("@cyanheads/mcp-ts-core").To
|
|
|
24
24
|
readonly reason: "canvas_not_found";
|
|
25
25
|
readonly code: JsonRpcErrorCode.NotFound;
|
|
26
26
|
readonly when: "The canvas_id is unknown or its lifetime has elapsed.";
|
|
27
|
-
readonly recovery: "Re-run
|
|
27
|
+
readonly recovery: "Re-run the tool that staged it (eurostat_query_dataset or eurostat_download_dataset) and use the canvasId it returns.";
|
|
28
28
|
readonly thrownBy: "service";
|
|
29
29
|
}, {
|
|
30
30
|
readonly reason: "missing_table";
|
|
31
31
|
readonly code: JsonRpcErrorCode.NotFound;
|
|
32
32
|
readonly when: "The SQL names a table that is not staged on this canvas, or that has expired.";
|
|
33
|
-
readonly recovery: "Call eurostat_dataframe_describe for the staged table names, or re-run
|
|
33
|
+
readonly recovery: "Call eurostat_dataframe_describe for the staged table names, or re-run the tool that staged them (eurostat_query_dataset or eurostat_download_dataset).";
|
|
34
34
|
readonly thrownBy: "service";
|
|
35
35
|
}], undefined>;
|
|
36
36
|
//# sourceMappingURL=eurostat-dataframe-query.tool.d.ts.map
|
|
@@ -43,14 +43,14 @@ export const eurostatDataframeQuery = tool('eurostat_dataframe_query', {
|
|
|
43
43
|
reason: 'canvas_not_found',
|
|
44
44
|
code: JsonRpcErrorCode.NotFound,
|
|
45
45
|
when: 'The canvas_id is unknown or its lifetime has elapsed.',
|
|
46
|
-
recovery: 'Re-run
|
|
46
|
+
recovery: 'Re-run the tool that staged it (eurostat_query_dataset or eurostat_download_dataset) and use the canvasId it returns.',
|
|
47
47
|
thrownBy: 'service',
|
|
48
48
|
},
|
|
49
49
|
{
|
|
50
50
|
reason: 'missing_table',
|
|
51
51
|
code: JsonRpcErrorCode.NotFound,
|
|
52
52
|
when: 'The SQL names a table that is not staged on this canvas, or that has expired.',
|
|
53
|
-
recovery: 'Call eurostat_dataframe_describe for the staged table names, or re-run
|
|
53
|
+
recovery: 'Call eurostat_dataframe_describe for the staged table names, or re-run the tool that staged them (eurostat_query_dataset or eurostat_download_dataset).',
|
|
54
54
|
thrownBy: 'service',
|
|
55
55
|
},
|
|
56
56
|
],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eurostat-dataframe-query.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/eurostat-dataframe-query.tool.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAEzE,MAAM,CAAC,MAAM,sBAAsB,GAAG,IAAI,CAAC,0BAA0B,EAAE;IACrE,KAAK,EAAE,2BAA2B;IAClC,WAAW,EACT,wiCAAwiC;IAC1iC,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE;IAC/E,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;QACd,SAAS,EAAE,cAAc,CAAC,QAAQ,CAChC,oJAAoJ,CACrJ;QACD,GAAG,EAAE,CAAC;aACH,MAAM,EAAE;aACR,GAAG,CAAC,CAAC,CAAC;aACN,QAAQ,CACP,kPAAkP,CACnP;KACJ,CAAC;IACF,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,0CAA0C,CAAC;QACzE,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAC,mCAAmC,CAAC;QAC1E,IAAI,EAAE,CAAC;aACJ,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;aACxC,QAAQ,CACP,oPAAoP,CACrP;QACH,QAAQ,EAAE,CAAC;aACR,MAAM,EAAE;aACR,QAAQ,CACP,6FAA6F,CAC9F;QACH,SAAS,EAAE,CAAC;aACT,OAAO,EAAE;aACT,QAAQ,CACP,8IAA8I,CAC/I;KACJ,CAAC;IAEF,MAAM,EAAE;QACN;YACE,MAAM,EAAE,iBAAiB;YACzB,IAAI,EAAE,gBAAgB,CAAC,kBAAkB;YACzC,IAAI,EAAE,gFAAgF;YACtF,SAAS,EAAE,KAAK;YAChB,QAAQ,EACN,uGAAuG;SAC1G;QACD;YACE,MAAM,EAAE,kBAAkB;YAC1B,IAAI,EAAE,gBAAgB,CAAC,QAAQ;YAC/B,IAAI,EAAE,uDAAuD;YAC7D,QAAQ,EACN,
|
|
1
|
+
{"version":3,"file":"eurostat-dataframe-query.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/eurostat-dataframe-query.tool.ts"],"names":[],"mappings":"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"}
|
|
@@ -43,9 +43,14 @@ export declare const eurostatDownloadDataset: import("@cyanheads/mcp-ts-core").T
|
|
|
43
43
|
}, {
|
|
44
44
|
readonly reason: "filter_arity";
|
|
45
45
|
readonly code: JsonRpcErrorCode.ValidationError;
|
|
46
|
-
readonly when: "Eurostat rejected the positional dimension key because it carried the wrong number of positions (SDMX faultcode 140), meaning the dataset structure has changed since the metadata call.";
|
|
46
|
+
readonly when: "Eurostat rejected the positional dimension key because it carried the wrong number of positions (SDMX faultcode 140, INVALID_QUERY_NB_FILTERS), meaning the dataset structure has changed since the metadata call.";
|
|
47
47
|
readonly recovery: "Retry without filters to download the whole dataset, or re-read the dimensions with eurostat_get_dataset_info.";
|
|
48
48
|
readonly thrownBy: "service";
|
|
49
|
+
}, {
|
|
50
|
+
readonly reason: "invalid_period";
|
|
51
|
+
readonly code: JsonRpcErrorCode.ValidationError;
|
|
52
|
+
readonly when: "since_period or until_period is not a period literal, or names a month, quarter, semester, trimester, week or day that does not exist, or since_period starts after until_period ends. Checked before any request — the bulk endpoint would otherwise roll an out-of-range period into a neighbouring one, and answer an inverted range with the whole series — and SDMX faultcode 140 TIME_PERIOD_FILTER_SPEC_INVALID maps here too.";
|
|
53
|
+
readonly recovery: "Write since_period/until_period as 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 (a day the year has, up to 366), for example \"2020\", \"2020-01\" or \"2020-Q1\", with since_period starting no later than until_period ends.";
|
|
49
54
|
}, {
|
|
50
55
|
readonly reason: "async_queued";
|
|
51
56
|
readonly code: JsonRpcErrorCode.ServiceUnavailable;
|
|
@@ -57,7 +62,7 @@ export declare const eurostatDownloadDataset: import("@cyanheads/mcp-ts-core").T
|
|
|
57
62
|
readonly reason: "no_results";
|
|
58
63
|
readonly code: JsonRpcErrorCode.NotFound;
|
|
59
64
|
readonly when: "The download completed but carried no populated observation cells.";
|
|
60
|
-
readonly recovery: "Verify the filter values with eurostat_get_dimension_values — a combination that exists in no cell
|
|
65
|
+
readonly recovery: "Verify the filter values with eurostat_get_dimension_values and keep since_period/until_period inside the series' coverage — a combination that exists in no cell and a range that misses the series both download as an empty table.";
|
|
61
66
|
}, {
|
|
62
67
|
readonly reason: "upstream_fault";
|
|
63
68
|
readonly code: JsonRpcErrorCode.ServiceUnavailable;
|
|
@@ -71,9 +76,7 @@ export declare const eurostatDownloadDataset: import("@cyanheads/mcp-ts-core").T
|
|
|
71
76
|
readonly recovery: "Omit canvas_id so the download starts a fresh canvas and returns its canvasId.";
|
|
72
77
|
readonly thrownBy: "service";
|
|
73
78
|
}], {
|
|
74
|
-
readonly
|
|
75
|
-
readonly shown: z.ZodOptional<z.ZodNumber>;
|
|
76
|
-
readonly cap: z.ZodOptional<z.ZodNumber>;
|
|
79
|
+
readonly totalCount: z.ZodNumber;
|
|
77
80
|
readonly appliedQuery: z.ZodObject<{
|
|
78
81
|
filters: z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString>>;
|
|
79
82
|
sincePeriod: z.ZodOptional<z.ZodString>;
|
|
@@ -83,7 +86,7 @@ export declare const eurostatDownloadDataset: import("@cyanheads/mcp-ts-core").T
|
|
|
83
86
|
readonly notice: z.ZodOptional<z.ZodString>;
|
|
84
87
|
}>;
|
|
85
88
|
/** Contract reasons the bulk service's classified failures map onto. */
|
|
86
|
-
type MappedReason = 'async_queued' | 'filter_arity' | 'invalid_dimension' | 'not_found' | 'upstream_fault';
|
|
89
|
+
type MappedReason = 'async_queued' | 'filter_arity' | 'invalid_dimension' | 'invalid_period' | 'not_found' | 'upstream_fault';
|
|
87
90
|
/**
|
|
88
91
|
* Translate a service-layer failure into the tool's declared contract.
|
|
89
92
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eurostat-download-dataset.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/eurostat-download-dataset.tool.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAEjD,OAAO,EAAE,gBAAgB,EAAiB,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"eurostat-download-dataset.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/eurostat-download-dataset.tool.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAEjD,OAAO,EAAE,gBAAgB,EAAiB,MAAM,+BAA+B,CAAC;AA8BhF,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAoalC,CAAC;AAEH,wEAAwE;AACxE,KAAK,YAAY,GACb,cAAc,GACd,cAAc,GACd,mBAAmB,GACnB,gBAAgB,GAChB,WAAW,GACX,gBAAgB,CAAC;AAErB;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,GAAG,EAAE,OAAO,EACZ,WAAW,EAAE,MAAM,GAClB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,GAAG,SAAS,CA2CrE"}
|