Skip to main content
Glama

Download Eurostat Dataset

eurostat_download_dataset
Read-onlyIdempotent

Download a Eurostat dataset in bulk through the SDMX 2.1 TSV endpoint and stage every observation as a SQL table on the dataframe canvas — the route to a whole dataset, where eurostat_query_dataset is the route to a slice of one. The TSV wire format is roughly half the bytes of the JSON-stat body eurostat_query_dataset reads, so it reaches datasets that would otherwise time out, and it is expanded here into one row per observation. Filters take the same dimension-code map eurostat_query_dataset uses and are applied server-side by Eurostat; call eurostat_get_dataset_info first for the dimension codes and eurostat_get_dimension_values for their values. Narrow with since_period/until_period rather than asking for the most recent N periods — the TSV layout keeps a column for every period whichever is requested, so a period range is what actually shrinks the response. Transfers are bounded by a byte budget enforced while streaming: when it is spent the download stops and budgetExceeded is set, leaving a prefix of the dataset rather than an error. Only preview_limit rows come back inline. When a table is staged, call eurostat_dataframe_describe first to confirm its columns, then eurostat_dataframe_query; without a canvas, rows past the preview are not retained.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
filtersNoDimension filters as a map of dimension code → array of accepted values, applied by Eurostat before the body is sent. Example: {"unit": ["CP_MEUR"], "na_item": ["B1G"], "geo": ["DE", "FR"]}. Omit a dimension or pass an empty array to accept every value for it. Dimension codes match in any case ("GEO" is geo). Do not put "time" here — use since_period/until_period. Naming a dimension the dataset does not have is rejected with the dataset's dimension list rather than silently ignored.
canvas_idNoReuse an existing dataframe canvas so this download lands beside earlier results and can be joined against them. Pass the canvasId a previous eurostat_download_dataset or eurostat_query_dataset response returned; omit to start a fresh canvas. Ignored on deployments without a dataframe canvas. A download that carries no observations fails as no_results and leaves the canvas untouched.
dataset_codeYesDataset code (e.g., "nama_10_gdp"). Required. A DS-* code — Comext detailed trade or PRODCOM, in any case — is served by the Comext host, which refuses an unfiltered download of its large collections as extraction_too_big: filter it, including freq on the trade flows, which mix annual and monthly series.
since_periodNoStart of the period range, inclusive, sent as startPeriod. Accepted forms: YYYY, YYYY-MM, YYYY-MM-DD, YYYY-Qn (1–4), YYYY-Sn (1–2), YYYY-Tn (1–3), YYYY-Mnn (01–12), YYYY-Wnn (a week the year has, up to 53) or YYYY-Dnnn (a day the year has, up to 366) (e.g., "2020", "2023-Q1", "2024-01"). Extra leading zeros after the letter are dropped ("2020-W001" is sent as "2020-W01"), a day of the year is sent as three digits ("2026-D1" as "2026-D001"), YYYY-A1 is sent as YYYY, and a period of another frequency is mapped onto the dataset's own. A malformed or non-existent period (e.g., "2020-13") is rejected as invalid_period. The most effective way to shrink a bulk response: it removes period columns from the TSV rather than blanking their cells.
until_periodNoEnd of the period range, inclusive (e.g., "2024"), sent as endPeriod, in the same forms as since_period. Omit for data through the latest available period. The range must hold at least one day: a since_period that starts after until_period ends is rejected as invalid_period, while pairs of different frequencies are fine ("2020-06" to "2020").
preview_limitNoHow many observations to echo inline, from the start of the download. Caps at 500. The full download is on the canvas table when one was staged; this is orientation, not the result set.

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
errorNoPresent when the call failed. Absent on success.
noticeNoGuidance on every download: the staged table with the required eurostat_dataframe_describe then eurostat_dataframe_query sequence (or, without a canvas, what was returned inline and what was discarded), preceded by byte-budget disclosure when the budget stopped the transfer and by the inline-preview length when preview_limit returns fewer rows than were downloaded.
canvasIdNoDataframe canvas holding the staged download. Pass to eurostat_dataframe_describe, eurostat_dataframe_query, or a later staging call. Omitted when nothing was staged.
rowCountNoObservations expanded from the download — one per populated cell, counting those Eurostat reports as unavailable.
bytesReadNoDecoded TSV bytes read from Eurostat — after gzip decompression when the body arrived compressed, so it measures the payload rather than the wire.
tableNameNoCanvas table holding every downloaded observation. Call eurostat_dataframe_describe with canvasId first to confirm the table and columns, then eurostat_dataframe_query. Omitted when this deployment runs without a dataframe canvas, in which case only the inline preview survives the call.
compressedNoTrue when Eurostat sent the body gzip-compressed. It does so without a Content-Encoding header on large responses, so this reports what the stream actually carried.
totalCountNoObservations the download produced — equal to rowCount. The inline observations array holds only the first preview_limit of them; budgetExceeded, not this count, says whether the download is the whole dataset.
datasetCodeNoDataset code as provided.
periodRangeNoPeriod coverage of the rows actually downloaded. Narrower than the dataset when budgetExceeded is true or a period range was applied.
appliedQueryNoThe bulk request as the server built it.
missingCountNoDownloaded observations carrying no numeric value (obs_value is null).
observationsNoThe first preview_limit observations of the download, in the order Eurostat streamed them. A prefix of the staged table, not a sample.
budgetExceededNoTrue when the byte budget stopped the transfer before the dataset ended, making the rows a prefix rather than the whole thing. Narrow with filters or a period range, or raise EUROSTAT_BULK_MAX_BYTES.
dimensionsUsedNoDimension codes carried by the downloaded rows, in the order Eurostat keys them (e.g., ["freq", "unit", "na_item", "geo"]). Read from the TSV header, so it reflects the response rather than metadata. The period lives in the separate "time" column.
stagedRowCountNoRows written to the canvas table. Matches rowCount. Omitted alongside tableName.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed5 schema fields changed
    • changedInput schema / properties / canvas_id / description
      Previous value: -"Reuse an existing dataframe canvas so this download lands beside earlier results and can be joined against them. Pass the canvasId a previous eurostat_download_dataset or eurostat_query_dataset response returned; omit to start a fresh canvas. Ignored on deployments without a dataframe canvas."New value: +"Reuse an existing dataframe canvas so this download lands beside earlier results and can be joined against them. Pass the canvasId a previous eurostat_download_dataset or eurostat_query_dataset response returned; omit to start a fresh canvas. Ignored on deployments without a dataframe canvas. A download that carries no observations fails as no_results and leaves the canvas untouched."
    • changedInput schema / properties / dataset_code / description
      Previous value: -"Dataset code (e.g., \"nama_10_gdp\"). Required."New value: +"Dataset code (e.g., \"nama_10_gdp\"). Required. A DS-* code — Comext detailed trade or PRODCOM, in any case — is served by the Comext host, which refuses an unfiltered download of its large collections as extraction_too_big: filter it, including freq on the trade flows, which mix annual and monthly series."
    • changedOutput schema / properties / error / properties / data / properties / reason / description
      Previous value: -"Machine-readable failure mode. Declared by this tool: `not_found`: The dataset code is not available for dissemination (HTTP 404, SDMX faultcode 100). `invalid_dimension`: A filter names a dimension the dataset does not have, or a value or period range Eurostat rejects (SDMX faultcode 150). `filter_arity`: Eurostat rejected the positional dimension key because it carried the wrong number of positions (SDMX faultcode 140, INVALID_QUERY_NB_FILTERS), meaning the dataset structure has changed since the metadata call. `invalid_period`: since_period or until_period is not a period literal, or names a month, quarter, semester, trimester, week or day that does not exist, or since_period starts after until_period ends. Checked before any request — the bulk endpoint would otherwise roll an out-of-range period into a neighbouring one, and answer an inverted range with the whole series — and SDMX faultcode 140 TIME_PERIOD_FILTER_SPEC_INVALID maps here too. `async_queued`: Eurostat answered HTTP 200 with a SOAP syncResponse queue ticket (status SUBMITTED) instead of data, because the extraction was too costly to serve synchronously. `no_results`: The download completed but carried no populated observation cells. `upstream_fault`: The SDMX endpoint returned a fault this server does not model, or a body that is not a TSV table. `canvas_not_found`: A canvas_id was supplied for staging but is unknown or its lifetime has elapsed. Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `not_found`: The dataset code is not available for dissemination (HTTP 404, SDMX faultcode 100). `invalid_dimension`: A filter names a dimension the dataset does not have, or a value or period range Eurostat rejects (SDMX faultcode 150). `filter_arity`: Eurostat rejected the positional dimension key because it carried the wrong number of positions (SDMX faultcode 140, INVALID_QUERY_NB_FILTERS), meaning the dataset structure has changed since the metadata call. `invalid_period`: since_period or until_period is not a period literal, or names a month, quarter, semester, trimester, week or day that does not exist, or since_period starts after until_period ends. Checked before any request — the bulk endpoint would otherwise roll an out-of-range period into a neighbouring one, and answer an inverted range with the whole series — and SDMX faultcode 140 TIME_PERIOD_FILTER_SPEC_INVALID maps here too. `async_queued`: Eurostat answered HTTP 200 with a SOAP syncResponse queue ticket (status SUBMITTED) instead of data, because the extraction was too costly to serve synchronously. `no_results`: The download completed but carried no populated observation cells. Nothing is staged, and no canvas is created or touched. `extraction_too_big`: Eurostat refused the extraction as too large (SDMX faultcode 413, HTTP 413): past its 5,000,000-row extraction limit, or an unfiltered download of a large DS-* Comext collection, which Eurostat serves only filtered. Covers every dataset, on either host. `upstream_fault`: The SDMX endpoint returned a fault this server does not model, or a body that is not a TSV table. `canvas_not_found`: A canvas_id was supplied for staging but is unknown or its lifetime has elapsed. Other values are possible when a failure originates below the handler."
    • changedOutput schema / properties / error / properties / data / properties / reason / examples
      Previous value: -[
      -  "not_found",
      -  "invalid_dimension",
      -  "filter_arity",
      -  "invalid_period",
      -  "async_queued",
      -  "no_results",
      -  "upstream_fault",
      -  "canvas_not_found"
      -]New value: +[
      +  "not_found",
      +  "invalid_dimension",
      +  "filter_arity",
      +  "invalid_period",
      +  "async_queued",
      +  "no_results",
      +  "extraction_too_big",
      +  "upstream_fault",
      +  "canvas_not_found"
      +]
    • changedOutput schema / properties / observations / items / description
      Previous value: -"One observation as a flat row: one column per dimension holding its code, \"time\" for the period, then obs_value, obs_flag, obs_flag_label, conf_status, conf_status_label. A label column is null when Eurostat publishes no label for that code."New value: +"One observation as a flat row: one column per dimension holding its code, \"time\" for the period, then obs_value, obs_flag, obs_flag_label, conf_status, conf_status_label. A label column is null when Eurostat publishes no label for that code. Rows of a DS-* dataset also carry obs_value_text after obs_value: a value Eurostat published as text, such as a PRODCOM quantity unit (\"KG\"), kept verbatim with obs_value null; a PRODCOM \":C\" arrives as conf_status \"C\" instead."
  2. Changed11 schema fields changed
    • changedInput schema / properties / filters / description
      Previous value: -"Dimension filters as a map of dimension code → array of accepted values, applied by Eurostat before the body is sent. Example: {\"unit\": [\"CP_MEUR\"], \"na_item\": [\"B1G\"], \"geo\": [\"DE\", \"FR\"]}. Omit a dimension or pass an empty array to accept every value for it. Do not put \"time\" here — use since_period/until_period. Naming a dimension the dataset does not have is rejected with the dataset's dimension list rather than silently ignored."New value: +"Dimension filters as a map of dimension code → array of accepted values, applied by Eurostat before the body is sent. Example: {\"unit\": [\"CP_MEUR\"], \"na_item\": [\"B1G\"], \"geo\": [\"DE\", \"FR\"]}. Omit a dimension or pass an empty array to accept every value for it. Dimension codes match in any case (\"GEO\" is geo). Do not put \"time\" here — use since_period/until_period. Naming a dimension the dataset does not have is rejected with the dataset's dimension list rather than silently ignored."
    • changedInput schema / properties / since_period / description
      Previous value: -"Start of the period range (e.g., \"2020\", \"2023-Q1\", \"2024-01\"), sent as startPeriod. The most effective way to shrink a bulk response: it removes period columns from the TSV rather than blanking their cells."New value: +"Start of the period range, inclusive, sent as startPeriod. Accepted forms: YYYY, YYYY-MM, YYYY-MM-DD, YYYY-Qn (1–4), YYYY-Sn (1–2), YYYY-Tn (1–3), YYYY-Mnn (01–12), YYYY-Wnn (a week the year has, up to 53) or YYYY-Dnnn (a day the year has, up to 366) (e.g., \"2020\", \"2023-Q1\", \"2024-01\"). Extra leading zeros after the letter are dropped (\"2020-W001\" is sent as \"2020-W01\"), a day of the year is sent as three digits (\"2026-D1\" as \"2026-D001\"), YYYY-A1 is sent as YYYY, and a period of another frequency is mapped onto the dataset's own. A malformed or non-existent period (e.g., \"2020-13\") is rejected as invalid_period. The most effective way to shrink a bulk response: it removes period columns from the TSV rather than blanking their cells."
    • changedInput schema / properties / until_period / description
      Previous value: -"End of the period range (e.g., \"2024\"), sent as endPeriod. Omit for data through the latest available period."New value: +"End of the period range, inclusive (e.g., \"2024\"), sent as endPeriod, in the same forms as since_period. Omit for data through the latest available period. The range must hold at least one day: a since_period that starts after until_period ends is rejected as invalid_period, while pairs of different frequencies are fine (\"2020-06\" to \"2020\")."
    • changedOutput schema / anyOf
      Previous value: -[
      -  {
      -    "not": {
      -      "required": [
      -        "error"
      -      ]
      -    },
      -    "required": [
      -      "datasetCode",
      -      "dimensionsUsed",
      -      "rowCount",
      -      "missingCount",
      -      "periodRange",
      -      "bytesRead",
      -      "compressed",
      -      "budgetExceeded",
      -      "observations",
      -      "appliedQuery"
      -    ]
      -  },
      -  {
      -    "required": [
      -      "error"
      -    ]
      -  }
      -]New value: +[
      +  {
      +    "not": {
      +      "required": [
      +        "error"
      +      ]
      +    },
      +    "required": [
      +      "datasetCode",
      +      "dimensionsUsed",
      +      "rowCount",
      +      "missingCount",
      +      "periodRange",
      +      "bytesRead",
      +      "compressed",
      +      "budgetExceeded",
      +      "observations",
      +      "totalCount",
      +      "appliedQuery"
      +    ]
      +  },
      +  {
      +    "required": [
      +      "error"
      +    ]
      +  }
      +]
    • removedOutput schema / properties / cap
      Removed value: -{
      -  "description": "The preview_limit applied to inline observations.",
      -  "type": "number"
      -}
    • changedOutput schema / properties / error / properties / data / properties / reason / description
      Previous value: -"Machine-readable failure mode. Declared by this tool: `not_found`: The dataset code is not available for dissemination (HTTP 404, SDMX faultcode 100). `invalid_dimension`: A filter names a dimension the dataset does not have, or a value or period range Eurostat rejects (SDMX faultcode 150). `filter_arity`: Eurostat rejected the positional dimension key because it carried the wrong number of positions (SDMX faultcode 140), meaning the dataset structure has changed since the metadata call. `async_queued`: Eurostat answered HTTP 200 with a SOAP syncResponse queue ticket (status SUBMITTED) instead of data, because the extraction was too costly to serve synchronously. `no_results`: The download completed but carried no populated observation cells. `upstream_fault`: The SDMX endpoint returned a fault this server does not model, or a body that is not a TSV table. `canvas_not_found`: A canvas_id was supplied for staging but is unknown or its lifetime has elapsed. Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `not_found`: The dataset code is not available for dissemination (HTTP 404, SDMX faultcode 100). `invalid_dimension`: A filter names a dimension the dataset does not have, or a value or period range Eurostat rejects (SDMX faultcode 150). `filter_arity`: Eurostat rejected the positional dimension key because it carried the wrong number of positions (SDMX faultcode 140, INVALID_QUERY_NB_FILTERS), meaning the dataset structure has changed since the metadata call. `invalid_period`: since_period or until_period is not a period literal, or names a month, quarter, semester, trimester, week or day that does not exist, or since_period starts after until_period ends. Checked before any request — the bulk endpoint would otherwise roll an out-of-range period into a neighbouring one, and answer an inverted range with the whole series — and SDMX faultcode 140 TIME_PERIOD_FILTER_SPEC_INVALID maps here too. `async_queued`: Eurostat answered HTTP 200 with a SOAP syncResponse queue ticket (status SUBMITTED) instead of data, because the extraction was too costly to serve synchronously. `no_results`: The download completed but carried no populated observation cells. `upstream_fault`: The SDMX endpoint returned a fault this server does not model, or a body that is not a TSV table. `canvas_not_found`: A canvas_id was supplied for staging but is unknown or its lifetime has elapsed. Other values are possible when a failure originates below the handler."
    • changedOutput schema / properties / error / properties / data / properties / reason / examples
      Previous value: -[
      -  "not_found",
      -  "invalid_dimension",
      -  "filter_arity",
      -  "async_queued",
      -  "no_results",
      -  "upstream_fault",
      -  "canvas_not_found"
      -]New value: +[
      +  "not_found",
      +  "invalid_dimension",
      +  "filter_arity",
      +  "invalid_period",
      +  "async_queued",
      +  "no_results",
      +  "upstream_fault",
      +  "canvas_not_found"
      +]
    • changedOutput schema / properties / notice / description
      Previous value: -"Guidance for every staged result, including the required eurostat_dataframe_describe then eurostat_dataframe_query sequence, composed with byte-budget, no-canvas, or empty-result disclosure when applicable."New value: +"Guidance on every download: the staged table with the required eurostat_dataframe_describe then eurostat_dataframe_query sequence (or, without a canvas, what was returned inline and what was discarded), preceded by byte-budget disclosure when the budget stopped the transfer and by the inline-preview length when preview_limit returns fewer rows than were downloaded."
    • removedOutput schema / properties / shown
      Removed value: -{
      -  "description": "Observations returned in the inline preview.",
      -  "type": "number"
      -}
    • addedOutput schema / properties / totalCount
      Added value: +{
      +  "description": "Observations the download produced — equal to rowCount. The inline observations array holds only the first preview_limit of them; budgetExceeded, not this count, says whether the download is the whole dataset.",
      +  "type": "number"
      +}
    • removedOutput schema / properties / truncated
      Removed value: -{
      -  "description": "True when the inline observation preview omits rows.",
      -  "type": "boolean"
      -}
  3. Changed2 schema fields changed
    • changedInput schema / properties / canvas_id / description
      Previous value: -"Reuse an existing dataframe canvas so this download lands beside earlier results 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."New value: +"Reuse an existing dataframe canvas so this download lands beside earlier results and can be joined against them. Pass the canvasId a previous eurostat_download_dataset or eurostat_query_dataset response returned; omit to start a fresh canvas. Ignored on deployments without a dataframe canvas."
    • addedInput schema / properties / canvas_id / pattern
      Added value: +"^[A-Za-z0-9_-]{10}$"
  4. Changed2 schema fields changed
    • removedOutput schema / properties / observations / items / additionalProperties / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "number"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedOutput schema / properties / observations / items / additionalProperties / type
      Added value: +[
      +  "string",
      +  "number",
      +  "null"
      +]
  5. Changed2 schema fields changed
    • changedOutput schema / properties / notice / description
      Previous value: -"Guidance when the download was cut short by the byte budget, when nothing could be staged, or when it returned no observations. Omitted otherwise."New value: +"Guidance for every staged result, including the required eurostat_dataframe_describe then eurostat_dataframe_query sequence, composed with byte-budget, no-canvas, or empty-result disclosure when applicable."
    • changedOutput schema / properties / tableName / description
      Previous value: -"Canvas table holding every downloaded observation. Omitted when this deployment runs without a dataframe canvas, in which case only the inline preview survives the call."New value: +"Canvas table holding every downloaded observation. Call eurostat_dataframe_describe with canvasId first to confirm the table and columns, then eurostat_dataframe_query. Omitted when this deployment runs without a dataframe canvas, in which case only the inline preview survives the call."
  6. Changed9 schema fields changed
    • changedInput schema / $schema
      Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • addedInput schema / additionalProperties
      Added value: +false
    • changedOutput schema / $schema
      Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • addedOutput schema / anyOf
      Added value: +[
      +  {
      +    "not": {
      +      "required": [
      +        "error"
      +      ]
      +    },
      +    "required": [
      +      "datasetCode",
      +      "dimensionsUsed",
      +      "rowCount",
      +      "missingCount",
      +      "periodRange",
      +      "bytesRead",
      +      "compressed",
      +      "budgetExceeded",
      +      "observations",
      +      "appliedQuery"
      +    ]
      +  },
      +  {
      +    "required": [
      +      "error"
      +    ]
      +  }
      +]
    • addedOutput schema / properties / cap
      Added value: +{
      +  "description": "The preview_limit applied to inline observations.",
      +  "type": "number"
      +}
    • addedOutput schema / properties / error
      Added value: +{
      +  "additionalProperties": {},
      +  "description": "Present when the call failed. Absent on success.",
      +  "properties": {
      +    "code": {
      +      "description": "JSON-RPC error code for this failure.",
      +      "maximum": 9007199254740991,
      +      "minimum": -9007199254740991,
      +      "type": "integer"
      +    },
      +    "data": {
      +      "additionalProperties": {},
      +      "properties": {
      +        "reason": {
      +          "description": "Machine-readable failure mode. Declared by this tool: `not_found`: The dataset code is not available for dissemination (HTTP 404, SDMX faultcode 100). `invalid_dimension`: A filter names a dimension the dataset does not have, or a value or period range Eurostat rejects (SDMX faultcode 150). `filter_arity`: Eurostat rejected the positional dimension key because it carried the wrong number of positions (SDMX faultcode 140), meaning the dataset structure has changed since the metadata call. `async_queued`: Eurostat answered HTTP 200 with a SOAP syncResponse queue ticket (status SUBMITTED) instead of data, because the extraction was too costly to serve synchronously. `no_results`: The download completed but carried no populated observation cells. `upstream_fault`: The SDMX endpoint returned a fault this server does not model, or a body that is not a TSV table. `canvas_not_found`: A canvas_id was supplied for staging but is unknown or its lifetime has elapsed. Other values are possible when a failure originates below the handler.",
      +          "examples": [
      +            "not_found",
      +            "invalid_dimension",
      +            "filter_arity",
      +            "async_queued",
      +            "no_results",
      +            "upstream_fault",
      +            "canvas_not_found"
      +          ],
      +          "type": "string"
      +        },
      +        "recovery": {
      +          "additionalProperties": {},
      +          "description": "Actionable next step for the caller.",
      +          "properties": {
      +            "hint": {
      +              "type": "string"
      +            }
      +          },
      +          "required": [
      +            "hint"
      +          ],
      +          "type": "object"
      +        },
      +        "retryable": {
      +          "description": "Whether retrying may succeed.",
      +          "type": "boolean"
      +        }
      +      },
      +      "type": "object"
      +    },
      +    "message": {
      +      "description": "Human-readable description of what went wrong.",
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "code",
      +    "message"
      +  ],
      +  "type": "object"
      +}
    • addedOutput schema / properties / shown
      Added value: +{
      +  "description": "Observations returned in the inline preview.",
      +  "type": "number"
      +}
    • addedOutput schema / properties / truncated
      Added value: +{
      +  "description": "True when the inline observation preview omits rows.",
      +  "type": "boolean"
      +}
    • removedOutput schema / required
      Removed value: -[
      -  "datasetCode",
      -  "dimensionsUsed",
      -  "rowCount",
      -  "missingCount",
      -  "periodRange",
      -  "bytesRead",
      -  "compressed",
      -  "budgetExceeded",
      -  "observations",
      -  "appliedQuery"
      -]
  7. Added

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, openWorldHint, and idempotentHint, so the safety profile is covered. The description goes beyond this to disclose the byte budget and budgetExceeded behavior, the preview_limit as orientation only, the canvas retention rule (rows past preview not retained without a canvas), and error conditions like extraction_too_big and no_results. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Despite its length, every sentence earns its place. The structure front-loads the core purpose and contrast, then systematically covers filters, periods, budget, preview, and canvas usage. There is no fluff or repetition; it is dense but tightly organized.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (6 params, nested filters, multiple error modes, a byte budget, and a canvas workflow), the description covers everything an agent needs: the full workflow, the rationale for period ranges, the Comext caveat, and post-download steps. An output schema exists, so return-value details are unnecessary.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

While schema coverage is 100%, the description adds substantial meaning: filters are case-insensitive, 'time' must not be placed there, unknown dimensions are rejected with the dimension list; period forms and normalization (leading zeros, YYYY-A1 mapping) are detailed; preview_limit is clarified as orientation, not the result set. This enriches each parameter beyond the schema's own descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb-resource pair ('Download a Eurostat dataset in bulk through the SDMX 2.1 TSV endpoint') and immediately distinguishes it from its sibling eurostat_query_dataset ('the route to a whole dataset' vs 'the route to a slice of one'). It names the wire format, the staging behavior, and the contrast, leaving no ambiguity about what the tool does and how it differs.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly states when to use this tool versus alternatives ('the route to a whole dataset, where eurostat_query_dataset is the route to a slice of one') and provides a clear workflow: call eurostat_get_dataset_info first for codes, eurostat_get_dimension_values for values, then after staging use eurostat_dataframe_describe and eurostat_dataframe_query. It also gives specific advice on period narrowing and the byte budget, leaving no guesswork.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.