Skip to main content
Glama

Query Eurostat Dataset

eurostat_query_dataset
Read-onlyIdempotent

Fetch statistical data from a Eurostat dataset with dimension filters. Returns a deterministic inline prefix of decoded observations with dimension codes and labels, numeric values, an OBS_FLAG status (e.g., "p" = provisional, "e" = estimated) and a separate CONF_STATUS confidentiality marker (e.g., "C" = confidential, which is usually why a value is null). preview_limit controls only that prefix; filters and period controls reduce the matched result itself. 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. Matches above 5,000 observations are staged whole when this deployment runs a dataframe canvas: call eurostat_dataframe_describe first, then eurostat_dataframe_query. Matches at or below 5,000 are never staged. When the target is a whole dataset rather than a slice, eurostat_download_dataset reads the SDMX bulk endpoint instead and is the cheaper route.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
langNoLanguage for labels in the response. Default is "EN". Options: "EN", "FR", "DE".EN
filtersNoDimension filters as a map of dimension code → array of valid values. Example: {"unit": ["CP_MEUR"], "na_item": ["B1GQ"], "geo": ["DE", "FR"]}. An empty array is treated as no filter for that dimension and is dropped from the request. Dimension codes match in any case ("GEO" is geo). Do not include "geo" here if using geo_level. A value that matches nothing contributes no rows rather than an error; the response names it in unmatchedValues, or in the no_results error when nothing matched at all. eurostat_get_dimension_values lists the valid values.
canvas_idNoReuse an existing dataframe canvas, so a result staged by this call lands beside earlier ones and can be joined against them. Pass the canvasId a previous eurostat_query_dataset or eurostat_download_dataset response returned; omit to start a fresh canvas. Ignored on deployments without a dataframe canvas and when the match is at or below 5,000 observations.
geo_levelNoFilter by NUTS hierarchy level. Mutually exclusive with a "geo" key in filters. Options: "aggregate" (EU/EA totals), "country" (41 member/candidate states), "nuts1" (127 major regions), "nuts2" (309 basic regions), "nuts3" (1,343 small regions).
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: filter freq on its trade flows, which mix annual and monthly series, and note that product, reporter and partner carry aggregates (TOTAL, EU27_2020) that double-count when summed with their members.
since_periodNoStart of the time range, inclusive. 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-Q01" is sent as "2020-Q1"), a day of the year is sent as three digits ("2026-D1" as "2026-D001"), and YYYY-A1 is sent as YYYY. A period of another frequency is mapped onto the dataset's own, so "2020-01" works on annual data. A malformed or non-existent period (e.g., "2020-13") is rejected as invalid_period. Mutually exclusive with last_n_periods.
until_periodNoEnd of the time range, inclusive (e.g., "2024"), 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"). Mutually exclusive with last_n_periods.
preview_limitNoHow many matched observations to return inline, from the deterministic start of the JSON-stat cell order. Default 50; maximum 500. This changes only the inline prefix: it does not reduce obsCount, missingObsCount, timeRange, the upstream response, or the rows staged when the match exceeds 5,000. Use filters or period controls to reduce the match itself.
last_n_periodsNoReturn only the N most recent periods. N counts back from the dataset's latest period, not from the latest period published for this slice, so a slice that lags the rest of the dataset can come back empty — raise N, or use until_period ending at a period the slice has published. Mutually exclusive with since_period and until_period.

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
errorNoPresent when the call failed. Absent on success.
noticeNoGuidance when a filter value matched nothing, when preview_limit omits matched rows, or when the match was staged — names the unmatched values, distinguishes the inline prefix from filters that reduce the match and, when staged, gives the describe-then-query sequence. Omitted when every filter value matched and the preview contains the whole match.
canvasIdNoDataframe 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.
obsCountNoTotal number of observations matched (before any cap).
tableNameNoCanvas 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, conf_status, conf_status_label. A DS-* table also carries obs_value_text, the valueText of each row. Call eurostat_dataframe_describe with canvasId first to confirm the table and columns, then eurostat_dataframe_query. Omitted when nothing was staged: either the match was at or below 5,000 observations, or this deployment runs without a dataframe canvas.
timeRangeNoTime coverage of everything matched — the same set obsCount counts, so it can reach periods absent from observations when truncated is true. Each bound is omitted when neither the match nor Eurostat report it — an omitted bound is unknown, not empty.
truncatedNoTrue only when the match exceeded the 5,000-observation staging threshold. Independent of preview_limit: observations can be a shorter prefix while truncated is false. When tableName is set, call eurostat_dataframe_describe first and then eurostat_dataframe_query; when it is absent, use filters or period controls to reduce the match.
datasetCodeNoDataset code as provided.
datasetLabelNoHuman-readable dataset title.
observationsNoThe first preview_limit decoded observations in deterministic JSON-stat cell order — the leading combinations of the dataset dimensions, neither a sample nor necessarily the most recent periods. This prefix is independent of the 5,000-observation staging threshold. When tableName is set, the table holds every matched row; otherwise use filters or a period range to reduce the match itself.
appliedFiltersNoEffective query parameters applied to the Eurostat API.
dimensionsUsedNoOrdered list of dimension codes present in the response (e.g., ["freq", "unit", "na_item", "geo", "time"]).
stagedRowCountNoRows written to the canvas table. Matches obsCount. Omitted alongside tableName when nothing was staged.
missingObsCountNoNumber of matched observations carrying no numeric value, counted across everything matched rather than only the returned rows. Covers both unavailable and withheld cells — a slice can be wholly confidential, so this equalling obsCount does not mean the data is absent.
unmatchedValuesNoFilter values that matched nothing in the dataset, keyed by dimension code and spelled as sent (matching ignores case). The observations cover only the values that did match. Omitted when every filter value matched.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed5 schema fields changed
    • 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: filter freq on its trade flows, which mix annual and monthly series, and note that product, reporter and partner carry aggregates (TOTAL, EU27_2020) that double-count when summed with their members."
    • changedOutput schema / properties / error / properties / data / properties / reason / description
      Previous value: -"Machine-readable failure mode. Declared by this tool: `not_found`: The dataset code does not exist (HTTP 404 carrying Eurostat error id 100). `no_results`: The query matched no observation cells — including Eurostat HTTP-200 error id 100. The dataset is valid, but no cell carries a value or a status flag for that filter combination and period range. When Eurostat returns the empty table, the error names the filter values that matched nothing (data.unmatchedValues) and the selected periods that carry no value (data.matchedPeriods, the newest 24, with data.matchedPeriodCount counting all of them). `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; a period Eurostat itself rejects maps here too. `async_response`: Eurostat returned an async warning or HTTP-413 error array — the query matched too many observations. `invalid_dimension`: A dimension code in filters does not exist in this dataset (HTTP 400, Eurostat error id 150). `conflicting_params`: Mutually exclusive parameters were combined: \"geo\" filter + geo_level, or since_period/until_period + last_n_periods. `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 does not exist (HTTP 404 carrying Eurostat error id 100). `no_results`: The query matched no observation cells — including Eurostat HTTP-200 error id 100. The dataset is valid, but no cell carries a value or a status flag for that filter combination and period range. When Eurostat returns the empty table, the error names the filter values that matched nothing (data.unmatchedValues) and the selected periods that carry no value (data.matchedPeriods, the newest 24, with data.matchedPeriodCount counting all of them). `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; a period Eurostat itself rejects maps here too. `async_response`: Eurostat returned an async warning or an HTTP-413 error array — the query matched too many observations, including an EXTRACTION_TOO_BIG refusal past Eurostat's 5,000,000-row limit. `invalid_dimension`: A dimension code in filters does not exist in this dataset (HTTP 400, Eurostat error id 150). `conflicting_params`: Mutually exclusive parameters were combined: \"geo\" filter + geo_level, or since_period/until_period + last_n_periods. `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 / observations / items / properties / value / description
      Previous value: -"Numeric observation value, or null when Eurostat reports none — either unavailable in the source data or withheld, in which case confStatus says so."New value: +"Numeric observation value, or null when Eurostat reports none — unavailable in the source data, withheld (confStatus says so), or published as text (valueText holds it)."
    • addedOutput schema / properties / observations / items / properties / valueText
      Added value: +{
      +  "description": "A value Eurostat published as text rather than a number, verbatim — PRODCOM (DS-*) flag and unit indicators such as QNTUNIT publish a unit like \"KG\" — with value null. PRODCOM's \":C\" is decoded to confStatus \"C\" instead. Omitted for numeric and missing values.",
      +  "type": "string"
      +}
    • changedOutput schema / properties / tableName / description
      Previous value: -"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, conf_status, conf_status_label. Call eurostat_dataframe_describe with canvasId first to confirm the table and columns, then eurostat_dataframe_query. Omitted when nothing was staged: either the match was at or below 5,000 observations, or this deployment runs without a dataframe canvas."New value: +"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, conf_status, conf_status_label. A DS-* table also carries obs_value_text, the valueText of each row. Call eurostat_dataframe_describe with canvasId first to confirm the table and columns, then eurostat_dataframe_query. Omitted when nothing was staged: either the match was at or below 5,000 observations, or this deployment runs without a dataframe canvas."
  2. Changed8 schema fields changed
    • changedInput schema / properties / filters / description
      Previous value: -"Dimension filters as a map of dimension code → array of valid values. Example: {\"unit\": [\"CP_MEUR\"], \"na_item\": [\"B1GQ\"], \"geo\": [\"DE\", \"FR\"]}. An empty array is treated as no filter for that dimension and is dropped from the request. Do not include \"geo\" here if using geo_level. Invalid dimension values silently return no data — verify with eurostat_get_dimension_values first."New value: +"Dimension filters as a map of dimension code → array of valid values. Example: {\"unit\": [\"CP_MEUR\"], \"na_item\": [\"B1GQ\"], \"geo\": [\"DE\", \"FR\"]}. An empty array is treated as no filter for that dimension and is dropped from the request. Dimension codes match in any case (\"GEO\" is geo). Do not include \"geo\" here if using geo_level. A value that matches nothing contributes no rows rather than an error; the response names it in unmatchedValues, or in the no_results error when nothing matched at all. eurostat_get_dimension_values lists the valid values."
    • changedInput schema / properties / last_n_periods / description
      Previous value: -"Return only the N most recent periods. Mutually exclusive with since_period and until_period."New value: +"Return only the N most recent periods. N counts back from the dataset's latest period, not from the latest period published for this slice, so a slice that lags the rest of the dataset can come back empty — raise N, or use until_period ending at a period the slice has published. Mutually exclusive with since_period and until_period."
    • changedInput schema / properties / since_period / description
      Previous value: -"Start of time range (e.g., \"2020\", \"2023-Q1\", \"2024-01\"). Mutually exclusive with last_n_periods."New value: +"Start of the time range, inclusive. 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-Q01\" is sent as \"2020-Q1\"), a day of the year is sent as three digits (\"2026-D1\" as \"2026-D001\"), and YYYY-A1 is sent as YYYY. A period of another frequency is mapped onto the dataset's own, so \"2020-01\" works on annual data. A malformed or non-existent period (e.g., \"2020-13\") is rejected as invalid_period. Mutually exclusive with last_n_periods."
    • changedInput schema / properties / until_period / description
      Previous value: -"End of time range (e.g., \"2024\"). Omit for data through the latest available period. Mutually exclusive with last_n_periods."New value: +"End of the time range, inclusive (e.g., \"2024\"), 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\"). Mutually exclusive with last_n_periods."
    • changedOutput schema / properties / error / properties / data / properties / reason / description
      Previous value: -"Machine-readable failure mode. Declared by this tool: `not_found`: The dataset code does not exist (HTTP 404 carrying Eurostat error id 100). `no_results`: The query matched no observation cells — including Eurostat HTTP-200 error id 100. The dataset is valid, but no cell carries a value or a status flag for that filter combination and period range. `async_response`: Eurostat returned an async warning or HTTP-413 error array — the query matched too many observations. `invalid_dimension`: A dimension code in filters does not exist in this dataset (HTTP 400, Eurostat error id 150). `conflicting_params`: Mutually exclusive parameters were combined: \"geo\" filter + geo_level, or since_period/until_period + last_n_periods. `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 does not exist (HTTP 404 carrying Eurostat error id 100). `no_results`: The query matched no observation cells — including Eurostat HTTP-200 error id 100. The dataset is valid, but no cell carries a value or a status flag for that filter combination and period range. When Eurostat returns the empty table, the error names the filter values that matched nothing (data.unmatchedValues) and the selected periods that carry no value (data.matchedPeriods, the newest 24, with data.matchedPeriodCount counting all of them). `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; a period Eurostat itself rejects maps here too. `async_response`: Eurostat returned an async warning or HTTP-413 error array — the query matched too many observations. `invalid_dimension`: A dimension code in filters does not exist in this dataset (HTTP 400, Eurostat error id 150). `conflicting_params`: Mutually exclusive parameters were combined: \"geo\" filter + geo_level, or since_period/until_period + last_n_periods. `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",
      -  "no_results",
      -  "async_response",
      -  "invalid_dimension",
      -  "conflicting_params",
      -  "canvas_not_found"
      -]New value: +[
      +  "not_found",
      +  "no_results",
      +  "invalid_period",
      +  "async_response",
      +  "invalid_dimension",
      +  "conflicting_params",
      +  "canvas_not_found"
      +]
    • changedOutput schema / properties / notice / description
      Previous value: -"Guidance when preview_limit omits matched rows or the match was staged — distinguishes the inline prefix from filters that reduce the match and, when staged, gives the describe-then-query sequence. Omitted when the preview contains the whole match."New value: +"Guidance when a filter value matched nothing, when preview_limit omits matched rows, or when the match was staged — names the unmatched values, distinguishes the inline prefix from filters that reduce the match and, when staged, gives the describe-then-query sequence. Omitted when every filter value matched and the preview contains the whole match."
    • addedOutput schema / properties / unmatchedValues
      Added value: +{
      +  "additionalProperties": {
      +    "items": {
      +      "type": "string"
      +    },
      +    "type": "array"
      +  },
      +  "description": "Filter values that matched nothing in the dataset, keyed by dimension code and spelled as sent (matching ignores case). The observations cover only the values that did match. Omitted when every filter value matched.",
      +  "propertyNames": {
      +    "type": "string"
      +  },
      +  "type": "object"
      +}
  3. Changed2 schema fields changed
    • changedInput schema / properties / canvas_id / description
      Previous value: -"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 match is at or below 5,000 observations."New value: +"Reuse an existing dataframe canvas, so a result staged by this call lands beside earlier ones and can be joined against them. Pass the canvasId a previous eurostat_query_dataset or eurostat_download_dataset response returned; omit to start a fresh canvas. Ignored on deployments without a dataframe canvas and when the match is at or below 5,000 observations."
    • addedInput schema / properties / canvas_id / pattern
      Added value: +"^[A-Za-z0-9_-]{10}$"
  4. Changed2 schema fields changed
    • removedOutput schema / properties / observations / items / properties / value / anyOf
      Removed value: -[
      -  {
      -    "type": "number"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedOutput schema / properties / observations / items / properties / value / type
      Added value: +[
      +  "number",
      +  "null"
      +]
  5. Changed7 schema fields changed
    • changedInput schema / properties / canvas_id / description
      Previous value: -"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."New value: +"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 match is at or below 5,000 observations."
    • addedInput schema / properties / preview_limit
      Added value: +{
      +  "default": 50,
      +  "description": "How many matched observations to return inline, from the deterministic start of the JSON-stat cell order. Default 50; maximum 500. This changes only the inline prefix: it does not reduce obsCount, missingObsCount, timeRange, the upstream response, or the rows staged when the match exceeds 5,000. Use filters or period controls to reduce the match itself.",
      +  "maximum": 500,
      +  "minimum": 1,
      +  "type": "integer"
      +}
    • changedOutput schema / properties / error / properties / data / properties / reason / description
      Previous value: -"Machine-readable failure mode. Declared by this tool: `not_found`: The dataset code does not exist (HTTP 404, Eurostat error id 100). `no_results`: The query matched no observation cells — valid dataset, but no cell carries a value or a status flag for that filter combination and period range. `async_response`: Eurostat returned an async warning — the query matched too many observations. `invalid_dimension`: A dimension code in filters does not exist in this dataset (HTTP 400, Eurostat error id 150). `conflicting_params`: Mutually exclusive parameters were combined: \"geo\" filter + geo_level, or since_period/until_period + last_n_periods. `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 does not exist (HTTP 404 carrying Eurostat error id 100). `no_results`: The query matched no observation cells — including Eurostat HTTP-200 error id 100. The dataset is valid, but no cell carries a value or a status flag for that filter combination and period range. `async_response`: Eurostat returned an async warning or HTTP-413 error array — the query matched too many observations. `invalid_dimension`: A dimension code in filters does not exist in this dataset (HTTP 400, Eurostat error id 150). `conflicting_params`: Mutually exclusive parameters were combined: \"geo\" filter + geo_level, or since_period/until_period + last_n_periods. `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 / notice / description
      Previous value: -"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."New value: +"Guidance when preview_limit omits matched rows or the match was staged — distinguishes the inline prefix from filters that reduce the match and, when staged, gives the describe-then-query sequence. Omitted when the preview contains the whole match."
    • changedOutput schema / properties / observations / description
      Previous value: -"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, or switch to eurostat_download_dataset when the whole dataset is what is wanted."New value: +"The first preview_limit decoded observations in deterministic JSON-stat cell order — the leading combinations of the dataset dimensions, neither a sample nor necessarily the most recent periods. This prefix is independent of the 5,000-observation staging threshold. When tableName is set, the table holds every matched row; otherwise use filters or a period range to reduce the match itself."
    • changedOutput schema / properties / tableName / description
      Previous value: -"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, conf_status, conf_status_label. The five measure columns match the ones eurostat_download_dataset stages, so the two tables join on dimension codes and time and compare like with like. Omitted when nothing was staged: either the result fit under the cap, or this deployment runs without a dataframe canvas."New value: +"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, conf_status, conf_status_label. Call eurostat_dataframe_describe with canvasId first to confirm the table and columns, then eurostat_dataframe_query. Omitted when nothing was staged: either the match was at or below 5,000 observations, or this deployment runs without a dataframe canvas."
    • changedOutput schema / properties / truncated / description
      Previous value: -"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, or downloading the dataset with eurostat_download_dataset, is what brings the rest into reach."New value: +"True only when the match exceeded the 5,000-observation staging threshold. Independent of preview_limit: observations can be a shorter prefix while truncated is false. When tableName is set, call eurostat_dataframe_describe first and then eurostat_dataframe_query; when it is absent, use filters or period controls to reduce the match."
  6. Changed6 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",
      +      "datasetLabel",
      +      "dimensionsUsed",
      +      "observations",
      +      "obsCount",
      +      "truncated",
      +      "timeRange",
      +      "missingObsCount",
      +      "appliedFilters"
      +    ]
      +  },
      +  {
      +    "required": [
      +      "error"
      +    ]
      +  }
      +]
    • 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 does not exist (HTTP 404, Eurostat error id 100). `no_results`: The query matched no observation cells — valid dataset, but no cell carries a value or a status flag for that filter combination and period range. `async_response`: Eurostat returned an async warning — the query matched too many observations. `invalid_dimension`: A dimension code in filters does not exist in this dataset (HTTP 400, Eurostat error id 150). `conflicting_params`: Mutually exclusive parameters were combined: \"geo\" filter + geo_level, or since_period/until_period + last_n_periods. `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",
      +            "no_results",
      +            "async_response",
      +            "invalid_dimension",
      +            "conflicting_params",
      +            "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"
      +}
    • removedOutput schema / required
      Removed value: -[
      -  "datasetCode",
      -  "datasetLabel",
      -  "dimensionsUsed",
      -  "observations",
      -  "obsCount",
      -  "truncated",
      -  "timeRange",
      -  "missingObsCount",
      -  "appliedFilters"
      -]
  7. Changed7 schema fields changed
    • changedOutput schema / properties / missingObsCount / description
      Previous value: -"Number of matched observations with null value (missing data points in the source), counted across everything matched rather than only the returned rows."New value: +"Number of matched observations carrying no numeric value, counted across everything matched rather than only the returned rows. Covers both unavailable and withheld cells — a slice can be wholly confidential, so this equalling obsCount does not mean the data is absent."
    • changedOutput schema / properties / observations / items / description
      Previous value: -"A single decoded observation with dimension values, numeric value, and optional status."New value: +"A single decoded observation with dimension values, numeric value, and the optional OBS_FLAG and CONF_STATUS markers."
    • addedOutput schema / properties / observations / items / properties / confStatus
      Added value: +{
      +  "additionalProperties": false,
      +  "description": "Eurostat CONF_STATUS for this observation — a different codelist from status. Present when Eurostat restricts the cell, which is usually why value is null. Omitted otherwise.",
      +  "properties": {
      +    "code": {
      +      "description": "CONF_STATUS code: \"C\", \"N\", or \"P\".",
      +      "type": "string"
      +    },
      +    "label": {
      +      "description": "Confidentiality description (e.g., \"confidential\", \"not for publication\").",
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "code",
      +    "label"
      +  ],
      +  "type": "object"
      +}
    • changedOutput schema / properties / observations / items / properties / status / description
      Previous value: -"Status flag for this observation. Omitted for normal observations."New value: +"Eurostat OBS_FLAG for this observation. Omitted for unflagged observations, and never carries a confidentiality code — that arrives in confStatus."
    • changedOutput schema / properties / observations / items / properties / status / properties / code / description
      Previous value: -"Status flag code (e.g., \"p\", \"e\", \"d\")."New value: +"OBS_FLAG code (e.g., \"p\", \"e\", \"d\")."
    • changedOutput schema / properties / observations / items / properties / value / description
      Previous value: -"Numeric observation value, or null when missing (flagged as unavailable in the source data)."New value: +"Numeric observation value, or null when Eurostat reports none — either unavailable in the source data or withheld, in which case confStatus says so."
    • changedOutput schema / properties / tableName / description
      Previous value: -"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."New value: +"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, conf_status, conf_status_label. The five measure columns match the ones eurostat_download_dataset stages, so the two tables join on dimension codes and time and compare like with like. Omitted when nothing was staged: either the result fit under the cap, or this deployment runs without a dataframe canvas."
  8. Changed2 schema fields changed
    • changedOutput schema / properties / observations / description
      Previous value: -"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."New value: +"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, or switch to eurostat_download_dataset when the whole dataset is what is wanted."
    • changedOutput schema / properties / truncated / description
      Previous value: -"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."New value: +"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, or downloading the dataset with eurostat_download_dataset, is what brings the rest into reach."
  9. Changed7 schema fields changed
    • addedInput schema / properties / canvas_id
      Added value: +{
      +  "description": "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.",
      +  "type": "string"
      +}
    • addedOutput schema / properties / canvasId
      Added value: +{
      +  "description": "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.",
      +  "type": "string"
      +}
    • changedOutput schema / properties / notice / description
      Previous value: -"Guidance when the result was truncated at 5,000 rows. Omitted for normal results."New value: +"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."
    • changedOutput schema / properties / observations / description
      Previous value: -"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."New value: +"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."
    • addedOutput schema / properties / stagedRowCount
      Added value: +{
      +  "description": "Rows written to the canvas table. Matches obsCount. Omitted alongside tableName when nothing was staged.",
      +  "type": "number"
      +}
    • addedOutput schema / properties / tableName
      Added value: +{
      +  "description": "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.",
      +  "type": "string"
      +}
    • changedOutput schema / properties / truncated / description
      Previous value: -"True when the result exceeded 5,000 observations and was capped. Apply dimension filters to get the full result."New value: +"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."
  10. Changed5 schema fields changed
    • changedOutput schema / properties / missingObsCount / description
      Previous value: -"Number of observations with null value (missing data points in the source)."New value: +"Number of matched observations with null value (missing data points in the source), counted across everything matched rather than only the returned rows."
    • changedOutput schema / properties / observations / description
      Previous value: -"Decoded observations, capped at 5,000 rows. When truncated is true, apply dimension filters to narrow the result."New value: +"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."
    • changedOutput schema / properties / timeRange / description
      Previous value: -"Time coverage of the returned observations. Each bound is omitted when neither the observations nor Eurostat report it — an omitted bound is unknown, not empty."New value: +"Time coverage of everything matched — the same set obsCount counts, so it can reach periods absent from observations when truncated is true. Each bound is omitted when neither the match nor Eurostat report it — an omitted bound is unknown, not empty."
    • changedOutput schema / properties / timeRange / properties / end / description
      Previous value: -"Most recent period in this result. Omitted when the observations carry no time dimension and Eurostat reports no overall period."New value: +"Most recent period matched. Omitted when the match carries no time dimension and Eurostat reports no overall period."
    • changedOutput schema / properties / timeRange / properties / start / description
      Previous value: -"Earliest period in this result. Omitted when the observations carry no time dimension and Eurostat reports no overall period."New value: +"Earliest period matched. Omitted when the match carries no time dimension and Eurostat reports no overall period."
  11. Changed6 schema fields changed
    • changedInput schema / properties / filters / description
      Previous value: -"Dimension filters as a map of dimension code → array of valid values. Example: {\"unit\": [\"CP_MEUR\"], \"na_item\": [\"B1GQ\"], \"geo\": [\"DE\", \"FR\"]}. Do not include \"geo\" here if using geo_level. Invalid dimension values silently return no data — verify with eurostat_get_dimension_values first."New value: +"Dimension filters as a map of dimension code → array of valid values. Example: {\"unit\": [\"CP_MEUR\"], \"na_item\": [\"B1GQ\"], \"geo\": [\"DE\", \"FR\"]}. An empty array is treated as no filter for that dimension and is dropped from the request. Do not include \"geo\" here if using geo_level. Invalid dimension values silently return no data — verify with eurostat_get_dimension_values first."
    • changedOutput schema / properties / appliedFilters / properties / filters / description
      Previous value: -"Dimension filters that were applied."New value: +"Dimension filters actually sent to Eurostat. Empty arrays from the request are dropped and do not appear here."
    • changedOutput schema / properties / timeRange / description
      Previous value: -"Time coverage of the returned observations."New value: +"Time coverage of the returned observations. Each bound is omitted when neither the observations nor Eurostat report it — an omitted bound is unknown, not empty."
    • changedOutput schema / properties / timeRange / properties / end / description
      Previous value: -"Most recent period in this result."New value: +"Most recent period in this result. Omitted when the observations carry no time dimension and Eurostat reports no overall period."
    • changedOutput schema / properties / timeRange / properties / start / description
      Previous value: -"Earliest period in this result."New value: +"Earliest period in this result. Omitted when the observations carry no time dimension and Eurostat reports no overall period."
    • removedOutput schema / properties / timeRange / required
      Removed value: -[
      -  "start",
      -  "end"
      -]
  12. Changed3 schema fields changed
    • addedOutput schema / properties / appliedFilters
      Added value: +{
      +  "additionalProperties": false,
      +  "description": "Effective query parameters applied to the Eurostat API.",
      +  "properties": {
      +    "filters": {
      +      "additionalProperties": {
      +        "items": {
      +          "type": "string"
      +        },
      +        "type": "array"
      +      },
      +      "description": "Dimension filters that were applied.",
      +      "propertyNames": {
      +        "type": "string"
      +      },
      +      "type": "object"
      +    },
      +    "geoLevel": {
      +      "description": "NUTS geo level filter applied, if any.",
      +      "type": "string"
      +    },
      +    "lastNPeriods": {
      +      "description": "Last N periods filter applied, if any.",
      +      "type": "number"
      +    },
      +    "sincePeriod": {
      +      "description": "Start of time range applied, if any.",
      +      "type": "string"
      +    },
      +    "untilPeriod": {
      +      "description": "End of time range applied, if any.",
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "filters"
      +  ],
      +  "type": "object"
      +}
    • addedOutput schema / properties / notice
      Added value: +{
      +  "description": "Guidance when the result was truncated at 5,000 rows. Omitted for normal results.",
      +  "type": "string"
      +}
    • changedOutput schema / required
      Previous value: -[
      -  "datasetCode",
      -  "datasetLabel",
      -  "dimensionsUsed",
      -  "observations",
      -  "obsCount",
      -  "truncated",
      -  "timeRange",
      -  "missingObsCount"
      -]New value: +[
      +  "datasetCode",
      +  "datasetLabel",
      +  "dimensionsUsed",
      +  "observations",
      +  "obsCount",
      +  "truncated",
      +  "timeRange",
      +  "missingObsCount",
      +  "appliedFilters"
      +]
  13. Changed4 schema fields changed
    • changedOutput schema / properties / obsCount / description
      Previous value: -"Number of observations returned."New value: +"Total number of observations matched (before any cap)."
    • changedOutput schema / properties / observations / description
      Previous value: -"Decoded observations. Each entry has one dimension entry per dimension in dimensionsUsed, plus value and optional status."New value: +"Decoded observations, capped at 5,000 rows. When truncated is true, apply dimension filters to narrow the result."
    • addedOutput schema / properties / truncated
      Added value: +{
      +  "description": "True when the result exceeded 5,000 observations and was capped. Apply dimension filters to get the full result.",
      +  "type": "boolean"
      +}
    • changedOutput schema / required
      Previous value: -[
      -  "datasetCode",
      -  "datasetLabel",
      -  "dimensionsUsed",
      -  "observations",
      -  "obsCount",
      -  "timeRange",
      -  "missingObsCount"
      -]New value: +[
      +  "datasetCode",
      +  "datasetLabel",
      +  "dimensionsUsed",
      +  "observations",
      +  "obsCount",
      +  "truncated",
      +  "timeRange",
      +  "missingObsCount"
      +]
  14. First observed

TDQS

A4.6/5.0
Behavior5/5

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

Beyond the readOnly/idempotent annotations, the description discloses the deterministic inline prefix, OBS_FLAG and CONF_STATUS semantics, the fact that preview_limit only affects the prefix, the 5,000-observation staging threshold, and the possibility of async response errors. This adds substantial behavioral context without contradicting annotations.

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

Conciseness4/5

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

The description is dense but well front-loaded: purpose and return contract appear immediately, followed by workflow and routing guidance. Some sentences repeat schema details, but the staging threshold, async error warning, and sibling alternates justify their presence.

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?

With 9 parameters, an output schema, and annotations present, the description still adds the missing workflow context: how to discover valid filters, how to avoid large-query failures, what happens at the 5,000 threshold, and when to prefer a sibling tool. An agent has what it needs to use the tool correctly.

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

Parameters3/5

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

Schema description coverage is 100%, so the schema already carries detailed parameter meaning. The description reinforces key semantics such as preview_limit only controlling the prefix and geo/geo_level mutual exclusivity, but it does not materially add parameter-level information beyond what the schema already provides.

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?

First sentence states a specific verb, resource, and mechanism: 'Fetch statistical data from a Eurostat dataset with dimension filters.' It also distinguishes this tool from eurostat_download_dataset by naming the whole-dataset alternative, so an agent can tell them apart.

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?

The description gives explicit routing: call eurostat_get_dataset_info first, apply filters to avoid async errors, use filters.geo vs geo_level, use last_n_periods without knowing the end date, and switch to eurostat_dataframe_describe/query or eurostat_download_dataset under specific conditions. Named alternatives and clear conditions make this very actionable.

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.