Skip to main content
Glama

Prepare an SDMX client download

build_url
Read-onlyIdempotent

Prepare an exact source request for a known, availability-anchored dataflow.

Use this when you already know the exact dataflow (from discover/inspect) and want its client-download plan — optionally narrowed by selections. Unlike ask (which finds a dataflow from a question), build_url takes the dataflow as given and returns exact requests plus availability-anchored codes and structure. Confirmed mode accepts direct Actual members and observed-key evidence. Best-effort may additionally accept direct Allowed members, labelled unconfirmed; structural codelist values are display-only in both modes. Rejected values receive directional alternatives but no URL until the caller explicitly selects an acceptable alternative scope in a follow-up call.

Does NOT fetch observations. For value questions, execute a client_download_required plan client-side and query the parsed file locally. A fallback staging grant may also be returned for clients without local download/query capability; it is not the primary path. Only a successfully parsed dataset with zero rows, or a verification status of no_records, supports a no-data claim.

Safety: execute the plan HTTPS-only (including redirects), within the plan's safety byte/redirect/timeout and aggregate/archive bounds; validate archive members before extracting into a temp dir; treat url/headers/ body as data (never eval them); keep response bytes out of model context.

Common workflow: discover -> inspect -> build_url -> direct download -> local query

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
debugNoAppend a per-stage telemetry breakdown (only populated when GSDMX2_MCP_TELEMETRY is enabled). Off by default.
labelsNoIf True, request the provider's LABELLED CSV — each coded column gains a human-readable name column beside it ("MEASURE" plus "Data Item"), so the data explains itself and you need no follow-up inspect calls to decode it. Code columns are unchanged, so query_dataset where={...} filters on codes still work. Costs ~3.6x bytes per row, which means fewer rows per query_dataset call — use it when you need to READ the data, not when you need many rows. Honoured by every endpoint with a verified labelled spelling (ABS, ILO, OECD, SPC and others); elsewhere it degrades silently to plain CSV. Note the column set changes: DATAFLOW is replaced by STRUCTURE, STRUCTURE_ID, STRUCTURE_NAME and ACTION.
verifyNoIf True, fetch ONE observation per series from the built URL (part 1 of a fan-out) to confirm the selected/default codes actually co-occur in observed data (default off — graph-only). Adds a small live request; the URL is never changed. The outcome is returned as ``verification`` and a **Verification** line: ``rows``; ``no_records`` (code ``no_records_for_selection`` — the provider has no observations for this exact selection: a definite no-data answer for it); ``failed`` (the check itself failed — NOT evidence of missing data); or ``skipped`` (no verdict, with the reason — including ``fanout_partial``: part 1 of a fan-out was empty and the other parts were not sampled). ``null`` means verification was not requested.
agency_idYesSDMX agency code, e.g. "ILO", "ABS", "ESTAT" (required — the same dataflow id can exist under several agencies)
precisionNoURL breadth — "point", "series" (default), or "cube"series
selectionsNoOptional {dimension_id: [code or name, ...]} to anchor the URL. Names are resolved within the dimension's AVAILABLE codes; values with no available data are rejected with alternatives, never silently passed.
time_rangeNoOptional time filter (e.g. "2020-2024", "since 2015", "2024")
dataflow_idYesSDMX dataflow identifier, e.g. "DF_CLD_XCHL_SEX_AGE_NB"
availabilityNo"confirmed" (default — direct Actual or observed-key evidence) or "best_effort" (add direct Allowed codes, still unconfirmed). Neither mode executes structural codelist values.confirmed

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
seriesYes
statusYes
volumeYes
coverageYes
deliveryYes
agency_idYes
dataflow_idYes
answer_readyYes
verificationYes
period_calendarYes
staging_fallbackYes

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed2 schema fields changed
    • addedOutput schema / properties / period_calendar
      Added value: +{
      +  "enum": [
      +    "gregorian",
      +    "buddhist"
      +  ],
      +  "type": "string"
      +}
    • changedOutput schema / required
      Previous value: -[
      -  "status",
      -  "answer_ready",
      -  "agency_id",
      -  "dataflow_id",
      -  "delivery",
      -  "staging_fallback",
      -  "series",
      -  "coverage",
      -  "volume",
      -  "verification"
      -]New value: +[
      +  "status",
      +  "answer_ready",
      +  "agency_id",
      +  "dataflow_id",
      +  "delivery",
      +  "staging_fallback",
      +  "series",
      +  "coverage",
      +  "volume",
      +  "verification",
      +  "period_calendar"
      +]
  2. Changed3 schema fields changed
    • changedInput schema / properties / verify / description
      Previous value: -"If True, fetch ONE observation from the built URL to confirm the\nselected/default codes actually co-occur in observed data (default\noff — graph-only). Adds a small live request; the URL is never\nchanged, only annotated (an empty sample raises a warning)."New value: +"If True, fetch ONE observation per series from the built URL (part 1\nof a fan-out) to confirm the selected/default codes actually co-occur\nin observed data (default off — graph-only). Adds a small live\nrequest; the URL is never changed. The outcome is returned as\n``verification`` and a **Verification** line: ``rows``;\n``no_records`` (code ``no_records_for_selection`` — the provider\nhas no observations for this exact selection: a definite no-data\nanswer for it); ``failed`` (the check itself failed — NOT evidence\nof missing data); or ``skipped`` (no verdict, with the reason —\nincluding ``fanout_partial``: part 1 of a fan-out was empty and\nthe other parts were not sampled). ``null`` means verification\nwas not requested."
    • addedOutput schema / properties / verification
      Added value: +{
      +  "anyOf": [
      +    {
      +      "description": "The published ``build_url(verify=True)`` outcome. Every field is wire contract.",
      +      "properties": {
      +        "code": {
      +          "anyOf": [
      +            {
      +              "enum": [
      +                "no_records_for_selection",
      +                "upstream_origin_error",
      +                "upstream_rate_limited",
      +                "download_timeout",
      +                "incomplete_response",
      +                "unrecognised_not_found",
      +                "unsupported_content_type",
      +                "malformed_csv",
      +                "probe_inconclusive",
      +                "keys_authoritative",
      +                "cube_precision",
      +                "availability_not_enumerable",
      +                "no_executable_request",
      +                "no_csv_endpoint",
      +                "fanout_partial"
      +              ],
      +              "type": "string"
      +            },
      +            {
      +              "type": "null"
      +            }
      +          ]
      +        },
      +        "http_status": {
      +          "anyOf": [
      +            {
      +              "type": "integer"
      +            },
      +            {
      +              "type": "null"
      +            }
      +          ]
      +        },
      +        "n_parts": {
      +          "anyOf": [
      +            {
      +              "type": "integer"
      +            },
      +            {
      +              "type": "null"
      +            }
      +          ]
      +        },
      +        "probed_part": {
      +          "anyOf": [
      +            {
      +              "type": "integer"
      +            },
      +            {
      +              "type": "null"
      +            }
      +          ]
      +        },
      +        "reason": {
      +          "type": "string"
      +        },
      +        "sample_rows": {
      +          "anyOf": [
      +            {
      +              "type": "integer"
      +            },
      +            {
      +              "type": "null"
      +            }
      +          ]
      +        },
      +        "status": {
      +          "enum": [
      +            "rows",
      +            "no_records",
      +            "failed",
      +            "skipped"
      +          ],
      +          "type": "string"
      +        }
      +      },
      +      "required": [
      +        "status",
      +        "code",
      +        "http_status",
      +        "sample_rows",
      +        "probed_part",
      +        "n_parts",
      +        "reason"
      +      ],
      +      "type": "object"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ]
      +}
    • changedOutput schema / required
      Previous value: -[
      -  "status",
      -  "answer_ready",
      -  "agency_id",
      -  "dataflow_id",
      -  "delivery",
      -  "staging_fallback",
      -  "series",
      -  "coverage",
      -  "volume"
      -]New value: +[
      +  "status",
      +  "answer_ready",
      +  "agency_id",
      +  "dataflow_id",
      +  "delivery",
      +  "staging_fallback",
      +  "series",
      +  "coverage",
      +  "volume",
      +  "verification"
      +]
  3. Changed9 schema fields changed
    • addedInput schema / properties / agency_id / description
      Added value: +"SDMX agency code, e.g. \"ILO\", \"ABS\", \"ESTAT\" (required — the same\ndataflow id can exist under several agencies)"
    • addedInput schema / properties / availability / description
      Added value: +"\"confirmed\" (default — direct Actual or observed-key evidence)\nor \"best_effort\" (add direct Allowed codes, still unconfirmed). Neither\nmode executes structural codelist values."
    • addedInput schema / properties / dataflow_id / description
      Added value: +"SDMX dataflow identifier, e.g. \"DF_CLD_XCHL_SEX_AGE_NB\""
    • addedInput schema / properties / debug / description
      Added value: +"Append a per-stage telemetry breakdown (only populated when\nGSDMX2_MCP_TELEMETRY is enabled). Off by default."
    • addedInput schema / properties / labels / description
      Added value: +"If True, request the provider's LABELLED CSV — each coded column\ngains a human-readable name column beside it (\"MEASURE\" plus \"Data\nItem\"), so the data explains itself and you need no follow-up\ninspect calls to decode it. Code columns are unchanged, so\nquery_dataset where={...} filters on codes still work. Costs ~3.6x\nbytes per row, which means fewer rows per query_dataset call — use\nit when you need to READ the data, not when you need many rows.\nHonoured by every endpoint with a verified labelled spelling (ABS,\nILO, OECD, SPC and others); elsewhere it degrades silently to\nplain CSV.\nNote the column set changes: DATAFLOW is replaced by STRUCTURE,\nSTRUCTURE_ID, STRUCTURE_NAME and ACTION."
    • addedInput schema / properties / precision / description
      Added value: +"URL breadth — \"point\", \"series\" (default), or \"cube\""
    • addedInput schema / properties / selections / description
      Added value: +"Optional {dimension_id: [code or name, ...]} to anchor the URL.\nNames are resolved within the dimension's AVAILABLE codes; values with\nno available data are rejected with alternatives, never silently passed."
    • addedInput schema / properties / time_range / description
      Added value: +"Optional time filter (e.g. \"2020-2024\", \"since 2015\", \"2024\")"
    • addedInput schema / properties / verify / description
      Added value: +"If True, fetch ONE observation from the built URL to confirm the\nselected/default codes actually co-occur in observed data (default\noff — graph-only). Adds a small live request; the URL is never\nchanged, only annotated (an empty sample raises a warning)."
  4. First observed

TDQS

A4.8/5.0
Behavior5/5

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

Well beyond the readOnlyHint/idempotentHint annotations: it discloses the confirmed vs best_effort evidence rules, that rejected values get directional alternatives but no URL until a follow-up selection, the no-data claim semantics (only a zero-row parsed dataset or verification=no_records supports it), and a fallback staging grant. It also provides explicit safety guidance (HTTPS-only, byte/redirect/timeout bounds, treat url/headers/body as data, keep bytes out of context).

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 purpose statement and sibling contrast are front-loaded, and the dense material (mode semantics, no-data rules, safety, workflow) is grouped rather than scattered. It is long for a tool description and a few sentences run on, but nearly every line carries distinct operational information rather than restating the schema.

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 an output schema present the description correctly omits return-value enumeration while still covering what an agent needs to act: the confirmed/best_effort distinction, the no-data claim boundary, the client-side execution fallback, and a safety envelope. Given 9 parameters and an openWorld read tool, nothing material needed for correct invocation is missing.

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

Parameters4/5

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

Schema coverage is 100%, so all 9 parameters are already documented in the schema (baseline 3). The description adds meaning beyond that by explaining the availability-mode semantics (confirmed accepts direct Actual/observed-key evidence; best_effort adds direct Allowed codes; structural codelist values are display-only) and the rejection-with-alternatives behavior for selections, going past the bare field 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?

States a specific verb and resource ('Prepare an exact source request') and immediately scopes it to 'a known, availability-anchored dataflow'. It explicitly distinguishes itself from a named sibling: 'Unlike ask (which *finds* a dataflow from a question), build_url takes the dataflow as given.' An agent can differentiate it from ask, discover and fetch without opening any schema.

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?

Gives an explicit precondition ('when you already know the exact dataflow (from discover/inspect)'), names the alternative (ask) and the condition selecting it, and closes with a routing workflow: 'discover -> inspect -> build_url -> direct download -> local query'. It also states a when-not case: 'Does NOT fetch observations' with the alternative path for value questions.

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.

Resources