@cyanheads/eurostat-mcp-server 0.3.0 → 0.4.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.
Files changed (31) hide show
  1. package/CLAUDE.md +1 -1
  2. package/Dockerfile +16 -3
  3. package/README.md +27 -6
  4. package/dist/index.js +23 -2
  5. package/dist/index.js.map +1 -1
  6. package/dist/mcp-server/tools/definitions/eurostat-dataframe-describe.tool.d.ts +40 -0
  7. package/dist/mcp-server/tools/definitions/eurostat-dataframe-describe.tool.d.ts.map +1 -0
  8. package/dist/mcp-server/tools/definitions/eurostat-dataframe-describe.tool.js +113 -0
  9. package/dist/mcp-server/tools/definitions/eurostat-dataframe-describe.tool.js.map +1 -0
  10. package/dist/mcp-server/tools/definitions/eurostat-dataframe-query.tool.d.ts +34 -0
  11. package/dist/mcp-server/tools/definitions/eurostat-dataframe-query.tool.d.ts.map +1 -0
  12. package/dist/mcp-server/tools/definitions/eurostat-dataframe-query.tool.js +98 -0
  13. package/dist/mcp-server/tools/definitions/eurostat-dataframe-query.tool.js.map +1 -0
  14. package/dist/mcp-server/tools/definitions/eurostat-query-dataset.tool.d.ts +9 -0
  15. package/dist/mcp-server/tools/definitions/eurostat-query-dataset.tool.d.ts.map +1 -1
  16. package/dist/mcp-server/tools/definitions/eurostat-query-dataset.tool.js +72 -10
  17. package/dist/mcp-server/tools/definitions/eurostat-query-dataset.tool.js.map +1 -1
  18. package/dist/services/canvas-accessor.d.ts +26 -0
  19. package/dist/services/canvas-accessor.d.ts.map +1 -0
  20. package/dist/services/canvas-accessor.js +57 -0
  21. package/dist/services/canvas-accessor.js.map +1 -0
  22. package/dist/services/eurostat-data/eurostat-data-service.d.ts +53 -8
  23. package/dist/services/eurostat-data/eurostat-data-service.d.ts.map +1 -1
  24. package/dist/services/eurostat-data/eurostat-data-service.js +90 -13
  25. package/dist/services/eurostat-data/eurostat-data-service.js.map +1 -1
  26. package/dist/services/eurostat-data/types.d.ts +30 -0
  27. package/dist/services/eurostat-data/types.d.ts.map +1 -1
  28. package/dist/services/eurostat-data/types.js +4 -0
  29. package/dist/services/eurostat-data/types.js.map +1 -1
  30. package/package.json +2 -1
  31. package/server.json +58 -4
@@ -4,11 +4,16 @@
4
4
  */
5
5
  import { tool, z } from '@cyanheads/mcp-ts-core';
6
6
  import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
7
- import { getEurostatDataService } from '../../../services/eurostat-data/eurostat-data-service.js';
7
+ import { acquireCanvas, getCanvas } from '../../../services/canvas-accessor.js';
8
+ import { getEurostatDataService, observationRowSchema, } from '../../../services/eurostat-data/eurostat-data-service.js';
8
9
  import { GEO_LEVEL_VALUES, OBS_CAP } from '../../../services/eurostat-data/types.js';
10
+ /** Fresh handle for one staged result set. Distinct per call — each is its own match. */
11
+ function newTableName() {
12
+ return `df_${globalThis.crypto.randomUUID().slice(0, 8)}`;
13
+ }
9
14
  export const eurostatQueryDataset = tool('eurostat_query_dataset', {
10
15
  title: 'Query Eurostat Dataset',
11
- description: 'Fetch statistical data from a Eurostat dataset with dimension filters. Returns decoded observations with dimension codes and labels, numeric values, and status flags (e.g., "p" = provisional, "e" = estimated). Call eurostat_get_dataset_info first to discover valid dimension codes and values. Apply filters to keep the result set manageable — large unfiltered queries may trigger an async response error. Use filters.geo for specific country/region codes, or geo_level for NUTS hierarchy filtering (mutually exclusive). Use last_n_periods for the N most recent periods without knowing the end date.',
16
+ description: 'Fetch statistical data from a Eurostat dataset with dimension filters. Returns decoded observations with dimension codes and labels, numeric values, and status flags (e.g., "p" = provisional, "e" = estimated), capped at 5,000 inline rows. Call eurostat_get_dataset_info first to discover valid dimension codes and values. Apply filters to keep the result set manageable — large unfiltered queries may trigger an async response error. Use filters.geo for specific country/region codes, or geo_level for NUTS hierarchy filtering (mutually exclusive). Use last_n_periods for the N most recent periods without knowing the end date. When the match exceeds the inline cap on a deployment that runs a dataframe canvas, the whole match is also staged as a SQL table and the response names it in tableName — read the rest with eurostat_dataframe_query rather than re-querying Eurostat.',
12
17
  annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: true },
13
18
  input: z.object({
14
19
  dataset_code: z.string().min(1).describe('Dataset code (e.g., "nama_10_gdp"). Required.'),
@@ -38,6 +43,10 @@ export const eurostatQueryDataset = tool('eurostat_query_dataset', {
38
43
  .enum(['EN', 'FR', 'DE'])
39
44
  .default('EN')
40
45
  .describe('Language for labels in the response. Default is "EN". Options: "EN", "FR", "DE".'),
46
+ canvas_id: z
47
+ .string()
48
+ .optional()
49
+ .describe('Reuse an existing dataframe canvas, so a result staged by this call lands beside earlier ones and can be joined against them. Pass a canvasId from a previous response; omit to start a fresh canvas. Ignored on deployments without a dataframe canvas, and when the result fits inline and nothing is staged.'),
41
50
  }),
42
51
  output: z.object({
43
52
  datasetCode: z.string().describe('Dataset code as provided.'),
@@ -70,11 +79,23 @@ export const eurostatQueryDataset = tool('eurostat_query_dataset', {
70
79
  .describe('Status flag for this observation. Omitted for normal observations.'),
71
80
  })
72
81
  .describe('A single decoded observation with dimension values, numeric value, and optional status.'))
73
- .describe('Decoded observations, capped at 5,000 rows. Past the cap these are the first 5,000 the response enumerates — the leading combinations of the dataset dimensions, neither a sample nor the most recent periods — so narrow the query with dimension filters or a period range to choose which observations you get.'),
82
+ .describe('Decoded observations, capped at 5,000 rows. Past the cap these are the first 5,000 the response enumerates — the leading combinations of the dataset dimensions, neither a sample nor the most recent periods. When tableName is set, these same rows and every row past the cap are staged on the dataframe canvas; when it is absent, narrow the query with dimension filters or a period range to choose which observations you get.'),
74
83
  obsCount: z.number().describe('Total number of observations matched (before any cap).'),
75
84
  truncated: z
76
85
  .boolean()
77
- .describe('True when the result exceeded 5,000 observations and was capped. Apply dimension filters to get the full result.'),
86
+ .describe('True when the result exceeded 5,000 observations, so the returned rows are a prefix of the match rather than all of it. When tableName is set, the whole match is on the canvas and reachable with eurostat_dataframe_query; when it is absent, narrowing the query with dimension filters is what brings the rest into reach.'),
87
+ canvasId: z
88
+ .string()
89
+ .optional()
90
+ .describe('Dataframe canvas holding the staged result. Pass to eurostat_dataframe_describe, eurostat_dataframe_query, or a later eurostat_query_dataset call. Omitted when nothing was staged.'),
91
+ tableName: z
92
+ .string()
93
+ .optional()
94
+ .describe('Canvas table holding every matched observation in flat form — one code column per dimension plus a "_label" companion, then obs_value, obs_flag, obs_flag_label. Omitted when nothing was staged: either the result fit under the cap, or this deployment runs without a dataframe canvas.'),
95
+ stagedRowCount: z
96
+ .number()
97
+ .optional()
98
+ .describe('Rows written to the canvas table. Matches obsCount. Omitted alongside tableName when nothing was staged.'),
78
99
  timeRange: z
79
100
  .object({
80
101
  start: z
@@ -106,7 +127,7 @@ export const eurostatQueryDataset = tool('eurostat_query_dataset', {
106
127
  notice: z
107
128
  .string()
108
129
  .optional()
109
- .describe('Guidance when the result was truncated at 5,000 rows. Omitted for normal results.'),
130
+ .describe('Guidance when the result was capped at 5,000 rows — where the rest of the match is, or how to narrow the query. Omitted for uncapped results.'),
110
131
  },
111
132
  enrichmentTrailer: {
112
133
  appliedFilters: {
@@ -161,6 +182,12 @@ export const eurostatQueryDataset = tool('eurostat_query_dataset', {
161
182
  when: 'Mutually exclusive parameters were combined: "geo" filter + geo_level, or since_period/until_period + last_n_periods.',
162
183
  recovery: 'Use "geo" or geo_level (not both); use since_period/until_period or last_n_periods (not both).',
163
184
  },
185
+ {
186
+ reason: 'canvas_not_found',
187
+ code: JsonRpcErrorCode.NotFound,
188
+ when: 'A canvas_id was supplied for staging but is unknown or its lifetime has elapsed.',
189
+ recovery: 'Omit canvas_id so the response starts a fresh canvas and returns its canvasId.',
190
+ },
164
191
  ],
165
192
  async handler(input, ctx) {
166
193
  const svc = getEurostatDataService();
@@ -204,13 +231,37 @@ export const eurostatQueryDataset = tool('eurostat_query_dataset', {
204
231
  }
205
232
  // The service caps `observations` while decoding, so its length says nothing about how
206
233
  // large the match was. `obsCount` is the full total and is what truncation turns on.
207
- const { appliedFilters, ...queryResult } = result;
234
+ const { appliedFilters, rows, ...queryResult } = result;
208
235
  const truncated = result.obsCount > OBS_CAP;
236
+ /**
237
+ * Stage the whole match only when the cap actually bit. Under the cap the
238
+ * caller already holds every row, so a canvas table would duplicate the
239
+ * response and burn a per-tenant canvas slot for nothing.
240
+ *
241
+ * `rows()` is a generator over the response body already in memory, so this
242
+ * costs no extra upstream request and never builds the full row set as an
243
+ * array — the canvas appender pulls one row at a time.
244
+ */
245
+ const canvas = truncated ? getCanvas() : undefined;
246
+ let staged;
247
+ if (canvas) {
248
+ const instance = await acquireCanvas(canvas, input.canvas_id, ctx);
249
+ const handle = await instance.registerTable(newTableName(), rows(), {
250
+ schema: observationRowSchema(result.dimensionsUsed),
251
+ signal: ctx.signal,
252
+ });
253
+ staged = {
254
+ canvasId: instance.canvasId,
255
+ tableName: handle.tableName,
256
+ stagedRowCount: handle.rowCount,
257
+ };
258
+ }
209
259
  ctx.log.info('Dataset query complete', {
210
260
  datasetCode: input.dataset_code,
211
261
  obsCount: result.obsCount,
212
262
  truncated,
213
263
  missingObsCount: result.missingObsCount,
264
+ ...(staged && { canvasId: staged.canvasId, tableName: staged.tableName }),
214
265
  });
215
266
  // Sourced from the service's applied set, not raw input: a zero-length filter array is
216
267
  // dropped from the upstream request, so echoing it back would claim a restriction that
@@ -225,9 +276,11 @@ export const eurostatQueryDataset = tool('eurostat_query_dataset', {
225
276
  },
226
277
  });
227
278
  if (truncated) {
228
- ctx.enrich.notice(`Result capped at ${OBS_CAP.toLocaleString()} rows. Add dimension filters (geo, unit, na_item) to reduce the result set.`);
279
+ ctx.enrich.notice(staged
280
+ ? `Inline rows capped at ${OBS_CAP.toLocaleString()} of ${result.obsCount.toLocaleString()} matched. All ${staged.stagedRowCount.toLocaleString()} are staged as table "${staged.tableName}" on canvas "${staged.canvasId}" — reach them with eurostat_dataframe_query, or narrow the query with dimension filters (geo, unit, na_item) to shrink what Eurostat sends.`
281
+ : `Result capped at ${OBS_CAP.toLocaleString()} of ${result.obsCount.toLocaleString()} matched rows. Add dimension filters (geo, unit, na_item) or a period range to bring the rest into reach.`);
229
282
  }
230
- return { ...queryResult, truncated };
283
+ return { ...queryResult, truncated, ...staged };
231
284
  },
232
285
  format: (result) => {
233
286
  // An absent period bound is named as unreported rather than rendered as a blank, so
@@ -235,12 +288,21 @@ export const eurostatQueryDataset = tool('eurostat_query_dataset', {
235
288
  const UNREPORTED = 'not reported by Eurostat';
236
289
  const { start, end } = result.timeRange;
237
290
  const period = start || end ? `${start ?? UNREPORTED} – ${end ?? UNREPORTED}` : UNREPORTED;
291
+ const truncationNote = !result.truncated
292
+ ? ''
293
+ : result.tableName
294
+ ? ' — inline rows capped at 5,000; the whole match is staged on the canvas below'
295
+ : ' — result capped at 5,000 rows. Add dimension filters to bring the rest into reach.';
238
296
  const lines = [
239
297
  `# ${result.datasetLabel} (\`${result.datasetCode}\`)`,
240
298
  `**Observations:** ${result.obsCount} (${result.missingObsCount} missing) | **Period:** ${period}`,
241
- `**Truncated:** ${result.truncated}${result.truncated ? ' — result capped at 5,000 rows. Add dimension filters to get the full result.' : ''}`,
242
- `**Dimensions:** ${result.dimensionsUsed.join(', ')}\n`,
299
+ `**Truncated:** ${result.truncated}${truncationNote}`,
300
+ `**Dimensions:** ${result.dimensionsUsed.join(', ')}`,
243
301
  ];
302
+ if (result.tableName) {
303
+ lines.push(`**Staged:** table \`${result.tableName}\` on canvas \`${result.canvasId}\` (stagedRowCount ${result.stagedRowCount}) — query it with eurostat_dataframe_query`);
304
+ }
305
+ lines.push('');
244
306
  // Render every observation so content[] carries the same rows as structuredContent —
245
307
  // both surfaces are already bounded by the row cap the decoder applies.
246
308
  for (const obs of result.observations) {
@@ -1 +1 @@
1
- {"version":3,"file":"eurostat-query-dataset.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/eurostat-query-dataset.tool.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"eurostat-query-dataset.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/eurostat-query-dataset.tool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * @fileoverview Module-level accessor for the framework's optional DataCanvas
3
+ * service, plus the acquire helper every canvas-touching handler goes through.
4
+ * @module services/canvas-accessor
5
+ */
6
+ import type { Context } from '@cyanheads/mcp-ts-core';
7
+ import type { CanvasInstance, DataCanvas } from '@cyanheads/mcp-ts-core/canvas';
8
+ /** Wired from `setup(core)` in `src/index.ts`. `undefined` when canvas is off. */
9
+ export declare function setCanvas(canvas: DataCanvas | undefined): void;
10
+ /**
11
+ * The DataCanvas service, or `undefined` when `CANVAS_PROVIDER_TYPE` is not
12
+ * `duckdb`. Callers branch on the absence rather than assuming a canvas exists:
13
+ * the server is a supported configuration with and without one.
14
+ */
15
+ export declare function getCanvas(): DataCanvas | undefined;
16
+ /**
17
+ * Acquire a canvas, translating a scratch-directory permission failure into an
18
+ * error that names the variable to change.
19
+ *
20
+ * DuckDB writes spill files under `CANVAS_TEMP_PATH`, whose directory is created
21
+ * on the first acquire. A container running as a non-root user against a
22
+ * root-owned or read-only path otherwise surfaces a bare `EACCES … mkdir` with
23
+ * nothing to connect it to a configuration knob.
24
+ */
25
+ export declare function acquireCanvas(canvas: DataCanvas, canvasId: string | undefined, ctx: Context): Promise<CanvasInstance>;
26
+ //# sourceMappingURL=canvas-accessor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canvas-accessor.d.ts","sourceRoot":"","sources":["../../src/services/canvas-accessor.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAKhF,kFAAkF;AAClF,wBAAgB,SAAS,CAAC,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,IAAI,CAE9D;AAED;;;;GAIG;AACH,wBAAgB,SAAS,IAAI,UAAU,GAAG,SAAS,CAElD;AAoBD;;;;;;;;GAQG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,UAAU,EAClB,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,GAAG,EAAE,OAAO,GACX,OAAO,CAAC,cAAc,CAAC,CAYzB"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * @fileoverview Module-level accessor for the framework's optional DataCanvas
3
+ * service, plus the acquire helper every canvas-touching handler goes through.
4
+ * @module services/canvas-accessor
5
+ */
6
+ import { serviceUnavailable } from '@cyanheads/mcp-ts-core/errors';
7
+ let _canvas;
8
+ /** Wired from `setup(core)` in `src/index.ts`. `undefined` when canvas is off. */
9
+ export function setCanvas(canvas) {
10
+ _canvas = canvas;
11
+ }
12
+ /**
13
+ * The DataCanvas service, or `undefined` when `CANVAS_PROVIDER_TYPE` is not
14
+ * `duckdb`. Callers branch on the absence rather than assuming a canvas exists:
15
+ * the server is a supported configuration with and without one.
16
+ */
17
+ export function getCanvas() {
18
+ return _canvas;
19
+ }
20
+ /**
21
+ * Errno codes meaning the configured scratch root cannot be written to.
22
+ *
23
+ * `ENOENT` is deliberately absent — `mkdir` is recursive, so a missing parent
24
+ * is created rather than reported.
25
+ */
26
+ const UNWRITABLE_ERRNOS = new Set(['EACCES', 'EPERM', 'EROFS', 'ENOSPC']);
27
+ /** First `errno` code found on an error or any link of its `cause` chain. */
28
+ function errnoOf(err) {
29
+ for (let cur = err, depth = 0; cur instanceof Error && depth < 5; depth++) {
30
+ const code = cur.code;
31
+ if (typeof code === 'string' && UNWRITABLE_ERRNOS.has(code))
32
+ return code;
33
+ cur = cur.cause;
34
+ }
35
+ return;
36
+ }
37
+ /**
38
+ * Acquire a canvas, translating a scratch-directory permission failure into an
39
+ * error that names the variable to change.
40
+ *
41
+ * DuckDB writes spill files under `CANVAS_TEMP_PATH`, whose directory is created
42
+ * on the first acquire. A container running as a non-root user against a
43
+ * root-owned or read-only path otherwise surfaces a bare `EACCES … mkdir` with
44
+ * nothing to connect it to a configuration knob.
45
+ */
46
+ export async function acquireCanvas(canvas, canvasId, ctx) {
47
+ try {
48
+ return await canvas.acquire(canvasId, ctx);
49
+ }
50
+ catch (err) {
51
+ const errno = errnoOf(err);
52
+ if (!errno)
53
+ throw err;
54
+ throw serviceUnavailable(`DataCanvas could not create its scratch directory (${errno}). Point CANVAS_TEMP_PATH at a directory the server process can write to, or set CANVAS_PROVIDER_TYPE=none to run without the dataframe tools.`, { reason: 'canvas_unavailable', errno }, { cause: err instanceof Error ? err : undefined });
55
+ }
56
+ }
57
+ //# sourceMappingURL=canvas-accessor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canvas-accessor.js","sourceRoot":"","sources":["../../src/services/canvas-accessor.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAEnE,IAAI,OAA+B,CAAC;AAEpC,kFAAkF;AAClF,MAAM,UAAU,SAAS,CAAC,MAA8B;IACtD,OAAO,GAAG,MAAM,CAAC;AACnB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,SAAS;IACvB,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;GAKG;AACH,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;AAE1E,6EAA6E;AAC7E,SAAS,OAAO,CAAC,GAAY;IAC3B,KAAK,IAAI,GAAG,GAAG,GAAG,EAAE,KAAK,GAAG,CAAC,EAAE,GAAG,YAAY,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC;QAC1E,MAAM,IAAI,GAAI,GAA6B,CAAC,IAAI,CAAC;QACjD,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;QACzE,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC;IAClB,CAAC;IACD,OAAO;AACT,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,MAAkB,EAClB,QAA4B,EAC5B,GAAY;IAEZ,IAAI,CAAC;QACH,OAAO,MAAM,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IAC7C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QAC3B,IAAI,CAAC,KAAK;YAAE,MAAM,GAAG,CAAC;QACtB,MAAM,kBAAkB,CACtB,sDAAsD,KAAK,gJAAgJ,EAC3M,EAAE,MAAM,EAAE,oBAAoB,EAAE,KAAK,EAAE,EACvC,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,EAAE,CAClD,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -4,9 +4,10 @@
4
4
  * @module services/eurostat-data/eurostat-data-service
5
5
  */
6
6
  import type { Context } from '@cyanheads/mcp-ts-core';
7
+ import type { ColumnSchema } from '@cyanheads/mcp-ts-core/canvas';
7
8
  import type { AppConfig } from '@cyanheads/mcp-ts-core/config';
8
9
  import type { StorageService } from '@cyanheads/mcp-ts-core/storage';
9
- import { type DatasetMeta, type DimensionValuesResult, type GeoLevel, type QueryResult } from './types.js';
10
+ import { type DatasetMeta, type DimensionValuesResult, type GeoLevel, type Observation, type ObservationRow, type QueryExecution } from './types.js';
10
11
  export declare class EurostatDataService {
11
12
  constructor(_config: AppConfig, _storage: StorageService);
12
13
  private buildUrl;
@@ -27,12 +28,26 @@ export declare class EurostatDataService {
27
28
  */
28
29
  private scanCells;
29
30
  /**
30
- * Decode a JSON-stat 2.0 response into labeled observations using stride-based indexing.
31
+ * Walk a JSON-stat 2.0 response's populated cells, yielding one labeled
32
+ * observation at a time via stride-based indexing.
31
33
  *
32
- * Stops once `limit` observations have been built, in ascending linear-index order — an
33
- * order the decoder sets itself rather than reading from the upstream key order, so the
34
- * rows returned for a given response are the same every time. Bounding here keeps an
35
- * oversized match from ever materializing as observation objects; the counts that
34
+ * Cells come out in ascending linear-index order — an order this walk sets
35
+ * itself rather than reading from the upstream key order, so a given response
36
+ * always yields the same rows in the same sequence. Being a generator, it
37
+ * allocates one observation per pull and none in advance, which is what lets
38
+ * the same walk serve both a capped decode and an uncapped dataframe spill.
39
+ *
40
+ * This is the only place cell membership is decided: a cell is an observation
41
+ * when its linear index appears in `value` or in `status`. `scanCells` counts
42
+ * that same predicate from the other direction (over the key maps) so the
43
+ * totals it reports describe exactly this set.
44
+ */
45
+ private iterateObservations;
46
+ /**
47
+ * Take the first `limit` observations off {@link iterateObservations}.
48
+ *
49
+ * Bounding here keeps an oversized match from ever materializing as observation
50
+ * objects — the walk stops the moment the cap is reached. The counts that
36
51
  * describe the whole match come from `scanCells`.
37
52
  */
38
53
  private decodeObservations;
@@ -89,10 +104,40 @@ export declare class EurostatDataService {
89
104
  getDimensionValues(datasetCode: string, dimension: string, geoLevel: GeoLevel | undefined, ctx: Context): Promise<DimensionValuesResult>;
90
105
  /**
91
106
  * Query dataset observations with dimension filters.
92
- * Returns decoded observations.
107
+ *
108
+ * Returns the capped observation list alongside `rows()`, a lazy generator
109
+ * over the whole match. Both read the same response body — already in memory
110
+ * before decoding starts — so reaching the rows past the cap costs no
111
+ * additional upstream request.
93
112
  */
94
- queryDataset(datasetCode: string, filters: Record<string, string[]>, geoLevel: GeoLevel | undefined, sinceP: string | undefined, untilP: string | undefined, lastN: number | undefined, lang: string, ctx: Context): Promise<QueryResult>;
113
+ queryDataset(datasetCode: string, filters: Record<string, string[]>, geoLevel: GeoLevel | undefined, sinceP: string | undefined, untilP: string | undefined, lastN: number | undefined, lang: string, ctx: Context): Promise<QueryExecution>;
114
+ /** {@link iterateObservations}, flattened to dataframe rows one at a time. */
115
+ private iterateRows;
95
116
  }
117
+ /**
118
+ * Flatten one observation into a dataframe row.
119
+ *
120
+ * The inverse of the nested shape `Observation` carries: each dimension
121
+ * contributes `<dim>` (code) and `<dim>_label`, and the status flag contributes
122
+ * `obs_flag` / `obs_flag_label`. A dimension the observation does not carry
123
+ * yields `null` in both of its columns rather than an absent key, so every row
124
+ * has the same column set the table is declared with.
125
+ */
126
+ export declare function toObservationRow(obs: Observation, dimensionsUsed: string[]): ObservationRow;
127
+ /**
128
+ * Explicit canvas column schema for {@link toObservationRow}'s output.
129
+ *
130
+ * Declared rather than sniffed. Inference reads only the leading rows, which is
131
+ * enough to get the measure column wrong twice over: an all-integer prefix types
132
+ * it `BIGINT`, which the canvas then serializes as a string, and an all-missing
133
+ * prefix types it from nulls alone. Every column is nullable — a dimension can
134
+ * be absent from a cell, and a status flag usually is.
135
+ *
136
+ * Names and order mirror {@link toObservationRow}. Nothing in the type system
137
+ * ties a row's keys to a schema's names, so the service tests assert the two
138
+ * against each other instead.
139
+ */
140
+ export declare function observationRowSchema(dimensionsUsed: string[]): ColumnSchema[];
96
141
  export declare function initEurostatDataService(config: AppConfig, storage: StorageService): void;
97
142
  export declare function getEurostatDataService(): EurostatDataService;
98
143
  //# sourceMappingURL=eurostat-data-service.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"eurostat-data-service.d.ts","sourceRoot":"","sources":["../../../src/services/eurostat-data/eurostat-data-service.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAO/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAGrE,OAAO,EACL,KAAK,WAAW,EAEhB,KAAK,qBAAqB,EAC1B,KAAK,QAAQ,EAIb,KAAK,WAAW,EACjB,MAAM,YAAY,CAAC;AAMpB,qBAAa,mBAAmB;IAI9B,YAAY,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,cAAc,EAAI;IAE5D,OAAO,CAAC,QAAQ;IAchB,OAAO,CAAC,SAAS;IA0DjB,OAAO,CAAC,mBAAmB;IAwC3B,oFAAoF;IACpF,OAAO,CAAC,cAAc;IAStB;;;;;;;;;;OAUG;IACH,OAAO,CAAC,SAAS;IA6CjB;;;;;;;;OAQG;IACH,OAAO,CAAC,kBAAkB;IA4D1B,OAAO,CAAC,iBAAiB;IAQzB;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,eAAe;IA4CvB;;;;;;;;;;;;;OAaG;IACG,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC,CAkB5E;IAED;;;;;;OAMG;IACH,OAAO,CAAC,aAAa;IAmBrB;;;;;;;;;;;;OAYG;IACG,kBAAkB,CACtB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,QAAQ,GAAG,SAAS,EAC9B,GAAG,EAAE,OAAO,GACX,OAAO,CAAC,qBAAqB,CAAC,CA4ChC;IAED;;;OAGG;IACG,YAAY,CAChB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EACjC,QAAQ,EAAE,QAAQ,GAAG,SAAS,EAC9B,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,OAAO,GACX,OAAO,CAAC,WAAW,CAAC,CA6EtB;CACF;AAMD,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,cAAc,GAAG,IAAI,CAExF;AAED,wBAAgB,sBAAsB,IAAI,mBAAmB,CAO5D"}
1
+ {"version":3,"file":"eurostat-data-service.d.ts","sourceRoot":"","sources":["../../../src/services/eurostat-data/eurostat-data-service.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAO/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAGrE,OAAO,EACL,KAAK,WAAW,EAEhB,KAAK,qBAAqB,EAC1B,KAAK,QAAQ,EAMb,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,cAAc,EACpB,MAAM,YAAY,CAAC;AAMpB,qBAAa,mBAAmB;IAI9B,YAAY,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,cAAc,EAAI;IAE5D,OAAO,CAAC,QAAQ;IAchB,OAAO,CAAC,SAAS;IA0DjB,OAAO,CAAC,mBAAmB;IAwC3B,oFAAoF;IACpF,OAAO,CAAC,cAAc;IAStB;;;;;;;;;;OAUG;IACH,OAAO,CAAC,SAAS;IA6CjB;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAE,mBAAmB;IAyD5B;;;;;;OAMG;IACH,OAAO,CAAC,kBAAkB;IAS1B,OAAO,CAAC,iBAAiB;IAQzB;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,eAAe;IA4CvB;;;;;;;;;;;;;OAaG;IACG,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC,CAkB5E;IAED;;;;;;OAMG;IACH,OAAO,CAAC,aAAa;IAmBrB;;;;;;;;;;;;OAYG;IACG,kBAAkB,CACtB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,QAAQ,GAAG,SAAS,EAC9B,GAAG,EAAE,OAAO,GACX,OAAO,CAAC,qBAAqB,CAAC,CA4ChC;IAED;;;;;;;OAOG;IACG,YAAY,CAChB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EACjC,QAAQ,EAAE,QAAQ,GAAG,SAAS,EAC9B,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,OAAO,GACX,OAAO,CAAC,cAAc,CAAC,CAgFzB;IAED,8EAA8E;IAC9E,OAAO,CAAE,WAAW;CAQrB;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,cAAc,CAW3F;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAAC,cAAc,EAAE,MAAM,EAAE,GAAG,YAAY,EAAE,CAU7E;AAMD,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,cAAc,GAAG,IAAI,CAExF;AAED,wBAAgB,sBAAsB,IAAI,mBAAmB,CAO5D"}
@@ -6,7 +6,7 @@
6
6
  import { McpError, notFound, serviceUnavailable, validationError, } from '@cyanheads/mcp-ts-core/errors';
7
7
  import { fetchWithTimeout, withRetry } from '@cyanheads/mcp-ts-core/utils';
8
8
  import { getServerConfig } from '../../config/server-config.js';
9
- import { OBS_CAP, } from './types.js';
9
+ import { OBS_CAP, OBS_FLAG_COLUMN, OBS_FLAG_LABEL_COLUMN, OBS_VALUE_COLUMN, } from './types.js';
10
10
  // Context satisfies the runtime contract of RequestContext but lacks the index signature
11
11
  // required by fetchWithTimeout/withRetry.
12
12
  const asReqCtx = (ctx) => ctx;
@@ -176,17 +176,23 @@ export class EurostatDataService {
176
176
  return { obsCount, missingObsCount, timeCodes: timeCodes.sort() };
177
177
  }
178
178
  /**
179
- * Decode a JSON-stat 2.0 response into labeled observations using stride-based indexing.
179
+ * Walk a JSON-stat 2.0 response's populated cells, yielding one labeled
180
+ * observation at a time via stride-based indexing.
180
181
  *
181
- * Stops once `limit` observations have been built, in ascending linear-index order — an
182
- * order the decoder sets itself rather than reading from the upstream key order, so the
183
- * rows returned for a given response are the same every time. Bounding here keeps an
184
- * oversized match from ever materializing as observation objects; the counts that
185
- * describe the whole match come from `scanCells`.
182
+ * Cells come out in ascending linear-index order — an order this walk sets
183
+ * itself rather than reading from the upstream key order, so a given response
184
+ * always yields the same rows in the same sequence. Being a generator, it
185
+ * allocates one observation per pull and none in advance, which is what lets
186
+ * the same walk serve both a capped decode and an uncapped dataframe spill.
187
+ *
188
+ * This is the only place cell membership is decided: a cell is an observation
189
+ * when its linear index appears in `value` or in `status`. `scanCells` counts
190
+ * that same predicate from the other direction (over the key maps) so the
191
+ * totals it reports describe exactly this set.
186
192
  */
187
- decodeObservations(data, limit) {
193
+ *iterateObservations(data) {
188
194
  if (!data.id || !data.size || !data.dimension)
189
- return [];
195
+ return;
190
196
  const dims = data.id;
191
197
  const sizes = data.size;
192
198
  const value = data.value ?? {};
@@ -205,9 +211,8 @@ export class EurostatDataService {
205
211
  label: cat.label?.[code] ?? code,
206
212
  }));
207
213
  });
208
- const observations = [];
209
214
  const totalCells = sizes.reduce((a, b) => a * b, 1);
210
- for (let linearIdx = 0; linearIdx < totalCells && observations.length < limit; linearIdx++) {
215
+ for (let linearIdx = 0; linearIdx < totalCells; linearIdx++) {
211
216
  const keyStr = String(linearIdx);
212
217
  if (!(keyStr in value) && !(keyStr in status))
213
218
  continue;
@@ -233,7 +238,22 @@ export class EurostatDataService {
233
238
  label: statusLabels[statusCode] ?? statusCode,
234
239
  };
235
240
  }
241
+ yield obs;
242
+ }
243
+ }
244
+ /**
245
+ * Take the first `limit` observations off {@link iterateObservations}.
246
+ *
247
+ * Bounding here keeps an oversized match from ever materializing as observation
248
+ * objects — the walk stops the moment the cap is reached. The counts that
249
+ * describe the whole match come from `scanCells`.
250
+ */
251
+ decodeObservations(data, limit) {
252
+ const observations = [];
253
+ for (const obs of this.iterateObservations(data)) {
236
254
  observations.push(obs);
255
+ if (observations.length >= limit)
256
+ break;
237
257
  }
238
258
  return observations;
239
259
  }
@@ -395,7 +415,11 @@ export class EurostatDataService {
395
415
  }
396
416
  /**
397
417
  * Query dataset observations with dimension filters.
398
- * Returns decoded observations.
418
+ *
419
+ * Returns the capped observation list alongside `rows()`, a lazy generator
420
+ * over the whole match. Both read the same response body — already in memory
421
+ * before decoding starts — so reaching the rows past the cap costs no
422
+ * additional upstream request.
399
423
  */
400
424
  async queryDataset(datasetCode, filters, geoLevel, sinceP, untilP, lastN, lang, ctx) {
401
425
  // A zero-length filter array places no restriction on the request. Drop those entries once,
@@ -446,17 +470,70 @@ export class EurostatDataService {
446
470
  const start = timeCodes[0] ?? this.extractAnnotation(data, 'OBS_PERIOD_OVERALL_OLDEST', 'title');
447
471
  const end = timeCodes.at(-1) ?? this.extractAnnotation(data, 'OBS_PERIOD_OVERALL_LATEST', 'title');
448
472
  const timeRange = { ...(start && { start }), ...(end && { end }) };
473
+ const dimensionsUsed = data.id ?? [];
449
474
  return {
450
475
  datasetCode,
451
476
  datasetLabel: data.label ?? datasetCode,
452
- dimensionsUsed: data.id ?? [],
477
+ dimensionsUsed,
453
478
  observations,
454
479
  obsCount,
455
480
  timeRange,
456
481
  missingObsCount,
457
482
  appliedFilters,
483
+ rows: () => this.iterateRows(data, dimensionsUsed),
458
484
  };
459
485
  }
486
+ /** {@link iterateObservations}, flattened to dataframe rows one at a time. */
487
+ *iterateRows(data, dimensionsUsed) {
488
+ for (const obs of this.iterateObservations(data)) {
489
+ yield toObservationRow(obs, dimensionsUsed);
490
+ }
491
+ }
492
+ }
493
+ /**
494
+ * Flatten one observation into a dataframe row.
495
+ *
496
+ * The inverse of the nested shape `Observation` carries: each dimension
497
+ * contributes `<dim>` (code) and `<dim>_label`, and the status flag contributes
498
+ * `obs_flag` / `obs_flag_label`. A dimension the observation does not carry
499
+ * yields `null` in both of its columns rather than an absent key, so every row
500
+ * has the same column set the table is declared with.
501
+ */
502
+ export function toObservationRow(obs, dimensionsUsed) {
503
+ const row = {};
504
+ for (const dim of dimensionsUsed) {
505
+ const cell = obs.dimensions[dim];
506
+ row[dim] = cell?.code ?? null;
507
+ row[`${dim}_label`] = cell?.label ?? null;
508
+ }
509
+ row[OBS_VALUE_COLUMN] = obs.value;
510
+ row[OBS_FLAG_COLUMN] = obs.status?.code ?? null;
511
+ row[OBS_FLAG_LABEL_COLUMN] = obs.status?.label ?? null;
512
+ return row;
513
+ }
514
+ /**
515
+ * Explicit canvas column schema for {@link toObservationRow}'s output.
516
+ *
517
+ * Declared rather than sniffed. Inference reads only the leading rows, which is
518
+ * enough to get the measure column wrong twice over: an all-integer prefix types
519
+ * it `BIGINT`, which the canvas then serializes as a string, and an all-missing
520
+ * prefix types it from nulls alone. Every column is nullable — a dimension can
521
+ * be absent from a cell, and a status flag usually is.
522
+ *
523
+ * Names and order mirror {@link toObservationRow}. Nothing in the type system
524
+ * ties a row's keys to a schema's names, so the service tests assert the two
525
+ * against each other instead.
526
+ */
527
+ export function observationRowSchema(dimensionsUsed) {
528
+ return [
529
+ ...dimensionsUsed.flatMap((dim) => [
530
+ { name: dim, type: 'VARCHAR', nullable: true },
531
+ { name: `${dim}_label`, type: 'VARCHAR', nullable: true },
532
+ ]),
533
+ { name: OBS_VALUE_COLUMN, type: 'DOUBLE', nullable: true },
534
+ { name: OBS_FLAG_COLUMN, type: 'VARCHAR', nullable: true },
535
+ { name: OBS_FLAG_LABEL_COLUMN, type: 'VARCHAR', nullable: true },
536
+ ];
460
537
  }
461
538
  // --- Init/accessor pattern ---
462
539
  let _service;