Skip to main content
Glama

sdmx-data-mcp

PyPI Python CI Licence

An MCP server that lets an AI assistant discover and retrieve official statistics from SDMX services.

Built on the BIS's own pysdmx library.

Why this exists

Other SDMX MCP servers navigate metadata well and then hand back a query URL. The assistant ends up with a link, not numbers — and cannot answer the question it was asked.

sdmx-data-mcp finishes the job. get_data returns the observations.

Related MCP server: Countries MCP Server

Quick start

pip install sdmx-data-mcp

Then register it with your client:

claude mcp add sdmx -- sdmx-data-mcp

That is the whole setup. Ask your assistant something like "what is the Swiss policy rate since 2020?" and it will find the dataflow, check what it can filter on, and come back with the actual series.

Claude Desktop — in claude_desktop_config.json:

{
  "mcpServers": {
    "sdmx": {
      "command": "sdmx-data-mcp"
    }
  }
}

Cursor — in .cursor/mcp.json:

{
  "mcpServers": {
    "sdmx": {
      "command": "sdmx-data-mcp"
    }
  }
}

If sdmx-data-mcp is not on your PATH, use the absolute path to the executable, or "command": "python", "args": ["-m", "sdmx_data_mcp"].

Over HTTP, to share one instance:

sdmx-data-mcp --transport http --host 127.0.0.1 --port 8000

The four tools

Meant to be called in order. Only the last one moves data.

Tool

Purpose

list_services

Known endpoints, plus any SDMX-REST v2 base URL you supply

search_dataflows

One dataflows() call, then local term matching

inspect_dataflow

Components, available codes, size signals

get_data

Retrieves the observations

A real session

Transcripts below are actual tool output, not illustrations. More in docs/EXAMPLES.md.

1. Find the dataflow

search_dataflows(query="policy rate central bank")

{
  "search_terms": ["policy", "rate", "central", "bank"],
  "total_dataflows_on_service": 32,
  "match_count": 12,
  "dataflows": [
    { "ref": "BIS:WS_CBPOL(1.0)", "name": "Central bank policy rates",
      "matched_on": "name" },
    { "ref": "BIS:WS_CBS_PUB(1.0)", "name": "Consolidated banking",
      "matched_on": "name" }
    // ...
  ]
}

One request to the service; the terms are matched locally. Searching for synonyms costs nothing extra, so put them all in one query.

2. See what you can filter on

inspect_dataflow(ref="BIS:WS_CBPOL(1.0)", find_code="CH")

{
  "series_count": 98,
  "obs_count": null,          // BIS does not report this
  "size_warning": null,       // small enough to retrieve
  "dimensions": [
    { "id": "FREQ", "name": "Frequency", "code_count": 2,
      "codes": [{"id": "D", "name": "Daily"}, {"id": "M", "name": "Monthly"}] },
    { "id": "REF_AREA", "name": "Reference area", "code_count": 49,
      "codes": [ /* ... */ {"id": "CH", "name": "Switzerland"} /* ... */ ] }
  ]
}

3. Get the numbers

get_data(
  ref="BIS:WS_CBPOL(1.0)",
  filters="FREQ = 'M' AND REF_AREA = 'CH' AND TIME_PERIOD >= '2020-01'",
  columns=["OBS_VALUE"],
)

{
  "filter_applied": "FREQ = 'M' AND REF_AREA = 'CH' AND TIME_PERIOD >= '2020-01'",
  "filter_fallback": null,
  "row_count": 79,
  "total_rows_available": 79,
  "truncated": false,
  "records": [
    {"SERIES_KEY": "M.CH", "OBS_VALUE": "-0.75", "TIME_PERIOD": "2020-01"},
    {"SERIES_KEY": "M.CH", "OBS_VALUE": "-0.75", "TIME_PERIOD": "2020-02"}
    // ...
  ],
  "next_step": "Complete: all 79 matching rows were returned. Safe to aggregate."
}

truncated: false and row_count == total_rows_available, so this really is the whole series and it is safe to average or chart.

Several values of one component

The query parser accepts AND but not OR. Use IN (...):

get_data(
  ref="BIS:WS_XRU(1.0)",
  filters="FREQ = 'M' AND CURRENCY IN ('CHF', 'KES') AND TIME_PERIOD >= '2026-01'",
  columns=["OBS_VALUE"],
)

{ "row_count": 14, "truncated": false, "records": [
  {"SERIES_KEY": "M.CH.CHF.E", "OBS_VALUE": "0.768269", "TIME_PERIOD": "2026-01"},
  {"SERIES_KEY": "M.KE.KES.A", "OBS_VALUE": "129.126615", "TIME_PERIOD": "2025-12"}
  // ...
] }

With both legs retrieved, an assistant can compute what neither service publishes — a CHF/KES cross rate — and correctly note that the newest period the two currencies share is December 2025, because KES lags CHF.

What the server enforces

These rules are handled by the server rather than left for the assistant to remember. Each one prevents a specific class of confidently wrong answer.

Conjunctions only. AND between clauses, never OR. Several values of one component use IN ('A', 'B').

Availability is not validity. inspect_dataflow reports codes for which data currently exist. A code missing from that list may still be valid in the full codelist, so its absence is never reported as proof that something does not exist.

Ambiguous codes are surfaced, not guessed. On BIS consolidated banking, CH is available in three components at once — reporting country, counterparty country, and a bank type that happens to share the country codelist:

inspect_dataflow(ref="BIS:WS_CBS_PUB(1.0)", find_code="CH")

{ "code_locations": [
    {"component_id": "L_REP_CTY",     "role_hint": "reporting country"},
    {"component_id": "CBS_BANK_TYPE", "role_hint": "bank type (shares a country codelist)"},
    {"component_id": "L_CP_COUNTRY",  "role_hint": "counterparty country"}
  ],
  "next_step": "That code is ambiguous - it appears in 3 components ..." }

Claims by Swiss banks and claims on Switzerland are different questions. The server makes the assistant choose rather than silently pick one.

Size before retrieval. obs_count is frequently unreported — the BIS returns null for it on both full and filtered scopes — so series_count is the signal relied on. A size_warning appears when retrieval would truncate.

Truncation is not sampling. When truncated is true, the rows are the first N in service order, and next_step says so explicitly:

Truncated: 112,648 rows matched but only 500 were returned. These are the first rows in service order, not a sample — do not compute totals or averages from them.

Time filters degrade gracefully. TIME_PERIOD is pushed down to the service first. On a client-side rejection the clause is stripped, the narrower query is retried, and the cutoff is applied with pandas — reported in filter_fallback. It deliberately does not fall back on NotFound, Unavailable or InternalError, where dropping a clause cannot help and would only obscure the real error.

Errors keep their meaning. The pysdmx error hierarchy is preserved rather than flattened, so an assistant can tell a transient outage from a bad reference instead of retrying blindly or giving up too early:

[internal_error] Unexpected message format - The payload could not be
deserialized. | retriable=false | next_step: The service failed, or returned a
response that could not be parsed. Do not repeat the identical call - narrow
the filter or try a different dataflow, since the fault is server-side.

Kind

Retriable

Means

unavailable

yes

Service unreachable; retry after a delay

retriable_error

yes

Transient failure

not_found

no

Resource does not exist; do not repeat

invalid_request

no

Malformed filter; check syntax and code IDs

unauthorized

no

Credentials rejected

not_implemented

no

Service lacks the required API

internal_error

no

Server-side fault; narrow or change the query

unexpected_error

no

Bug in this server; please report it

Services

pysdmx.api.dc.Endpoints currently ships exactly one endpoint, the BIS. Every tool therefore takes a service argument accepting any SDMX-REST v2 base URL as a first-class input, not a fallback:

search_dataflows(query="prices", service="https://your-service.org/api/v2")

The service must return structural metadata as SDMX-JSON 2.0.0 and data as SDMX-CSV. Other providers (ECB, OECD, IMF, Eurostat, ILO) are deliberately not hardcoded: each needs verifying against those requirements first, and listing them unverified would invite confident failures.

Development

pip install -e ".[dev]"
ruff format && ruff check && mypy
pytest --cov=sdmx_data_mcp --cov-branch --cov-report=term-missing

162 tests at 100% statement and branch coverage, mypy in strict mode, CI across Linux, Windows and macOS on Python 3.10–3.13.

Most server tests inject a fake connector so every branch is reachable deterministically. A separate end-to-end module drives the real PandasConnector against respx-mocked responses, so drift in URL construction or SDMX-CSV parsing surfaces there.

Relationship to pysdmx

This package depends on pysdmx[data] from PyPI. It does not fork or vendor it, and uses only the public API — PandasConnector, Endpoints and the errors hierarchy.

The same server has also been proposed upstream as bis-med-it/pysdmx#669. This package exists so it is installable today regardless of what happens there.

Licence

Apache-2.0. See LICENSE.

Available Tools

4 tools
get_dataA

Retrieve observations as records. This returns the actual numbers.

Call inspect_dataflow first to confirm component and code IDs and to check the size of what you are about to pull.

If a TIME_PERIOD clause is rejected by the service, it is retried without that clause and the cutoff is applied locally; the response says so in filter_fallback.

Returns: The observations, the filter actually sent, and a truncated flag. When truncated, the rows are the first N in service order and are NOT a representative sample.

Raises: ToolError: If retrieval fails. The message carries a [kind] discriminator and a retry hint.

ParametersJSON Schema
NameRequiredDescriptionDefault
refYesDataflow reference in agency:id(version) form, such as 'BIS:WS_CBS_PUB(1.0)'.
limitNoMaximum rows to return. Defaults to 1000, hard ceiling 10000.
labelsNo'id' returns code IDs (default, and far more compact). 'name' substitutes human-readable names. 'both' gives 'ID: Name'. Leave as 'id' unless names were requested.id
columnsNoComponents to return, such as ['OBS_VALUE']. Omit for all. TIME_PERIOD and SERIES_KEY are added automatically by pysdmx.
filtersNoFilter selecting the data, such as "L_MEASURE = 'S' AND L_REP_CTY = 'CH' AND TIME_PERIOD >= '2020-Q1'". AND only, never OR; use IN ('A', 'B') for several values of one component. Omitting this pulls the whole dataflow and will almost certainly truncate.
serviceNoService name or SDMX-REST v2 base URL.

Output Schema

ParametersJSON Schema
NameRequiredDescription
refYesThe resolved dataflow reference.
columnsYes
recordsYes
serviceYes
next_stepYes
row_countYesRows actually returned.
truncatedYesTrue when total_rows_available exceeded the cap. The returned rows are the first row_count in service order and are NOT a representative sample - narrow the filter for a complete answer.
filter_appliedYesThe filter actually sent to the service, echoed so the caller can verify what was queried.
filter_fallbackNoSet when server-side time pushdown failed and the time constraint was applied locally instead. Names the filter that was sent and the cutoff applied with pandas.
total_rows_availableYesRows matching the filter before the cap was applied.

TDQS

A4.8/5.0
Behavior5/5

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

With no annotations provided, the description carries the full burden. It discloses the fallback behavior for rejected TIME_PERIOD clauses, the truncated flag and that rows are 'NOT a representative sample' when truncated, and the ToolError format with a [kind] discriminator and retry hint. It also notes that TIME_PERIOD and SERIES_KEY are added automatically. This is thorough behavioral disclosure.

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 moderately long but every sentence earns its place. It is front-loaded with the purpose, then proceeds logically to prerequisites, fallback behavior, return info, and error handling. It is structured and does not ramble, though it could be slightly trimmed without losing information.

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, output schema exists, no annotations), the description covers the critical gotchas: prerequisite inspection, fallback behavior, truncation semantics, and error format. It does not need to explain return values because an output schema is present. Nothing essential 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 the baseline is 3. The description adds value by contextualizing the ref and filters parameters—telling the agent to obtain component/code IDs from inspect_dataflow and explaining the consequence of omitting filters. This goes beyond the schema's per-parameter descriptions, hence a 4.

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 'Retrieve observations as records. This returns the actual numbers.' which is a specific verb+resource that clearly distinguishes this from the sibling tools (list_services, search_dataflows, inspect_dataflow). It leaves no ambiguity about what the tool does and its output nature.

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 instructs the agent to 'Call inspect_dataflow first to confirm component and code IDs and to check the size of what you are about to pull.' This is a clear prerequisite and directly routes the agent to the right sibling. It also warns that omitting the filters 'pulls the whole dataflow and will almost certainly truncate,' giving concrete guidance on when to use filters.

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

inspect_dataflowA

Inspect a dataflow's components, available codes and size.

Call this before get_data. It answers three questions: what can I filter on, which codes actually have data, and is this small enough to retrieve?

If you only need to know whether data exist for some subset, pass filters and stop here rather than going on to get_data.

Returns: Components grouped by role, availability-backed codes, and size signals with a warning when retrieval would truncate.

Raises: ToolError: If the dataflow is not found or the request fails.

ParametersJSON Schema
NameRequiredDescriptionDefault
refYesDataflow reference in agency:id(version) form, such as 'BIS:WS_CBS_PUB(1.0)'. Take this from the ref field of search_dataflows. A full SDMX URN also works.
filtersNoOptional filter scoping availability to a subset, such as "L_REP_CTY = 'CH' AND FREQ = 'Q'". AND only, never OR; use IN ('A', 'B') for several values of one component. Supplying this narrows the reported codes and counts to what remains available.
serviceNoService name or SDMX-REST v2 base URL.
find_codeNoOptional code value such as 'CH'. Reports every component whose available codes contain it, and the role each plays. Use this before filtering on a country: the same code often appears in several dimensions with different meanings.

Output Schema

ParametersJSON Schema
NameRequiredDescription
refYesThe resolved dataflow reference.
nameNo
serviceYes
measuresYes
next_stepYes
obs_countNoObservation count. Frequently null - BIS does not report it. Use series_count as the size signal when null.
attributesYes
dimensionsYes
descriptionNo
series_countNo
size_warningNoPresent when the scope is large enough that get_data would truncate. Narrow the filter first.
code_locationsNoPopulated when find_code was supplied: every component whose available codes contain that value, with the role each plays. More than one entry means the value is ambiguous - on BIS consolidated banking 'CH' appears as reporting country, counterparty country and bank type - so choose the intended role before filtering.
filter_appliedNoThe filter used to scope availability, echoed verbatim. Null means availability covers the whole dataflow.
availability_noteYes

TDQS

A4.5/5.0
Behavior4/5

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

With no annotations provided, the description carries the full burden and does a solid job: it discloses the return content, warns about truncation signals, and lists the ToolError condition. It could more explicitly state that the operation is read-only and has no side effects, but 'Inspect' plus the returns/raises structure conveys the essential behavioral profile.

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?

The description is compact, front-loaded with the core purpose, and uses a clear structure with Returns and Raises sections. Each sentence earns its place; the 'three questions' framing is especially efficient because it instantly communicates the tool's decision-making value.

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?

For a 4-parameter inspection tool with an output schema and a richly documented input schema, the description is complete: it states what the tool does, when to call it relative to get_data, what it returns, and when it errors. The sibling relationships are sufficiently covered by the explicit get_data comparison.

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 baseline is 3. The tool description does not add parameter-level meaning beyond the schema, but the schema itself already explains ref format, filter syntax, the IN() alternative, and find_code semantics. The description's reference to 'filters' aligns with the schema but adds no new parameter information.

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 and resource: 'Inspect a dataflow's components, available codes and size.' It further clarifies the tool's role by naming the three questions it answers, distinguishing it from get_data by positioning itself as the pre-retrieval inspection step.

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 explicitly says 'Call this before get_data' and gives a concrete stopping condition: 'If you only need to know whether data exist for some subset, pass filters and stop here rather than going on to get_data.' This gives clear when-to-use guidance and differentiates it from the main sibling alternative.

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

list_servicesA

List the SDMX services this server can query.

Any SDMX-REST v2 base URL also works: pass it as the service argument to any other tool. The service must return structural metadata as SDMX-JSON 2.0.0 and data as SDMX-CSV.

Returns: The known services, with capability notes for each.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
servicesYes
next_stepYes
custom_endpoints_supportedNoEvery tool accepts a 'service' argument holding either a known name or an arbitrary SDMX-REST v2 base URL.

TDQS

A4.4/5.0
Behavior4/5

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

With no annotations, the description carries the full burden. It discloses the tool's behavior (lists services) and explicitly describes the return format ('known services, with capability notes'). It does not mention side effects or permissions, but listing is inherently non-destructive and the return description adds meaningful context, warranting a 4.

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?

The description is extremely concise—two sentences plus a 'Returns:' line—with the core purpose front-loaded. Every sentence adds value: it explains the tool's purpose, notes the service URL flexibility for other tools, and outlines the return. No waste or redundancy.

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

Completeness4/5

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

Given the tool's simplicity (0 params, list operation) and the presence of an output schema, the description covers the essentials: what the tool does and what it returns. It could be more explicit about the possible content of 'capability notes' or how services are discovered, but it is adequate for the agent to use correctly.

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?

The tool has zero parameters and schema coverage is 100% (empty schema). The baseline for 0 params is 4. The description adds context about passing service arguments to other tools, which is helpful for the broader workflow even though it does not directly describe this tool's parameters (none exist).

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 'List the SDMX services this server can query', clearly stating the verb, resource, and scope. It distinguishes itself from siblings like search_dataflows, inspect_dataflow, and get_data, which all focus on data retrieval rather than service enumeration.

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

Usage Guidelines4/5

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

The description implies usage by noting that any SDMX-REST v2 base URL can be passed as a service argument to other tools, which directs the user to this listing tool to discover available services before querying data. However, it does not explicitly state 'use this when you need to see available services' or provide a when-not-to-use rule, leaving some inference to the agent.

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

search_dataflowsA

Find dataflows (datasets) matching a topic.

Issues exactly one request to the service and matches the terms locally, so searching for synonyms costs nothing extra: put them all in one query rather than calling this repeatedly.

Returns: Matching dataflows, each with a ref to pass to the next tool.

Raises: ToolError: If the service is unknown or the request fails. The message carries a [kind] discriminator and a retry hint.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum dataflows to return.
queryNoTopic to search for, such as 'banking' or 'policy rates'. Space-separated words are treated as alternatives and matched case-insensitively against each dataflow's id, name and description. Pass an empty string to list every dataflow.
serviceNoService name from list_services, or an SDMX-REST v2 base URL. Defaults to the pysdmx endpoint.

Output Schema

ParametersJSON Schema
NameRequiredDescription
serviceYes
dataflowsYes
next_stepYes
match_countYes
search_termsYes
total_dataflows_on_serviceYes

TDQS

A4.3/5.0
Behavior4/5

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

With no annotations, the description carries the full burden. It discloses that exactly one request is issued, terms are matched locally, and errors raise ToolError with a [kind] discriminator and retry hint. This goes beyond typical descriptions, though it stops short of covering side effects or permissions—less critical for a read-only search.

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?

The description is compact and well-structured, front-loading the purpose, then behavioral notes, then Returns and Raises sections. Every sentence adds value: the request-count note, the synonym advice, the ref routing hint, and the error format are all useful and not redundant with 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?

Given the tool's relative simplicity, full schema coverage, and the existence of an output schema, the description covers purpose, usage, behavior, return value routing, and error handling. No critical information an agent needs to call it correctly is missing.

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 documents all three parameters thoroughly. The description adds no additional parameter-level detail, but the baseline of 3 applies since the schema does the heavy lifting.

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 'Find dataflows (datasets) matching a topic', which names a specific verb and resource. It is clearly distinct from siblings: search_dataflows searches for dataflows, list_services lists services, inspect_dataflow inspects a single dataflow, and get_data fetches data.

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

Usage Guidelines4/5

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

The description explains when to use the tool (topic search) and gives efficiency guidance: put synonyms in one query because matching is local. It does not explicitly name alternatives or say when not to use it, but the purpose is clear and the returned refs point to the next tool, providing contextual routing.

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

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 4 tool updatesv0.1.0
    • First observedget_data
    • First observedinspect_dataflow
    • First observedlist_services
    • First observedsearch_dataflows

TDQS

A4.6/5.0

Scored across 4 tools

Disambiguation5/5

Each tool maps to a distinct stage of an SDMX query workflow: discovering services, finding dataflows, inspecting a dataflow, and fetching data. There is no overlap in purpose, and the descriptions explicitly position each tool relative to the next.

Naming Consistency5/5

All tool names follow a consistent verb_noun snake_case pattern: list_services, search_dataflows, inspect_dataflow, get_data. The minor singular/plural variation between dataflows and dataflow is natural and does not create confusion.

Tool Count5/5

Four tools is a well-scoped size for a focused SDMX data retrieval server. Each tool is necessary and corresponds to a meaningful step in the pipeline without redundancy or bloat.

Completeness5/5

The tool surface covers the full read-only workflow: discovering available services, locating relevant dataflows, understanding their structure and constraints, and retrieving actual observations. No critical operations are missing for the stated purpose.

Maintenance

ActivitySlowing
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers