@cyanheads/eurostat-mcp-server 0.8.1 → 0.10.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 +27 -21
- package/CLAUDE.md +27 -21
- package/Dockerfile +94 -46
- package/README.md +42 -38
- package/changelog/0.10.x/0.10.0.md +40 -0
- package/changelog/0.9.x/0.9.0.md +43 -0
- package/dist/config/server-config.d.ts +1 -0
- package/dist/config/server-config.d.ts.map +1 -1
- package/dist/config/server-config.js +5 -0
- package/dist/config/server-config.js.map +1 -1
- package/dist/index.js +45 -5
- package/dist/index.js.map +1 -1
- package/dist/mcp-server/tools/definitions/eurostat-browse-themes.tool.d.ts +10 -2
- package/dist/mcp-server/tools/definitions/eurostat-browse-themes.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/eurostat-browse-themes.tool.js +63 -10
- package/dist/mcp-server/tools/definitions/eurostat-browse-themes.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/eurostat-dataframe-describe.tool.d.ts +0 -1
- package/dist/mcp-server/tools/definitions/eurostat-dataframe-describe.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/eurostat-dataframe-describe.tool.js +15 -5
- package/dist/mcp-server/tools/definitions/eurostat-dataframe-describe.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/eurostat-dataframe-drop.tool.d.ts +34 -0
- package/dist/mcp-server/tools/definitions/eurostat-dataframe-drop.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/eurostat-dataframe-drop.tool.js +112 -0
- package/dist/mcp-server/tools/definitions/eurostat-dataframe-drop.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/eurostat-dataframe-query.tool.d.ts +0 -2
- package/dist/mcp-server/tools/definitions/eurostat-dataframe-query.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/eurostat-dataframe-query.tool.js +18 -6
- 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 +1 -2
- 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 +39 -14
- package/dist/mcp-server/tools/definitions/eurostat-download-dataset.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/eurostat-get-dataset-info.tool.d.ts +1 -1
- package/dist/mcp-server/tools/definitions/eurostat-get-dataset-info.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/eurostat-get-dataset-info.tool.js +10 -1
- package/dist/mcp-server/tools/definitions/eurostat-get-dataset-info.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/eurostat-get-dimension-values.tool.d.ts +13 -6
- package/dist/mcp-server/tools/definitions/eurostat-get-dimension-values.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/eurostat-get-dimension-values.tool.js +235 -53
- 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 +9 -5
- 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 +45 -19
- package/dist/mcp-server/tools/definitions/eurostat-query-dataset.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/eurostat-search-datasets.tool.d.ts +10 -2
- package/dist/mcp-server/tools/definitions/eurostat-search-datasets.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/eurostat-search-datasets.tool.js +79 -14
- package/dist/mcp-server/tools/definitions/eurostat-search-datasets.tool.js.map +1 -1
- package/dist/mcp-server/tools/narrowing-advice.d.ts +2 -1
- package/dist/mcp-server/tools/narrowing-advice.d.ts.map +1 -1
- package/dist/mcp-server/tools/narrowing-advice.js +4 -1
- package/dist/mcp-server/tools/narrowing-advice.js.map +1 -1
- package/dist/mcp-server/tools/value-list-paging.d.ts +49 -0
- package/dist/mcp-server/tools/value-list-paging.d.ts.map +1 -0
- package/dist/mcp-server/tools/value-list-paging.js +73 -0
- package/dist/mcp-server/tools/value-list-paging.js.map +1 -0
- package/dist/services/canvas-accessor.d.ts +21 -7
- package/dist/services/canvas-accessor.d.ts.map +1 -1
- package/dist/services/canvas-accessor.js +26 -11
- package/dist/services/canvas-accessor.js.map +1 -1
- package/dist/services/eurostat-bulk/eurostat-bulk-service.d.ts +8 -4
- package/dist/services/eurostat-bulk/eurostat-bulk-service.d.ts.map +1 -1
- package/dist/services/eurostat-bulk/eurostat-bulk-service.js +62 -25
- package/dist/services/eurostat-bulk/eurostat-bulk-service.js.map +1 -1
- package/dist/services/eurostat-catalogue/eurostat-catalogue-service.d.ts +46 -4
- package/dist/services/eurostat-catalogue/eurostat-catalogue-service.d.ts.map +1 -1
- package/dist/services/eurostat-catalogue/eurostat-catalogue-service.js +134 -33
- package/dist/services/eurostat-catalogue/eurostat-catalogue-service.js.map +1 -1
- package/dist/services/eurostat-data/eurostat-data-service.d.ts +5 -0
- package/dist/services/eurostat-data/eurostat-data-service.d.ts.map +1 -1
- package/dist/services/eurostat-data/eurostat-data-service.js +133 -24
- package/dist/services/eurostat-data/eurostat-data-service.js.map +1 -1
- package/dist/services/eurostat-filters.d.ts +13 -0
- package/dist/services/eurostat-filters.d.ts.map +1 -0
- package/dist/services/eurostat-filters.js +21 -0
- package/dist/services/eurostat-filters.js.map +1 -0
- package/dist/services/eurostat-outage.d.ts +27 -0
- package/dist/services/eurostat-outage.d.ts.map +1 -0
- package/dist/services/eurostat-outage.js +44 -0
- package/dist/services/eurostat-outage.js.map +1 -0
- package/package.json +12 -11
- package/server.json +26 -26
package/README.md
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
<h1>@cyanheads/eurostat-mcp-server</h1>
|
|
3
3
|
<p><b>Search and query the Eurostat catalogue — EU economy, demography, trade, health, and NUTS regional data via MCP. STDIO or Streamable HTTP.</b>
|
|
4
|
-
<div>6 Tools (
|
|
4
|
+
<div>6 Tools (up to 9 with the dataframe canvas) • 1 Resource</div>
|
|
5
5
|
</p>
|
|
6
6
|
</div>
|
|
7
7
|
|
|
8
8
|
<div align="center">
|
|
9
9
|
|
|
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/)
|
|
11
11
|
|
|
12
12
|
</div>
|
|
13
13
|
|
|
@@ -35,18 +35,19 @@ The catalogue spans two Eurostat hosts. Most datasets come from the disseminatio
|
|
|
35
35
|
|
|
36
36
|
### Tools
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
Three of the nine are listed only when the dataframe canvas is enabled (`CANVAS_PROVIDER_TYPE=duckdb`), and `eurostat_dataframe_drop` also needs `EUROSTAT_DATAFRAME_DROP_ENABLED=true`.
|
|
39
39
|
|
|
40
40
|
| Tool | Description |
|
|
41
41
|
|:---|:---|
|
|
42
42
|
| `eurostat_search_datasets` | Search the Eurostat catalogue by keyword — returns codes, descriptions, period coverage, and theme breadcrumbs |
|
|
43
43
|
| `eurostat_browse_themes` | Navigate the Eurostat theme hierarchy — list root themes or drill into subthemes and datasets |
|
|
44
44
|
| `eurostat_get_dataset_info` | Fetch dataset metadata: dimensions with sample values, time range, observation count, and last-update date |
|
|
45
|
-
| `eurostat_get_dimension_values` | List all valid codes for one dataset dimension, with NUTS hierarchy filtering for `geo` |
|
|
45
|
+
| `eurostat_get_dimension_values` | List all valid codes for one dataset dimension, paged, with a code/label word filter and NUTS hierarchy filtering for `geo` |
|
|
46
46
|
| `eurostat_query_dataset` | Fetch a bounded preview of decoded observations with dimension filters, NUTS geo-level, and time-range controls |
|
|
47
47
|
| `eurostat_download_dataset` | Download a whole dataset via the SDMX bulk endpoint and stage every observation on the dataframe canvas |
|
|
48
48
|
| `eurostat_dataframe_describe` | List the tables staged on a dataframe canvas, with row counts and column types |
|
|
49
49
|
| `eurostat_dataframe_query` | Run a read-only SQL SELECT across staged tables |
|
|
50
|
+
| `eurostat_dataframe_drop` | Remove one staged table from a dataframe canvas, leaving its other tables in place (opt-in) |
|
|
50
51
|
|
|
51
52
|
### Resources
|
|
52
53
|
|
|
@@ -60,76 +61,77 @@ The same metadata is available through `eurostat_get_dataset_info` for tool-only
|
|
|
60
61
|
|
|
61
62
|
### `eurostat_search_datasets` <sub>tool</sub>
|
|
62
63
|
|
|
63
|
-
- `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`
|
|
64
|
-
- Results carry `code`, `label`, `type` (`dataset` / `table`), period coverage, `obsCount`, `lastUpdated`, and `themePath
|
|
65
|
-
-
|
|
66
|
-
- Fails as `no_match` — for a query naming such a `DS-*` code, saying the collection is not disseminated rather than suggesting a broader search — or `invalid_cursor` when a cursor is reused with a different query or after the catalogue refreshes
|
|
64
|
+
- `query` tokens are ANDed case-insensitively across each dataset's label, theme breadcrumb, and code, ignoring spacing beside punctuation in the catalogue (`Rev.2` finds `Rev. 2`); `limit` 1–100 (default 20), paged by passing `nextCursor` back as `cursor`
|
|
65
|
+
- Results carry `code`, `label`, `type` (`dataset` / `table`), period coverage, `obsCount`, `lastUpdated`, and `themePath`, with `totalMatches` across every page; fails as `no_match` (naming each word whose removal alone finds matches, with the count), `invalid_cursor`, or a retryable `upstream_fault` when the server has no catalogue loaded yet and Eurostat's table of contents answers HTTP 5xx or cannot be reached on every retry
|
|
66
|
+
- While the Comext dataflow list cannot be loaded, results come from the dissemination catalogue alone and carry `comextListMissing` and a `notice`; a catalogue a failed refresh could not replace carries `catalogueLoadedAt`, and a `no_match` hint names both
|
|
67
67
|
|
|
68
68
|
---
|
|
69
69
|
|
|
70
70
|
### `eurostat_browse_themes` <sub>tool</sub>
|
|
71
71
|
|
|
72
|
-
- Omit `theme_code` for the top-level theme folders; pass a folder code for its immediate children
|
|
73
|
-
-
|
|
74
|
-
-
|
|
75
|
-
- Fails as `not_found` for an unknown code, `not_a_folder` for a dataset or table code
|
|
72
|
+
- Omit `theme_code` for the top-level theme folders; pass a folder code for its immediate children. The Comext collections sit under `ext_go_detail` (detailed trade, in `ext_go`) and `prom` (PRODCOM, in `icts`)
|
|
73
|
+
- Items carry `code`, `label`, `type` (`folder` / `dataset` / `table`), and `hasChildren`, with a `parentPath` breadcrumb and `otherPlacements` for a folder code filed in several branches; fails as `not_found` for an unknown code, `not_a_folder` for a dataset or table code, or a retryable `upstream_fault` when the server has no catalogue loaded yet and Eurostat's table of contents answers HTTP 5xx or cannot be reached on every retry
|
|
74
|
+
- While the Comext dataflow list cannot be loaded, `ext_go` and `icts` carry `comextListMissing` and a `notice`, and `not_found` on a Comext folder or `DS-*` code says the list could not be loaded; a catalogue a failed refresh could not replace carries `catalogueLoadedAt`, and a `not_found` hint gives its load time
|
|
76
75
|
|
|
77
76
|
---
|
|
78
77
|
|
|
79
78
|
### `eurostat_get_dataset_info` <sub>tool</sub>
|
|
80
79
|
|
|
81
80
|
- One `dataset_code`; returns every dimension with `valuesCount` and up to 10 `sampleValues`, plus `timeRange`, `obsCount`, `lastUpdated`, and the ESMS `metadataUrl`
|
|
82
|
-
-
|
|
83
|
-
- Fails as `not_found` for an unknown dataset, or `upstream_fault` when Eurostat returns a structure or content constraint the server cannot read; a failed read is not cached, so a later call downloads it afresh
|
|
81
|
+
- Fails as `not_found` for an unknown dataset, or `upstream_fault` when Eurostat returns a structure or content constraint the server cannot read, or when the structure endpoint answers HTTP 5xx or cannot be reached on every retry (marked retryable)
|
|
84
82
|
|
|
85
83
|
---
|
|
86
84
|
|
|
87
85
|
### `eurostat_get_dimension_values` <sub>tool</sub>
|
|
88
86
|
|
|
89
|
-
- `dataset_code` plus `dimension`;
|
|
90
|
-
-
|
|
91
|
-
-
|
|
92
|
-
-
|
|
93
|
-
-
|
|
87
|
+
- `dataset_code` plus `dimension`; for `geo`, `geo_level` picks a NUTS level (`aggregate`, `country` by default, `nuts1`, `nuts2`, `nuts3`). Values come back in Eurostat's order
|
|
88
|
+
- `filter` keeps the values whose code and label contain every word given, ignoring case and accents (`palma frankfurt` finds `DE_EDDF_ES_LEPA`), with `matchCount` counting the matches
|
|
89
|
+
- A long list comes back a page at a time: each response holds whole values within 64,000 bytes, up to an optional `limit`, and a page with more after it carries `truncated`, `nextCursor` (pass it back as `cursor`), and a `notice`. `totalCount` counts every value
|
|
90
|
+
- Fails as `not_found`, `no_results`, `conflicting_params`, `invalid_cursor`, `upstream_fault` (a structure or content constraint the server cannot read, or, marked retryable, a structure endpoint that answers HTTP 5xx or cannot be reached on every retry), or `canvas_not_found`
|
|
91
|
+
- `canvas_id` stages every value, whatever `filter` and `limit` are, on that canvas as a `code` / `label` table (`canvasId` / `tableName` / `stagedRowCount`) that labels a download's code columns through a join; this tool never starts a canvas of its own
|
|
94
92
|
|
|
95
93
|
---
|
|
96
94
|
|
|
97
95
|
### `eurostat_query_dataset` <sub>tool</sub>
|
|
98
96
|
|
|
99
|
-
- `dataset_code` plus `filters` (`{dimension_code: [values]}
|
|
100
|
-
- Each observation carries code/label pairs per dimension, a nullable `value`,
|
|
101
|
-
-
|
|
102
|
-
- 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`
|
|
97
|
+
- `dataset_code` plus `filters` (`{dimension_code: [values]}`), `geo_level`, and either `since_period` / `until_period` (`2020`, `2020-Q1`, `2020-01`, down to `YYYY-Wnn` and `YYYY-Dnnn`) or `last_n_periods`; `preview_limit` 1–500 (default 50) sets the inline rows; `lang` is `EN`, `FR`, or `DE`
|
|
98
|
+
- Each observation carries code/label pairs per dimension, a nullable `value`, `status` (OBS_FLAG), and `confStatus` (CONF_STATUS); `obsCount`, `missingObsCount`, and `timeRange` cover the whole match, `truncated` is true above 5,000 observations, and `unmatchedValues` names filter values that matched nothing
|
|
99
|
+
- Fails as `not_found`, `no_results` (naming the unmatched values and the periods that carry no value), `invalid_dimension`, `invalid_period`, `conflicting_params`, a non-retryable `async_response` for a query too large to serve inline, `canvas_not_found`, or a retryable `upstream_fault` when the Statistics API answers HTTP 5xx or cannot be reached on every retry
|
|
103
100
|
|
|
104
101
|
---
|
|
105
102
|
|
|
106
103
|
### `eurostat_download_dataset` <sub>tool</sub>
|
|
107
104
|
|
|
108
|
-
- `dataset_code` plus the same `filters` map and `since_period` / `until_period`
|
|
109
|
-
- Returns `rowCount` (echoed as `totalCount`), `missingCount`, `periodRange`, and `bytesRead` for the whole download;
|
|
110
|
-
-
|
|
111
|
-
- 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, a non-retryable `extraction_too_big` when Eurostat refuses it as too large (past its 5,000,000-row limit, or an unfiltered download of a large Comext collection) with the dimensions left to filter, `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`
|
|
105
|
+
- `dataset_code` plus the same `filters` map and `since_period` / `until_period` (no `last_n_periods`: the TSV keeps a column per period unless a range drops it); `preview_limit` 1–500 (default 50)
|
|
106
|
+
- Returns `rowCount` (echoed as `totalCount`), `missingCount`, `periodRange`, and `bytesRead` for the whole download; fails as `not_found`, `invalid_dimension`, `invalid_period`, `filter_arity`, a non-retryable `async_queued` or `extraction_too_big`, `no_results`, `upstream_fault` (an unmodelled fault or a body that is not a TSV table, or, marked retryable, an SDMX endpoint that answers HTTP 5xx or cannot be reached on every retry), or `canvas_not_found`
|
|
107
|
+
- The `EUROSTAT_BULK_MAX_BYTES` budget (default 50 MiB) stops a transfer mid-stream and returns what arrived with `budgetExceeded: true`
|
|
112
108
|
|
|
113
109
|
---
|
|
114
110
|
|
|
115
111
|
### `eurostat_dataframe_describe` <sub>tool</sub>
|
|
116
112
|
|
|
117
|
-
- `canvas_id` from a staging response; lists each table's `name`, `rowCount`,
|
|
118
|
-
- `eurostat_query_dataset`
|
|
119
|
-
- `eurostat_get_dimension_values` tables carry `code` and `label`: join one to a download on its dimension column (`d.geo = g.code`) to label it
|
|
113
|
+
- `canvas_id` from a staging response; lists each table's `name`, `rowCount`, typed columns, and `expiresAt` (sliding `CANVAS_TTL_MS`, default 24h); fails as `canvas_not_found` or `canvas_disabled`
|
|
114
|
+
- Columns differ by the tool that staged them: `eurostat_query_dataset` writes a code and a `_label` column per dimension, `eurostat_download_dataset` codes only plus `time` — both with the same `obs_*` and `conf_status*` measures, so they join on dimension codes and `time` — and `eurostat_get_dimension_values` writes `code` and `label`
|
|
120
115
|
|
|
121
116
|
---
|
|
122
117
|
|
|
123
118
|
### `eurostat_dataframe_query` <sub>tool</sub>
|
|
124
119
|
|
|
125
120
|
- One read-only `SELECT` per call; chained statements, other verbs, and functions that read files or external data are rejected
|
|
126
|
-
- Returns `columns`, `rows`, `rowCount`, and `truncated`,
|
|
121
|
+
- Returns `columns`, `rows`, `rowCount`, and `truncated`, true past `CANVAS_DEFAULT_ROW_LIMIT` (default 10,000) rows; 64-bit integers arrive as strings. Fails as `missing_table`, `canvas_not_found`, or `canvas_disabled`
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
### `eurostat_dataframe_drop` <sub>tool</sub>
|
|
126
|
+
|
|
127
|
+
- `canvas_id` plus `table_name`, exactly as `eurostat_dataframe_describe` lists it; removes that one table and leaves the canvas and its other tables in place. Listed only when `EUROSTAT_DATAFRAME_DROP_ENABLED=true` is set beside the canvas
|
|
128
|
+
- Returns `canvasId`, `tableName`, `dropped`, and `expiresAt`; `dropped` is `false`, with a `notice`, when nothing by that name was staged, so repeating a drop is safe. Fails as `canvas_not_found`, `identifier_reserved`, or `canvas_disabled`
|
|
127
129
|
|
|
128
130
|
---
|
|
129
131
|
|
|
130
132
|
### `eurostat://dataset/{dataset_code}` <sub>resource</sub>
|
|
131
133
|
|
|
132
|
-
- Same payload as `eurostat_get_dataset_info`, returned as `application/json`
|
|
134
|
+
- Same payload as `eurostat_get_dataset_info`, returned as `application/json`; a failed read carries the same `reason`, and `retryable` on an outage
|
|
133
135
|
- `dataset_code` comes from `eurostat_search_datasets` or `eurostat_browse_themes`
|
|
134
136
|
|
|
135
137
|
## Features
|
|
@@ -139,10 +141,10 @@ Built on [`@cyanheads/mcp-ts-core`](https://github.com/cyanheads/mcp-ts-core): s
|
|
|
139
141
|
Eurostat-specific:
|
|
140
142
|
|
|
141
143
|
- 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
|
|
142
|
-
- The Comext host's `DS-*` collections through the same tools: detailed trade by CN8, HS, SITC, BEC and CPA, and PRODCOM.
|
|
143
|
-
- NUTS geo-level filtering (`aggregate` / `country` / `nuts1` / `nuts2` / `nuts3`) on `eurostat_query_dataset` and `eurostat_get_dimension_values
|
|
144
|
-
- 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
|
|
144
|
+
- The Comext host's `DS-*` collections through the same tools: detailed trade by CN8, HS, SITC, BEC and CPA, and PRODCOM. They report no period coverage or `obsCount`, and the trade flows mix annual and monthly series in one dataset, so filter `freq`; `product`, `reporter` and `partner` carry aggregates (`TOTAL`, `EU27_2020`, `EXT_EU27_2020`) that double-count when summed with their members. The Comext host serves no large collection unfiltered. PRODCOM values published as text arrive in `valueText` / `obs_value_text` (the unit `KG`), and its `:C` as confidentiality status `C`. A collection on neither host, such as the legacy `DS-056120`, is not disseminated
|
|
145
|
+
- NUTS geo-level filtering (`aggregate` / `country` / `nuts1` / `nuts2` / `nuts3`) on `eurostat_query_dataset` and `eurostat_get_dimension_values`, and 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
|
|
145
146
|
- Eurostat's too-large-to-serve responses (HTTP-200 async warnings, HTTP 413, SOAP fault 413, SOAP queue tickets) come back as non-retryable `async_response`, `extraction_too_big`, or `async_queued` errors that name the dataset's own dimensions left to filter, not timeouts
|
|
147
|
+
- A Eurostat outage — HTTP 5xx or an unreachable host on all four attempts, about seven seconds of backoff in all — comes back as `upstream_fault` marked `retryable`, with a hint naming the endpoint and saying to retry in a few minutes. HTTP 501 fails on its first attempt, marked not retryable
|
|
146
148
|
- 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 — including a dimension's code/label list from `eurostat_get_dimension_values`, which labels a bulk table's codes. An empty download fails as `no_results` without creating or touching a canvas. The `.mcpb` bundle strips the native DuckDB binding, so SQL analytics need the npm, Docker, or from-source install
|
|
147
149
|
|
|
148
150
|
Agent-friendly output:
|
|
@@ -270,15 +272,17 @@ cp .env.example .env
|
|
|
270
272
|
| `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) |
|
|
271
273
|
| `EUROSTAT_BULK_TIMEOUT_MS` | Timeout for one `eurostat_download_dataset` transfer, in ms. | `120000` (2 min) |
|
|
272
274
|
| `EUROSTAT_BULK_MAX_BYTES` | Byte budget for one bulk download, counted on the decoded TSV and enforced while streaming. | `52428800` (50 MiB) |
|
|
273
|
-
| `CANVAS_PROVIDER_TYPE` | `duckdb` enables the dataframe canvas: lists
|
|
275
|
+
| `CANVAS_PROVIDER_TYPE` | `duckdb` enables the dataframe canvas: lists `eurostat_dataframe_describe` and `eurostat_dataframe_query` and turns on staging. | `none` |
|
|
274
276
|
| `CANVAS_TTL_MS` | Sliding lifetime of a staged canvas, in ms. | `86400000` (24 h) |
|
|
275
277
|
| `CANVAS_DEFAULT_ROW_LIMIT` | Max rows one `eurostat_dataframe_query` returns before reporting `truncated`. | `10000` |
|
|
278
|
+
| `EUROSTAT_DATAFRAME_DROP_ENABLED` | `true` lists `eurostat_dataframe_drop`, which removes one staged table; needs `CANVAS_PROVIDER_TYPE=duckdb`. Off by default because a drop cannot be undone. | `false` |
|
|
276
279
|
| `MCP_TRANSPORT_TYPE` | Transport: `stdio` or `http`. | `stdio` |
|
|
277
280
|
| `MCP_HTTP_PORT` | HTTP server port. | `3010` |
|
|
278
281
|
| `MCP_SESSION_MODE` | HTTP session mode: `stateless`, `stateful`, or `auto`. The server declares `stateless`; a set value overrides it. | `stateless` |
|
|
279
282
|
| `MCP_AUTH_MODE` | Authentication: `none`, `jwt`, or `oauth`. | `none` |
|
|
280
283
|
| `MCP_LOG_LEVEL` | Log level (`debug`, `info`, `warning`, `error`, etc.). The Docker image sets `info`. | `debug` |
|
|
281
284
|
| `LOGS_DIR` | Directory for log files (Node.js only). | `<project-root>/logs` |
|
|
285
|
+
| `LOG_TOOL_FAILURE_PAYLOADS` | Log each failed tool call's arguments and result, redacted by key name and capped at `LOG_TOOL_FAILURE_PAYLOAD_MAX_BYTES` (default `16384`). A secret inside a free-form value is not redacted. | `false` |
|
|
282
286
|
| `STORAGE_PROVIDER_TYPE` | Storage backend: `in-memory`, `filesystem`, `supabase`, `cloudflare-kv/r2/d1`. | `in-memory` |
|
|
283
287
|
| `OTEL_ENABLED` | Enable [OpenTelemetry](https://github.com/cyanheads/mcp-ts-core/tree/main/docs/telemetry). | `false` |
|
|
284
288
|
|
|
@@ -320,8 +324,8 @@ The Dockerfile defaults to HTTP transport, stateless session mode, and logs to `
|
|
|
320
324
|
|
|
321
325
|
| Directory | Purpose |
|
|
322
326
|
|:---|:---|
|
|
323
|
-
| `src/index.ts` | `createApp()` entry point — registers tools and the resource, inits services, gates the dataframe tools on the canvas. |
|
|
324
|
-
| `src/mcp-server/tools` | Tool definitions (`*.tool.ts`). Six discovery and data tools, plus
|
|
327
|
+
| `src/index.ts` | `createApp()` entry point — registers tools and the resource, inits services, gates the dataframe tools on the canvas and the drop tool on its own flag. |
|
|
328
|
+
| `src/mcp-server/tools` | Tool definitions (`*.tool.ts`). Six discovery and data tools, plus three canvas-gated dataframe tools, one of them opt-in. |
|
|
325
329
|
| `src/mcp-server/resources` | Resource definitions. Dataset metadata resource. |
|
|
326
330
|
| `src/services/eurostat-catalogue` | Catalogue service — fetches and parses the Eurostat TOC, merges the Comext dataflow list into it, with a TTL-bounded in-memory cache. |
|
|
327
331
|
| `src/services/eurostat-data` | Statistics API service — SDMX metadata parsing with a per-dataset cache, JSON-stat 2.0 decoding, async-response detection, canvas row source. |
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
summary: "Pages long dimension-value lists with filter and cursor, rejects filter keys named like API controls, reports upstream outages and partial or stale catalogues, fixes blank filters, time-selection conflicts and canvas recoveries, matches search terms across spacing beside punctuation, and adopts mcp-ts-core 0.13.15."
|
|
3
|
+
breaking: true
|
|
4
|
+
security: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 0.10.0 — 2026-10-14
|
|
8
|
+
|
|
9
|
+
## Added
|
|
10
|
+
|
|
11
|
+
- **`eurostat_get_dimension_values` takes `filter`, `limit`, and `cursor`** ([#64](https://github.com/cyanheads/eurostat-mcp-server/issues/64)) — `filter` keeps values whose code and label contain every word given (case- and accent-blind, any order), with `matchCount` counting the matches; a page with more after it carries `truncated`, `nextCursor`, and a `notice`. A cursor bound to another `dataset_code`, `dimension`, `geo_level`, or `filter`, or resuming after a code no longer listed, fails as `invalid_cursor`; every binding but `geo_level` is checked before the dimension's structure is fetched. On a deployment with a dataframe canvas, `canvas_id` beside `cursor` fails as `conflicting_params`; without one, `canvas_id` is ignored and the page is served. A filter that matches nothing on a call that staged the list names the staged table.
|
|
12
|
+
- **Partial and stale catalogues are disclosed** ([#63](https://github.com/cyanheads/eurostat-mcp-server/issues/63)) — while the Comext dataflow list is unmerged, `eurostat_search_datasets` and `eurostat_browse_themes` (on `ext_go` and `icts`) carry `comextListMissing` and a `notice`, `no_match` hints name it, and `not_found` on a Comext folder or `DS-*` code says the list could not be loaded. A catalogue a failed TOC refresh could not replace carries `catalogueLoadedAt`, and a search `no_match` or browse `not_found` answered from it names that load time in its hint.
|
|
13
|
+
- **`eurostat_search_datasets` `no_match` names the blocking word** ([#69](https://github.com/cyanheads/eurostat-mcp-server/issues/69)) — for two or more distinct words, each word whose removal alone yields matches is listed with its count (`Without "rates": 7 matches.`), counted in one pass over the catalogue.
|
|
14
|
+
- **Upstream outages fail as retryable `upstream_fault`** ([#71](https://github.com/cyanheads/eurostat-mcp-server/issues/71)) — an HTTP 5xx or an unreachable host that outlasts the retries, on every tool that calls Eurostat, with an outage hint (HTTP 501 is not retryable); the `eurostat://dataset/{dataset_code}` resource fails with the same retryable `upstream_fault`, without a hint. `eurostat_download_dataset`, filtered or not, now retries its SDMX data request on an outage instead of failing on the first attempt, and `eurostat_search_datasets` and `eurostat_browse_themes` fail the same way when no catalogue has loaded yet.
|
|
15
|
+
|
|
16
|
+
## Changed
|
|
17
|
+
|
|
18
|
+
- **Breaking: `eurostat_query_dataset` rejects filter keys named like Eurostat API controls** (`lang`, `format`, `geoLevel`, `sinceTimePeriod`, `untilTimePeriod`, `lastTimePeriod`, any case) as `invalid_dimension` ([#62](https://github.com/cyanheads/eurostat-mcp-server/issues/62)). Some such calls used to return data; set the `lang`, `geo_level`, `since_period`, `until_period`, or `last_n_periods` input instead.
|
|
19
|
+
- **Breaking: `eurostat_get_dimension_values` no longer returns `shown` and `cap`** ([#64](https://github.com/cyanheads/eurostat-mcp-server/issues/64)). Long lists are paged within a 64,000-byte budget per response surface with `nextCursor`, instead of being cut at 2,000 values.
|
|
20
|
+
- **`eurostat_search_datasets` matches across spacing beside punctuation** ([#69](https://github.com/cyanheads/eurostat-mcp-server/issues/69)) — `Rev.2` finds `Rev. 2`, and `R&D`, `non-EU`, and `DS-045409` keep their punctuation. Search text is built once per catalogue snapshot.
|
|
21
|
+
- **Eurostat error labels in messages end in one period**, and server log lines no longer carry request URLs; fetches are labelled by endpoint.
|
|
22
|
+
- **`instructions`, tool descriptions, `README.md`, and `docs/design.md`** describe paging, outage and partial-catalogue behavior, and the new rejections.
|
|
23
|
+
- **`CLAUDE.md`/`AGENTS.md`** follow the 0.13.15 template, and the framework anti-pattern checks in `scripts/check-framework-antipatterns.ts` use POSIX character classes.
|
|
24
|
+
- **Framework** — `cyanheads/mcp-ts-core` ^0.13.11 → ^0.13.15: log records carry no request URLs, and `eurostat_dataframe_query` runs on a DuckDB canvas with external access off, with an SQL gate that refuses more functions and file references. Framework skills are synced to 0.13.15.
|
|
25
|
+
|
|
26
|
+
## Fixed
|
|
27
|
+
|
|
28
|
+
- **A blank or whitespace-only filter element is unset** ([#61](https://github.com/cyanheads/eurostat-mcp-server/issues/61)) — `[""]` accepts every value and `["", "DE"]` is `["DE"]` on `eurostat_query_dataset` and `eurostat_download_dataset`, in the request, the `geo`/`geo_level` check, `appliedFilters`/`appliedQuery`, and the too-large hint. A blank used to be sent upstream and echoed as applied.
|
|
29
|
+
- **A time filter beside a period input fails as `conflicting_params`** ([#70](https://github.com/cyanheads/eurostat-mcp-server/issues/70)) — `filters.time` or `filters.time_period` (any case) with `since_period`, `until_period`, or `last_n_periods` is refused before any request, and Eurostat's own "cannot be set at the same time" refusal is no longer reported as `invalid_period`.
|
|
30
|
+
- **Declared `canvas_not_found` and `missing_table` recoveries reach callers** ([#68](https://github.com/cyanheads/eurostat-mcp-server/issues/68)) on `eurostat_query_dataset`, `eurostat_download_dataset`, `eurostat_get_dimension_values`, `eurostat_dataframe_describe`, and `eurostat_dataframe_query`, in place of the canvas service's generic hints.
|
|
31
|
+
- **The canvas-off over-cap notice and truncation banner of `eurostat_query_dataset` name only filters and a period range** ([#65](https://github.com/cyanheads/eurostat-mcp-server/issues/65)); they used to route to `eurostat_download_dataset`, which keeps only its preview without a canvas.
|
|
32
|
+
|
|
33
|
+
## Dependencies
|
|
34
|
+
|
|
35
|
+
- `@cyanheads/mcp-ts-core` ^0.13.11 → ^0.13.15
|
|
36
|
+
- `pino-pretty` ^13.1.3 → ^13.2.0
|
|
37
|
+
- `zod` ^4.6.5 → ^4.6.6
|
|
38
|
+
- Dev: `@types/node` 26.6.3 → 26.6.5
|
|
39
|
+
- Dev: `ignore` ^7.0.11 → ^7.0.12
|
|
40
|
+
- Bun 1.4.2 → 1.4.3 (`packageManager`, Dockerfile)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
---
|
|
2
|
+
summary: "Opt-in eurostat_dataframe_drop removes one staged table from a canvas, the server moves to mcp-ts-core 0.13.11, and an unwritable CANVAS_TEMP_PATH now fails as a configuration error naming its errno."
|
|
3
|
+
breaking: false
|
|
4
|
+
security: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 0.9.0 — 2026-10-03
|
|
8
|
+
|
|
9
|
+
## Added
|
|
10
|
+
|
|
11
|
+
- **`eurostat_dataframe_drop`** removes one table from a dataframe canvas, leaving the canvas and its other tables in place, and returns `canvasId`, `tableName`, `dropped`, and `expiresAt`. `dropped: false`, with a `notice`, means nothing by that name was staged, so repeating a drop is safe.
|
|
12
|
+
- **`EUROSTAT_DATAFRAME_DROP_ENABLED`** (default `false`) gates it, since a drop cannot be undone: the tool is listed only with this set to `true` beside `CANVAS_PROVIDER_TYPE=duckdb`, and is otherwise registered disabled, shown on the landing page with the setting or settings that turn it on. A boot test pins that a `.env` file in the working directory sets the gate as the environment does.
|
|
13
|
+
- **The drop tool's errors carry its own recovery** ([#66](https://github.com/cyanheads/eurostat-mcp-server/issues/66)) — `canvas_not_found` and `identifier_reserved` reach the caller with the tool's declared recovery instead of the canvas service's hints, which are worded for staging (stage the data again, choose another table name), and `identifier_reserved` with the tool's own message.
|
|
14
|
+
|
|
15
|
+
## Changed
|
|
16
|
+
|
|
17
|
+
- **The server config is parsed in `setup()`**, so a bad `EUROSTAT_*` value fails startup with the framework's configuration banner naming the variable. The first tool call used to parse it, so the server reported ready and then failed every call.
|
|
18
|
+
- **Dockerfile installs in a `deps` stage** on `$BUILDPLATFORM`, cross-installing for the target with `--os`/`--cpu` through `bunfig.toml`'s release-age gate and scanner; `scripts/install-otel.ts` installs the OTel peers and `scripts/prune-musl-packages.ts` drops musl-only packages. `MCP_FORCE_CONSOLE_LOGGING`, which nothing read, is gone.
|
|
19
|
+
- **`server.json` npm entries launch the bin via `npx`** without the `run start:*` arguments, and the `streamable-http` entry fixes `MCP_TRANSPORT_TYPE` to `http`; the bin ignored those arguments, so the HTTP entry started on stdio.
|
|
20
|
+
- **Tool handlers no longer forward `ctx.recoveryFor`**, which the framework now fills (0.13.10); the recovery hints on the wire are unchanged.
|
|
21
|
+
- **Repo and packaging config** — `.gitignore` and `.dockerignore` cover every `.env*` file (the three templates stay tracked) and `.dockerignore` adds the MCP registry token files, CodeQL runs one job per language under `/language:<language>`, `.mcpbignore` excludes `docs/idea.md` and `logs/`, and `package.json` `files` excludes `dist/*.mcpb`.
|
|
22
|
+
- **Docs** — the README documents the drop tool and condenses the per-tool reference, `.env.example` documents `EUROSTAT_DATAFRAME_DROP_ENABLED`, `LOG_TOOL_FAILURE_PAYLOADS`, and the per-signal OTLP endpoints, `CANVAS_TEMP_PATH` is described as a parent directory throughout, and `CLAUDE.md`/`AGENTS.md` follow the 0.13.11 template.
|
|
23
|
+
- **Framework skills and scripts resynced** from mcp-ts-core 0.13.11, adding `scripts/install-otel.ts` and `scripts/prune-musl-packages.ts` and removing the one-shot `scripts/split-changelog.ts`; `lint:packaging` gains the `.mcpb` exclusion, manifest version, Dockerfile build platform, and npm launch shape checks.
|
|
24
|
+
- **mcp-ts-core 0.13.7** — server stack traces (`originalStack`, `causeChain`) no longer reach clients through error `data`. With `OTEL_ENABLED=true`, `OTEL_EXPORTER_OTLP_ENDPOINT` alone exports traces and metrics to `<base>/v1/traces` and `<base>/v1/metrics`, and with no endpoint set nothing is exported (it used to send to `localhost:4318`).
|
|
25
|
+
- **mcp-ts-core 0.13.8** — request context (tenant, operation, `extra` fields) no longer reaches client error `data`, and a tool result that breaks its own output schema fails as `-32603` (was `-32007`). Opt-in OTLP log export (`OTEL_EXPORTER_OTLP_LOGS_ENDPOINT`) and failed-call payload logging (`LOG_TOOL_FAILURE_PAYLOADS`, `LOG_TOOL_FAILURE_PAYLOAD_MAX_BYTES`).
|
|
26
|
+
- **mcp-ts-core 0.13.9** — a JSON-stringified object sent for an object field, or an integer sent for a string field, is repaired before validation, and argument rejections name alias rewrites and dropped keys. Canvas scratch files live in a private directory inside `CANVAS_TEMP_PATH`. MCP SDK 2.1.0 refuses a JSON-RPC batch over 100 messages, and stdin EOF on stdio aborts in-flight requests.
|
|
27
|
+
- **mcp-ts-core 0.13.10** — a declared `recovery` hint reaches the wire on any typed error that carries none of its own, service throws included. Error results carry `data.requestId`, and their `content[]` closes with `request <id>`. `invalid_arguments` refusals log at `notice`. The multi-arch Docker build installs dependencies on the build platform, so Bun no longer runs under QEMU.
|
|
28
|
+
- **mcp-ts-core 0.13.11** — `ctx.log` messages mirrored to the client honor `MCP_LOG_LEVEL` and mask sensitive fields, the log level filter compares RFC 5424 severity, and resource-read logs cap the URI at 1,024 characters. The Docker image drops musl-only bindings, `lint:packaging` enforces the `server.json` npm launch shape above, and `@modelcontextprotocol/server` moves to 2.2.0.
|
|
29
|
+
|
|
30
|
+
## Fixed
|
|
31
|
+
|
|
32
|
+
- **An unwritable `CANVAS_TEMP_PATH` fails as `-32008` `ConfigurationError`** (was `-32000` `ServiceUnavailable`), naming its errno in the message and in `data.errno` beside `data.reason: "canvas_unavailable"`. Since mcp-ts-core 0.13.9 the provider fails with that code itself; the server keeps it and adds the errno and the `CANVAS_PROVIDER_TYPE=none` way out, which the framework's message omits.
|
|
33
|
+
- **A cancelled `eurostat_query_dataset` or `eurostat_download_dataset` call stays a cancellation** when it reaches the too-large refusal's dimension lookup, which rethrows the abort instead of swallowing it into a generic narrowing hint.
|
|
34
|
+
|
|
35
|
+
## Dependencies
|
|
36
|
+
|
|
37
|
+
- `@cyanheads/mcp-ts-core` ^0.13.6 → ^0.13.11 (`@modelcontextprotocol/server` 2.0.0 → 2.2.0 transitively).
|
|
38
|
+
- `@duckdb/node-api` ^1.5.5-r.5 → ^1.5.6-r.1.
|
|
39
|
+
- Dev: `@biomejs/biome` 2.5.14 → 2.5.15.
|
|
40
|
+
- Dev: `@types/node` 26.6.2 → 26.6.3.
|
|
41
|
+
- Dev: `ignore` ^7.0.9 → ^7.0.11.
|
|
42
|
+
- Dev: `tsc-alias` ^1.9.5 → ^1.9.7.
|
|
43
|
+
- Dev: `vitest` ^5.0.1 → ^5.0.3.
|
|
@@ -11,6 +11,7 @@ declare const ServerConfigSchema: z.ZodObject<{
|
|
|
11
11
|
tocCacheTtlMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
12
12
|
bulkTimeoutMs: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
13
13
|
bulkMaxBytes: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
14
|
+
dataframeDropEnabled: z.ZodDefault<z.ZodCodec<z.ZodString, z.ZodBoolean>>;
|
|
14
15
|
}, z.core.$strip>;
|
|
15
16
|
export declare function getServerConfig(): z.infer<typeof ServerConfigSchema>;
|
|
16
17
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-config.d.ts","sourceRoot":"","sources":["../../src/config/server-config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAG3C,QAAA,MAAM,kBAAkB
|
|
1
|
+
{"version":3,"file":"server-config.d.ts","sourceRoot":"","sources":["../../src/config/server-config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAG3C,QAAA,MAAM,kBAAkB;;;;;;;;;iBAyDtB,CAAC;AAIH,wBAAgB,eAAe,IAAI,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAYpE"}
|
|
@@ -45,6 +45,10 @@ const ServerConfigSchema = z.object({
|
|
|
45
45
|
.positive()
|
|
46
46
|
.default(52_428_800)
|
|
47
47
|
.describe('Byte budget for one SDMX bulk download, measured 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 the moment it is reached. Defaults to 50 MiB.'),
|
|
48
|
+
dataframeDropEnabled: z
|
|
49
|
+
.stringbool()
|
|
50
|
+
.default(false)
|
|
51
|
+
.describe('Register eurostat_dataframe_drop, which removes one staged table from a dataframe canvas. Off by default: a drop cannot be undone, and staged tables already expire with their canvas. Takes effect only with CANVAS_PROVIDER_TYPE=duckdb.'),
|
|
48
52
|
});
|
|
49
53
|
let _config;
|
|
50
54
|
export function getServerConfig() {
|
|
@@ -56,6 +60,7 @@ export function getServerConfig() {
|
|
|
56
60
|
tocCacheTtlMs: 'EUROSTAT_TOC_CACHE_TTL_MS',
|
|
57
61
|
bulkTimeoutMs: 'EUROSTAT_BULK_TIMEOUT_MS',
|
|
58
62
|
bulkMaxBytes: 'EUROSTAT_BULK_MAX_BYTES',
|
|
63
|
+
dataframeDropEnabled: 'EUROSTAT_DATAFRAME_DROP_ENABLED',
|
|
59
64
|
});
|
|
60
65
|
return _config;
|
|
61
66
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-config.js","sourceRoot":"","sources":["../../src/config/server-config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAE/D,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IAClC,OAAO,EAAE,CAAC;SACP,MAAM,EAAE;SACR,GAAG,EAAE;SACL,OAAO,CAAC,iDAAiD,CAAC;SAC1D,QAAQ,CAAC,uBAAuB,CAAC;IACpC,aAAa,EAAE,CAAC;SACb,MAAM,EAAE;SACR,GAAG,EAAE;SACL,OAAO,CAAC,wDAAwD,CAAC;SACjE,QAAQ,CACP,mMAAmM,CACpM;IACH,gBAAgB,EAAE,CAAC,CAAC,MAAM;SACvB,MAAM,EAAE;SACR,GAAG,EAAE;SACL,QAAQ,EAAE;SACV,OAAO,CAAC,MAAM,CAAC;SACf,QAAQ,CAAC,sCAAsC,CAAC;IACnD,iBAAiB,EAAE,CAAC,CAAC,MAAM;SACxB,MAAM,EAAE;SACR,GAAG,EAAE;SACL,QAAQ,EAAE;SACV,OAAO,CAAC,OAAO,CAAC;SAChB,QAAQ,CACP,oRAAoR,CACrR;IACH,aAAa,EAAE,CAAC,CAAC,MAAM;SACpB,MAAM,EAAE;SACR,GAAG,EAAE;SACL,QAAQ,EAAE;SACV,OAAO,CAAC,UAAU,CAAC;SACnB,QAAQ,CACP,qLAAqL,CACtL;IACH,aAAa,EAAE,CAAC,CAAC,MAAM;SACpB,MAAM,EAAE;SACR,GAAG,EAAE;SACL,QAAQ,EAAE;SACV,OAAO,CAAC,OAAO,CAAC;SAChB,QAAQ,CACP,mNAAmN,CACpN;IACH,YAAY,EAAE,CAAC,CAAC,MAAM;SACnB,MAAM,EAAE;SACR,GAAG,EAAE;SACL,QAAQ,EAAE;SACV,OAAO,CAAC,UAAU,CAAC;SACnB,QAAQ,CACP,0QAA0Q,CAC3Q;CACJ,CAAC,CAAC;AAEH,IAAI,OAAuD,CAAC;AAE5D,MAAM,UAAU,eAAe;IAC7B,OAAO,KAAK,cAAc,CAAC,kBAAkB,EAAE;QAC7C,OAAO,EAAE,mBAAmB;QAC5B,aAAa,EAAE,0BAA0B;QACzC,gBAAgB,EAAE,6BAA6B;QAC/C,iBAAiB,EAAE,8BAA8B;QACjD,aAAa,EAAE,2BAA2B;QAC1C,aAAa,EAAE,0BAA0B;QACzC,YAAY,EAAE,yBAAyB;
|
|
1
|
+
{"version":3,"file":"server-config.js","sourceRoot":"","sources":["../../src/config/server-config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAE/D,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IAClC,OAAO,EAAE,CAAC;SACP,MAAM,EAAE;SACR,GAAG,EAAE;SACL,OAAO,CAAC,iDAAiD,CAAC;SAC1D,QAAQ,CAAC,uBAAuB,CAAC;IACpC,aAAa,EAAE,CAAC;SACb,MAAM,EAAE;SACR,GAAG,EAAE;SACL,OAAO,CAAC,wDAAwD,CAAC;SACjE,QAAQ,CACP,mMAAmM,CACpM;IACH,gBAAgB,EAAE,CAAC,CAAC,MAAM;SACvB,MAAM,EAAE;SACR,GAAG,EAAE;SACL,QAAQ,EAAE;SACV,OAAO,CAAC,MAAM,CAAC;SACf,QAAQ,CAAC,sCAAsC,CAAC;IACnD,iBAAiB,EAAE,CAAC,CAAC,MAAM;SACxB,MAAM,EAAE;SACR,GAAG,EAAE;SACL,QAAQ,EAAE;SACV,OAAO,CAAC,OAAO,CAAC;SAChB,QAAQ,CACP,oRAAoR,CACrR;IACH,aAAa,EAAE,CAAC,CAAC,MAAM;SACpB,MAAM,EAAE;SACR,GAAG,EAAE;SACL,QAAQ,EAAE;SACV,OAAO,CAAC,UAAU,CAAC;SACnB,QAAQ,CACP,qLAAqL,CACtL;IACH,aAAa,EAAE,CAAC,CAAC,MAAM;SACpB,MAAM,EAAE;SACR,GAAG,EAAE;SACL,QAAQ,EAAE;SACV,OAAO,CAAC,OAAO,CAAC;SAChB,QAAQ,CACP,mNAAmN,CACpN;IACH,YAAY,EAAE,CAAC,CAAC,MAAM;SACnB,MAAM,EAAE;SACR,GAAG,EAAE;SACL,QAAQ,EAAE;SACV,OAAO,CAAC,UAAU,CAAC;SACnB,QAAQ,CACP,0QAA0Q,CAC3Q;IACH,oBAAoB,EAAE,CAAC;SACpB,UAAU,EAAE;SACZ,OAAO,CAAC,KAAK,CAAC;SACd,QAAQ,CACP,4OAA4O,CAC7O;CACJ,CAAC,CAAC;AAEH,IAAI,OAAuD,CAAC;AAE5D,MAAM,UAAU,eAAe;IAC7B,OAAO,KAAK,cAAc,CAAC,kBAAkB,EAAE;QAC7C,OAAO,EAAE,mBAAmB;QAC5B,aAAa,EAAE,0BAA0B;QACzC,gBAAgB,EAAE,6BAA6B;QAC/C,iBAAiB,EAAE,8BAA8B;QACjD,aAAa,EAAE,2BAA2B;QAC1C,aAAa,EAAE,0BAA0B;QACzC,YAAY,EAAE,yBAAyB;QACvC,oBAAoB,EAAE,iCAAiC;KACxD,CAAC,CAAC;IACH,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -5,9 +5,11 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { createApp, disabledTool } from '@cyanheads/mcp-ts-core';
|
|
7
7
|
import { config } from '@cyanheads/mcp-ts-core/config';
|
|
8
|
+
import { getServerConfig } from './config/server-config.js';
|
|
8
9
|
import { eurostatDatasetResource } from './mcp-server/resources/definitions/eurostat-dataset.resource.js';
|
|
9
10
|
import { eurostatBrowseThemes } from './mcp-server/tools/definitions/eurostat-browse-themes.tool.js';
|
|
10
11
|
import { eurostatDataframeDescribe } from './mcp-server/tools/definitions/eurostat-dataframe-describe.tool.js';
|
|
12
|
+
import { eurostatDataframeDrop } from './mcp-server/tools/definitions/eurostat-dataframe-drop.tool.js';
|
|
11
13
|
import { eurostatDataframeQuery } from './mcp-server/tools/definitions/eurostat-dataframe-query.tool.js';
|
|
12
14
|
import { eurostatDownloadDataset } from './mcp-server/tools/definitions/eurostat-download-dataset.tool.js';
|
|
13
15
|
import { eurostatGetDatasetInfo } from './mcp-server/tools/definitions/eurostat-get-dataset-info.tool.js';
|
|
@@ -20,17 +22,51 @@ import { initEurostatCatalogueService } from './services/eurostat-catalogue/euro
|
|
|
20
22
|
import { initEurostatDataService } from './services/eurostat-data/eurostat-data-service.js';
|
|
21
23
|
/**
|
|
22
24
|
* The dataframe tools address tables on a canvas, so without one they have
|
|
23
|
-
* nothing to talk to. `disabledTool` keeps
|
|
24
|
-
* cannot call
|
|
25
|
-
*
|
|
25
|
+
* nothing to talk to. `disabledTool` keeps a gated tool off `tools/list` —
|
|
26
|
+
* clients cannot call it — while the landing page still renders it with the
|
|
27
|
+
* reason it is off and the setting that turns it on, so an operator can see the
|
|
26
28
|
* capability exists rather than wondering why the README documents a tool the
|
|
27
|
-
* server does not advertise.
|
|
29
|
+
* server does not advertise. The drop tool carries a second gate: a drop cannot
|
|
30
|
+
* be undone, so it stays off until EUROSTAT_DATAFRAME_DROP_ENABLED opts in, and
|
|
31
|
+
* its hint names every setting still missing.
|
|
28
32
|
*/
|
|
29
33
|
const canvasEnabled = config.canvas.providerType !== 'none';
|
|
30
34
|
const CANVAS_OFF = {
|
|
31
35
|
reason: 'This deployment runs without a dataframe canvas, so there are no tables to address.',
|
|
32
36
|
hint: 'CANVAS_PROVIDER_TYPE=duckdb',
|
|
33
37
|
};
|
|
38
|
+
const DROP_OFF_HINT = 'EUROSTAT_DATAFRAME_DROP_ENABLED=true';
|
|
39
|
+
/**
|
|
40
|
+
* Read before `createApp()` because the drop tool's registration depends on it.
|
|
41
|
+
* A value that fails to parse is not reported here: `setup()` reads the server
|
|
42
|
+
* config again inside `createApp()`, which prints the configuration banner and
|
|
43
|
+
* exits 1 — thrown at this point, the same error would escape as an uncaught
|
|
44
|
+
* stack trace.
|
|
45
|
+
*/
|
|
46
|
+
function dataframeDropEnabled() {
|
|
47
|
+
try {
|
|
48
|
+
return getServerConfig().dataframeDropEnabled;
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/** The drop tool, or its disabled card naming every setting it still needs. */
|
|
55
|
+
function dataframeDropTool() {
|
|
56
|
+
const dropEnabled = dataframeDropEnabled();
|
|
57
|
+
if (!canvasEnabled) {
|
|
58
|
+
return disabledTool(eurostatDataframeDrop, {
|
|
59
|
+
reason: CANVAS_OFF.reason,
|
|
60
|
+
hint: dropEnabled ? CANVAS_OFF.hint : `${CANVAS_OFF.hint}\n${DROP_OFF_HINT}`,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
return dropEnabled
|
|
64
|
+
? eurostatDataframeDrop
|
|
65
|
+
: disabledTool(eurostatDataframeDrop, {
|
|
66
|
+
reason: 'Table cleanup is disabled in this deployment, so a staged table leaves only when its canvas expires.',
|
|
67
|
+
hint: DROP_OFF_HINT,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
34
70
|
await createApp({
|
|
35
71
|
name: 'eurostat-mcp-server',
|
|
36
72
|
title: 'eurostat-mcp-server',
|
|
@@ -49,17 +85,21 @@ await createApp({
|
|
|
49
85
|
eurostatDownloadDataset,
|
|
50
86
|
canvasEnabled ? eurostatDataframeDescribe : disabledTool(eurostatDataframeDescribe, CANVAS_OFF),
|
|
51
87
|
canvasEnabled ? eurostatDataframeQuery : disabledTool(eurostatDataframeQuery, CANVAS_OFF),
|
|
88
|
+
dataframeDropTool(),
|
|
52
89
|
],
|
|
53
90
|
resources: [eurostatDatasetResource],
|
|
54
91
|
prompts: [],
|
|
55
92
|
instructions: `Eurostat MCP server — EU statistical data across the Eurostat catalogue.
|
|
56
93
|
Workflow: eurostat_search_datasets or eurostat_browse_themes to find a dataset code → eurostat_get_dataset_info to see dimensions → eurostat_get_dimension_values to list valid filter values → eurostat_query_dataset to fetch observations.
|
|
57
94
|
Apply dimension filters to keep queries small: an unfiltered query on a large dataset is slow and can return an async response error instead of data.
|
|
58
|
-
The catalogue covers two hosts. Most datasets come from the Eurostat dissemination table of contents; the DS-* codes — detailed trade by CN8, HS, SITC, BEC and CPA, and PRODCOM — come from the Comext host, and every tool routes a DS-* code there by its prefix. Comext collections are large: filter every request (freq included, since the trade flows mix annual and monthly series), and expect eurostat_get_dimension_values to
|
|
95
|
+
The catalogue covers two hosts. Most datasets come from the Eurostat dissemination table of contents; the DS-* codes — detailed trade by CN8, HS, SITC, BEC and CPA, and PRODCOM — come from the Comext host, and every tool routes a DS-* code there by its prefix. Comext collections are large: filter every request (freq included, since the trade flows mix annual and monthly series), and expect eurostat_get_dimension_values to page a long list such as the 37,069 CN8 product codes — pass filter with words of the code or label to find one value, or follow nextCursor. A collection on neither host, such as the legacy DS-056120, is not disseminated.
|
|
59
96
|
Two paths past eurostat_query_dataset's 5,000-observation inline cap. For a slice of a dataset, keep using eurostat_query_dataset: when the match is larger than the cap and this deployment runs a dataframe canvas, the whole match is also staged as a SQL table named in the response. For a whole dataset, use eurostat_download_dataset, which reads the SDMX bulk endpoint instead — about half the bytes — and stages every observation the same way, bounded by a byte budget it reports back. Read either staged table with eurostat_dataframe_query (eurostat_dataframe_describe lists the table and column names); the two stage different column sets, since the bulk endpoint carries dimension codes with no labels. To label a download's codes, pass its canvasId to eurostat_get_dimension_values as canvas_id: the dimension's values are staged beside it as a code/label table to join on.
|
|
97
|
+
Staged tables expire with their canvas. eurostat_dataframe_drop removes one sooner, leaving the canvas and its other tables in place; it is opt-in, listed only where the deployment also sets EUROSTAT_DATAFRAME_DROP_ENABLED=true.
|
|
60
98
|
The dataframe tools are not listed when the canvas is off. There, narrowing the filters is what brings a capped match into reach, and eurostat_download_dataset retains only its inline preview.`,
|
|
61
99
|
landing: { requireAuth: false },
|
|
62
100
|
setup(core) {
|
|
101
|
+
// Parsed here so a bad value fails startup with the configuration banner, not every call.
|
|
102
|
+
getServerConfig();
|
|
63
103
|
initEurostatCatalogueService(core.config, core.storage);
|
|
64
104
|
initEurostatDataService(core.config, core.storage);
|
|
65
105
|
initEurostatBulkService(core.config, core.storage);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AACvD,OAAO,EAAE,uBAAuB,EAAE,MAAM,iEAAiE,CAAC;AAC1G,OAAO,EAAE,oBAAoB,EAAE,MAAM,+DAA+D,CAAC;AACrG,OAAO,EAAE,yBAAyB,EAAE,MAAM,oEAAoE,CAAC;AAC/G,OAAO,EAAE,sBAAsB,EAAE,MAAM,iEAAiE,CAAC;AACzG,OAAO,EAAE,uBAAuB,EAAE,MAAM,kEAAkE,CAAC;AAC3G,OAAO,EAAE,sBAAsB,EAAE,MAAM,kEAAkE,CAAC;AAC1G,OAAO,EAAE,0BAA0B,EAAE,MAAM,sEAAsE,CAAC;AAClH,OAAO,EAAE,oBAAoB,EAAE,MAAM,+DAA+D,CAAC;AACrG,OAAO,EAAE,sBAAsB,EAAE,MAAM,iEAAiE,CAAC;AACzG,OAAO,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAC1D,OAAO,EAAE,uBAAuB,EAAE,MAAM,mDAAmD,CAAC;AAC5F,OAAO,EAAE,4BAA4B,EAAE,MAAM,6DAA6D,CAAC;AAC3G,OAAO,EAAE,uBAAuB,EAAE,MAAM,mDAAmD,CAAC;AAE5F
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,uBAAuB,EAAE,MAAM,iEAAiE,CAAC;AAC1G,OAAO,EAAE,oBAAoB,EAAE,MAAM,+DAA+D,CAAC;AACrG,OAAO,EAAE,yBAAyB,EAAE,MAAM,oEAAoE,CAAC;AAC/G,OAAO,EAAE,qBAAqB,EAAE,MAAM,gEAAgE,CAAC;AACvG,OAAO,EAAE,sBAAsB,EAAE,MAAM,iEAAiE,CAAC;AACzG,OAAO,EAAE,uBAAuB,EAAE,MAAM,kEAAkE,CAAC;AAC3G,OAAO,EAAE,sBAAsB,EAAE,MAAM,kEAAkE,CAAC;AAC1G,OAAO,EAAE,0BAA0B,EAAE,MAAM,sEAAsE,CAAC;AAClH,OAAO,EAAE,oBAAoB,EAAE,MAAM,+DAA+D,CAAC;AACrG,OAAO,EAAE,sBAAsB,EAAE,MAAM,iEAAiE,CAAC;AACzG,OAAO,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAC1D,OAAO,EAAE,uBAAuB,EAAE,MAAM,mDAAmD,CAAC;AAC5F,OAAO,EAAE,4BAA4B,EAAE,MAAM,6DAA6D,CAAC;AAC3G,OAAO,EAAE,uBAAuB,EAAE,MAAM,mDAAmD,CAAC;AAE5F;;;;;;;;;GASG;AACH,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC,YAAY,KAAK,MAAM,CAAC;AAC5D,MAAM,UAAU,GAAG;IACjB,MAAM,EAAE,qFAAqF;IAC7F,IAAI,EAAE,6BAA6B;CAC3B,CAAC;AACX,MAAM,aAAa,GAAG,sCAAsC,CAAC;AAE7D;;;;;;GAMG;AACH,SAAS,oBAAoB;IAC3B,IAAI,CAAC;QACH,OAAO,eAAe,EAAE,CAAC,oBAAoB,CAAC;IAChD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,+EAA+E;AAC/E,SAAS,iBAAiB;IACxB,MAAM,WAAW,GAAG,oBAAoB,EAAE,CAAC;IAC3C,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,OAAO,YAAY,CAAC,qBAAqB,EAAE;YACzC,MAAM,EAAE,UAAU,CAAC,MAAM;YACzB,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,IAAI,KAAK,aAAa,EAAE;SAC7E,CAAC,CAAC;IACL,CAAC;IACD,OAAO,WAAW;QAChB,CAAC,CAAC,qBAAqB;QACvB,CAAC,CAAC,YAAY,CAAC,qBAAqB,EAAE;YAClC,MAAM,EACJ,sGAAsG;YACxG,IAAI,EAAE,aAAa;SACpB,CAAC,CAAC;AACT,CAAC;AAED,MAAM,SAAS,CAAC;IACd,IAAI,EAAE,qBAAqB;IAC3B,KAAK,EAAE,qBAAqB;IAC5B;;;;OAIG;IACH,WAAW,EAAE,WAAW;IACxB,KAAK,EAAE;QACL,sBAAsB;QACtB,oBAAoB;QACpB,sBAAsB;QACtB,0BAA0B;QAC1B,oBAAoB;QACpB,uBAAuB;QACvB,aAAa,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAC,YAAY,CAAC,yBAAyB,EAAE,UAAU,CAAC;QAC/F,aAAa,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,YAAY,CAAC,sBAAsB,EAAE,UAAU,CAAC;QACzF,iBAAiB,EAAE;KACpB;IACD,SAAS,EAAE,CAAC,uBAAuB,CAAC;IACpC,OAAO,EAAE,EAAE;IACX,YAAY,EAAE;;;;;;iMAMiL;IAC/L,OAAO,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE;IAC/B,KAAK,CAAC,IAAI;QACR,0FAA0F;QAC1F,eAAe,EAAE,CAAC;QAClB,4BAA4B,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QACxD,uBAAuB,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QACnD,uBAAuB,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QACnD,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACzB,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -26,15 +26,23 @@ export declare const eurostatBrowseThemes: import("@cyanheads/mcp-ts-core").Tool
|
|
|
26
26
|
}, z.core.$strip>, readonly [{
|
|
27
27
|
readonly reason: "not_found";
|
|
28
28
|
readonly code: JsonRpcErrorCode.NotFound;
|
|
29
|
-
readonly when: "The provided theme_code does not exist in the TOC.";
|
|
30
|
-
readonly recovery: "Call eurostat_browse_themes without theme_code to see valid root themes, then navigate from there.";
|
|
29
|
+
readonly when: "The provided theme_code does not exist in the TOC — or is a Comext folder (ext_go_detail, prom, comext) or DS-* code while the Comext dataflow list cannot be loaded.";
|
|
30
|
+
readonly recovery: "Call eurostat_browse_themes without theme_code to see valid root themes, then navigate from there. A Comext folder missing because its list could not be loaded returns once the merge is retried, about once a minute; eurostat_get_dataset_info reads a DS-* code directly.";
|
|
31
31
|
}, {
|
|
32
32
|
readonly reason: "not_a_folder";
|
|
33
33
|
readonly code: JsonRpcErrorCode.ValidationError;
|
|
34
34
|
readonly when: "The provided theme_code identifies a dataset or table entry instead of a folder.";
|
|
35
35
|
readonly recovery: "Pass the code to eurostat_get_dataset_info to inspect it, then eurostat_query_dataset to retrieve data.";
|
|
36
|
+
}, {
|
|
37
|
+
readonly reason: "upstream_fault";
|
|
38
|
+
readonly code: JsonRpcErrorCode.ServiceUnavailable;
|
|
39
|
+
readonly when: "The server had no catalogue loaded yet, and Eurostat's table of contents answered HTTP 5xx or could not be reached on every retry, which the error marks retryable. Once a catalogue is loaded, a failed refresh serves that copy instead.";
|
|
40
|
+
readonly recovery: "Retry in a few minutes: the catalogue load failed on Eurostat's side and runs again on the next call.";
|
|
36
41
|
}], {
|
|
37
42
|
readonly itemCount: z.ZodNumber;
|
|
38
43
|
readonly themeCode: z.ZodOptional<z.ZodString>;
|
|
44
|
+
readonly comextListMissing: z.ZodOptional<z.ZodBoolean>;
|
|
45
|
+
readonly catalogueLoadedAt: z.ZodOptional<z.ZodString>;
|
|
46
|
+
readonly notice: z.ZodOptional<z.ZodString>;
|
|
39
47
|
}>;
|
|
40
48
|
//# sourceMappingURL=eurostat-browse-themes.tool.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eurostat-browse-themes.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/eurostat-browse-themes.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAiB,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"eurostat-browse-themes.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/eurostat-browse-themes.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAiB,MAAM,+BAA+B,CAAC;AAIhF,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiO/B,CAAC"}
|