imf-mcp-server
Server Details
Query IMF SDMX 3.0 macroeconomic dataflows — WEO, BOP, CPI, exchange rates, 190 countries.
- Status
- Healthy
- Uptime
- 99.9% over 40 days
- Last Tested
- Transport
- Streamable HTTP · MCP 2025-11-25
- URL
- Repository
- cyanheads/imf-mcp-server
- GitHub Stars
- 1
- Server Listing
- imf-mcp-server
TDQS
Scored across 5 tools
Each tool occupies a distinct stage: listing dataflows, inspecting a dataflow's codelists, querying SDMX data, and analyzing staged DataCanvas results. The two query-like tools are clearly separated by one being SDMX key-based and the other being SQL over already-staged tables.
All names share an imf_ prefix and lowercase snake_case, but three are verb_noun (imf_list_databases, imf_get_database, imf_query_dataset) while two invert the order (imf_dataframe_describe, imf_dataframe_query). This is a minor structural inconsistency, though it does not harm readability.
Five tools cover the full pipeline for exploring and querying IMF data without redundancy. This is a well-scoped count for the server's stated purpose.
The tools form a complete read-only workflow: discover dataflows, resolve dimensions/codes, query observations, and run further SQL analysis on large result sets. No obvious lifecycle gaps exist for this domain.
Available Tools
5 toolsimf_dataframe_describeImf Dataframe DescribeARead-onlyIdempotentInspect
List DataCanvas tables and columns staged by a prior imf_query_dataset call. Returns each table's name, row count, and column schema (name + DuckDB type). Required before imf_dataframe_query to discover the table and column names for SQL.
| Name | Required | Description | Default |
|---|---|---|---|
| canvas_id | Yes | Canvas ID returned by imf_query_dataset whenever staged=true, from automatic spillover or output_mode="canvas". |
Output Schema
| Name | Required | Description |
|---|---|---|
| error | No | Present when the call failed. Absent on success. |
| tables | No | All tables registered on this canvas. |
| canvas_id | No | Canvas session ID that was introspected. |
| table_count | No | Total number of tables on the canvas. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and idempotentHint=true, so the safety profile is covered. The description adds meaningful behavioral context by clarifying the dependency on a prior imf_query_dataset call and specifying what is returned (table name, row count, column schema). It does not go into pagination or error behavior, but that is minor given the annotations and output schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no filler: the first states the action and return content, the second states the prerequisite. The most important operational detail (required before imf_dataframe_query) is placed at the end but is still concise and clearly separated from the functional description.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description is complete for an introspection tool: it explains what the tool lists, what the output includes, and why an agent needs it before querying. The output schema exists, annotations cover safety, and the single parameter is fully documented. Nothing critical is missing for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The only parameter, canvas_id, is fully documented in the schema with a description that already explains its origin and valid values. The tool description reinforces the staging context but does not add new parameter-level meaning beyond what the schema provides. Since schema coverage is 100%, the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('List') and identifies the precise resource: DataCanvas tables and columns staged by a prior imf_query_dataset call. It also clearly differentiates this tool from siblings like imf_dataframe_query and imf_query_dataset by framing it as the discovery step for staged data.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use this tool: 'Required before imf_dataframe_query to discover the table and column names for SQL.' This gives the agent a clear prerequisite relationship and tells it why this tool exists in the workflow.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
imf_dataframe_queryImf Dataframe QueryARead-onlyIdempotentInspect
Run a read-only SQL SELECT against a DataCanvas table staged by imf_query_dataset. Supports multi-country comparisons, time-series aggregation, and cross-indicator joins. Requires imf_dataframe_describe first to discover table and column names. One SELECT statement per call; a leading WITH … SELECT (CTE) is accepted. DML and DDL are rejected.
| Name | Required | Description | Default |
|---|---|---|---|
| sql | Yes | Read-only SQL SELECT statement — exactly one statement, starting with SELECT or with a WITH … SELECT common table expression. Reference tables by the names returned by imf_dataframe_describe. Example: SELECT time_period, value FROM spilled_abc123 WHERE time_period >= '2010' ORDER BY time_period. | |
| canvas_id | Yes | Canvas ID returned by imf_query_dataset whenever staged=true. Call imf_dataframe_describe with it before writing SQL. |
Output Schema
| Name | Required | Description |
|---|---|---|
| rows | No | Largest result-row prefix whose complete structured and formatted response fits the 100,000-character response budget, after the canvas row limit (default 10,000) is applied. |
| error | No | Present when the call failed. Absent on success. |
| row_count | No | Number of materialized rows returned in rows. Always equals rows.length and never claims a pre-cap total. |
| truncated | No | True when DataCanvas capped the query at its row limit or the server omitted materialized rows to fit the response-size budget. Page the remainder with a stable ORDER BY plus LIMIT/OFFSET, or narrow the query with WHERE or aggregation. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and idempotentHint=true, and the description goes further by stating exactly what is accepted and rejected: one SELECT or WITH…SELECT, DML and DDL rejection. It also discloses the dependency on imf_dataframe_describe, giving the agent a clear picture of the call's constraints beyond the structured annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four purposeful sentences front-load the core action, then add capabilities, prerequisite, and invocation constraints. No filler or redundancy beyond necessary emphasis; every sentence contributes to correct usage.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the output schema, annotations, and full parameter documentation, the description covers the required workflow, the staged-data source, the prerequisite describe call, and the statement grammar constraints. An agent has enough information to select and invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, with both `sql` and `canvas_id` already documented in detail, including an example SQL statement. The tool description mostly reaffirms these requirements rather than adding new parameter meaning, so the baseline score of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
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: 'Run a read-only SQL SELECT against a DataCanvas table staged by imf_query_dataset.' It clearly distinguishes this from sibling tools by tying it to the staged-table query step and by mentioning capabilities like multi-country comparisons and cross-indicator joins.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides a clear workflow prerequisite: 'Requires imf_dataframe_describe first to discover table and column names.' It also states constraints ('One SELECT statement per call', 'DML and DDL are rejected'), but it does not explicitly contrast with sibling tools such as imf_get_database or imf_list_databases beyond implying the describe-then-query sequence.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
imf_get_databaseImf Get DatabaseARead-onlyIdempotentInspect
Fetch a dataflow's dimension list with a codelist preview for each dimension. Resolves human-readable terms to SDMX codes (e.g. "United States" → USA, "Constant prices" → NGDP_RPCH). Required before imf_query_dataset — SDMX keys are opaque without codelist lookups. Each codelist is capped at the first 50 entries by default, including previews filtered by codelist_filter. Set dimension_id to retrieve one codelist with bounded limit/offset paging after the optional substring filter. Set available_only=true to page codes the dataflow actually publishes, with series and time coverage metadata; availability filtering happens before codelist_filter and paging. The imf://database/{dataflow_id} resource provides the same bounded discovery summary. Country codes are ISO 3-letter (USA, GBR, DEU), not ISO 2-letter (US, GB, DE). The key_format field shows the exact dimension order required by imf_query_dataset. Note: codelists enumerate the code universe, not actual coverage — valid codes can still return no_data if the combination has no series in this dataflow.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Entries to return from the selected dimension. Valid only with dimension_id; default 50, maximum 200. | |
| offset | No | Matching entries to skip in the selected dimension before this page. Valid only with dimension_id; default 0. | |
| version | No | Dataflow version, e.g. 9.0.0. Auto-detected from the dataflow list when omitted. | |
| agency_id | No | Agency ID that publishes this dataflow, e.g. IMF.RES or IMF.STA. Auto-detected from the dataflow list when omitted. | |
| dataflow_id | Yes | Dataflow identifier from imf_list_databases, e.g. WEO, BOP, CPI. Case-sensitive. | |
| dimension_id | No | Exact dimension ID from this tool, e.g. INDICATOR. Select one dimension to page beyond its preview. | |
| available_only | No | Return only codes reported by the dataflow-wide availability constraint. Default false keeps ordinary codelist discovery unchanged. | |
| codelist_filter | No | Optional case-insensitive substring to search within each dimension's codelist (code ID and name). Filtering runs before the 50-entry preview or selected-dimension page. Example: "CPI" or "Constant prices" surfaces matching WEO indicator codes. |
Output Schema
| Name | Required | Description |
|---|---|---|
| name | No | Human-readable dataflow name. |
| error | No | Present when the call failed. Absent on success. |
| notice | No | Populated when a codelist_filter matched no entries anywhere, or when a dimension has no resolvable codelist, or when offset is past the final match. |
| source | No | Attribution string required by IMF data terms: "Source: International Monetary Fund, <dataflow name>, <link>". |
| version | No | Dataflow version string, e.g. 9.0.0. |
| agency_id | No | Agency that publishes this dataflow, e.g. IMF.RES, IMF.STA. |
| truncated | No | True when any returned dimension page omits matching codes. |
| dimensions | No | All dimension previews, or the one selected dimension page. |
| key_format | No | Dimension names in dot-separated keyPosition order, e.g. COUNTRY.INDICATOR.FREQUENCY. Use this exact format when constructing the key for imf_query_dataset. |
| dataflow_id | No | Dataflow identifier, e.g. WEO, BOP, CPI. |
| description | No | This dataflow's own description in full — not the shared DSD's, and not the shortened preview imf_list_databases returns for the same id. Absent when the dataflow publishes none. |
| dsd_version | No | Version of the underlying data structure definition (DSD) that backs this dataflow. Differs from version when the dataflow references a shared DSD (e.g. IIP → DSD_BOP at 24.0.0). |
| dimension_id | No | Selected dimension ID. Absent when previews for every dimension were returned. |
| series_count | No | Total series published by the dataflow. Present when available_only is true. |
| structure_ref | No | Identifier of the underlying DSD, e.g. DSD_BOP. Several dataflows can share one DSD. |
| available_only | No | True when dimensions contain published availability coverage rather than codelists. |
| codelist_filter | No | Echo of the codelist_filter that produced this result. Absent when no filter was applied — an empty codelist then means the codelist could not be resolved, not that the filter missed. |
| time_period_end | No | Latest period with published data, or null when the constraint omits it. |
| time_period_start | No | Earliest period with published data, or null when the constraint omits it. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint/idempotentHint annotations, the description reveals important behavioral traits: codelists are capped at 50 entries, filtering order matters, available_only changes pagination semantics, country codes are ISO 3-letter, and codelists list the code universe rather than actual coverage. This is exactly the kind of non-obvious behavior an agent needs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but every sentence earns its place: primary purpose, why it is needed, default behavior, option-driven behavior, output format hint, and a critical caveat. It is front-loaded with the main purpose and prerequisite relationship, and the caveat at the end prevents a common misuse.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 8 parameters and a meaningful relationship to sibling tools, the description covers the required dataflow_id, optional version/agency auto-detection, dimension paging, availability behavior, filtering semantics, ISO code caveat, and no_data possibility. With an output schema present, nothing essential is missing for an agent to invoke this correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although schema description coverage is 100%, the description adds substantial operational meaning beyond the schema: the 50-entry default cap, the interaction between dimension_id and limit/offset, the filtering order for codelist_filter and available_only, and the key_format field's relevance to imf_query_dataset. These details make parameter behavior significantly clearer.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
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: 'Fetch a dataflow's dimension list with a codelist preview for each dimension.' It clearly distinguishes this tool as the SDMX code-lookup/discovery step and explicitly positions it as 'Required before imf_query_dataset,' which separates it from sibling query and list tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit usage context: this tool is the prerequisite for imf_query_dataset because SDMX keys are opaque without codelist lookups. It also explains when to use dimension_id for one codelist with paging, when to use available_only for actual published coverage, and warns that valid codes can still return no_data—guiding the agent away from incorrect assumptions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
imf_list_databasesImf List DatabasesARead-onlyIdempotentInspect
List IMF SDMX dataflows available on the portal. Entry point for every query: imf_get_database and imf_query_dataset both require a dataflow id obtained here. Vintage (historical snapshot) dataflows such as WEO_2025_OCT_VINTAGE are excluded by default; set include_vintages=true to include them. Results are paged — 50 per call by default, adjustable with limit and offset — and total_count reports how many dataflows matched. Descriptions are shortened here; imf_get_database returns the full text for a single dataflow.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum dataflows to return in this call. Default 50, ceiling 200; total_count reports how many matched, so a partial page is always recognizable as one. | |
| filter | No | Optional name, ID, or description substring to filter results. Case-insensitive. Example: "exchange rate" returns ER and related dataflows. | |
| offset | No | Number of matching dataflows to skip before this page. Combine with limit to page through a broad or unfiltered catalog. | |
| include_vintages | No | Include vintage (historical snapshot) dataflows such as WEO_2025_OCT_VINTAGE. Default false — vintages are excluded to keep the discovery surface clean. |
Output Schema
| Name | Required | Description |
|---|---|---|
| cap | No | The limit that bounded this page. |
| error | No | Present when the call failed. Absent on success. |
| shown | No | Dataflows returned in this page. |
| notice | No | Populated when the filter matches nothing, or when matches remain beyond this page — explains why and names the next offset to request. |
| offset | No | Number of matching dataflows skipped before this page. |
| dataflows | No | This page of matching dataflows; pass the id to imf_get_database to resolve dimension codelists. |
| truncated | No | True when matching dataflows remain beyond this page. |
| total_count | No | Dataflows matching filter and include_vintages, before limit and offset are applied. Exceeds returned_count when more pages remain. |
| returned_count | No | Dataflows in this page — the length of dataflows. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly/openWorld/idempotent annotations, the description discloses default vintage exclusion, the include_vintages escape hatch, paging behavior with default page size, and that descriptions are intentionally shortened. This is substantial behavioral context not visible in the schema or annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Five sentences, all information-dense and front-loaded: purpose, entry-point role, default exclusion behavior, paging, and the distinction from imf_get_database. No filler or repetition of schema details.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present and annotations covering safety, the description still adds the essential operational context: how to obtain IDs for dependent tools, the vintage default, pagination semantics, and total_count availability. Nothing an agent needs to correctly call or interpret this tool is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, and each parameter already has a descriptive schema entry. The description adds some cross-parameter context around paging and total_count, but it does not materially extend the meaning of filter or include_vintages beyond what the schema already provides. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb+resource: 'List IMF SDMX dataflows available on the portal.' It also differentiates itself from siblings by stating that imf_get_database and imf_query_dataset both require a dataflow id obtained here, and that imf_get_database returns full descriptions while this tool returns shortened ones.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly positions the tool as the entry point for every query and names the sibling tools that depend on its output. It also explains when to use the include_vintages parameter and notes that imf_get_database is the alternative for full text, giving clear routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
imf_query_datasetImf Query DatasetARead-onlyIdempotentInspect
Query an IMF SDMX dataflow by dimension key over a time range. Returns observations with time_period, value, and status, plus the unit, scale, and decimals of each series — a key resolving to several series carries one entry per series in series_metadata, since unit and scale differ between them. Requires imf_get_database first to obtain the correct key_format and valid dimension codes. Country codes are ISO 3-letter (USA, GBR, DEU — not US, GB, DE). Key format: dot-separated codes in DSD keyPosition order (e.g. USA.NGDP_RPCH.A for WEO). Every position must carry a code: use + to combine codes (e.g. USA+GBR.NGDP_RPCH.A) and * to match every code at a position (e.g. *.NGDP_RPCH.A for all countries). Codelists from imf_get_database enumerate the code universe, not actual coverage — valid codes can still return no_data if the combination has no series. start_period and end_period must be valid period strings (YYYY, YYYY-SN, YYYY-QN, YYYY-MM, or a calendar-valid YYYY-MM-DD) with start_period no later than end_period; malformed or reversed ranges are rejected. A bound covers the whole period it names, so end_period 2023 includes 2023-M12 and 2023-Q4. Large analytical result sets (multi-country, long time range) spill to DataCanvas; call imf_dataframe_describe first to inspect staged tables and columns, then imf_dataframe_query for SQL analysis.
| Name | Required | Description | Default |
|---|---|---|---|
| key | Yes | Dot-separated dimension codes in DSD keyPosition order. Call imf_get_database to get key_format and valid codes first. Use + to combine codes at one position (e.g. USA+GBR.NGDP_RPCH.A). Use * to match every code at a position — *.NGDP_RPCH.A returns the indicator for all countries, and CAN.*.A every indicator for Canada. Every position needs a code or a *; an empty segment (USA..A) is rejected. Country codes are ISO 3-letter: USA not US, GBR not GB, DEU not DE. | |
| version | No | Dataflow version. Auto-detected from dataflow list when omitted. | |
| agency_id | No | Agency ID, e.g. IMF.RES or IMF.STA. Auto-detected from dataflow list when omitted. | |
| canvas_id | No | Existing canvas ID to accumulate results into across multiple queries. This selects the destination only; it does not force staging. Use output_mode="canvas" to stage an under-budget result. | |
| end_period | No | End of time range (inclusive). Same formats as start_period, and must not be earlier than it. The bound covers the whole period it names, so end_period 2023 admits 2023-M12 and 2023-Q4. Observations after this period are excluded from the result. | |
| dataflow_id | Yes | Dataflow identifier from imf_list_databases, e.g. WEO, BOP, CPI. | |
| output_mode | No | Result placement. auto returns an under-budget result inline and spills only when needed. canvas explicitly stages the full result, using canvas_id when supplied or allocating a fresh canvas. | auto |
| start_period | No | Start of time range (inclusive). Accepts any of YYYY (annual), YYYY-SN (semi-annual, e.g. 2023-S1), YYYY-QN (quarterly, e.g. 2023-Q1), YYYY-MM (monthly), or a calendar-valid YYYY-MM-DD (daily), whatever the dataflow's frequency. The bound covers the whole period it names, so start_period 2023 admits 2023-M01 and 2023-Q1. Observations before this period are excluded from the result. |
Output Schema
| Name | Required | Description |
|---|---|---|
| key | No | Dimension key used in the query, e.g. USA.NGDP_RPCH.A. |
| error | No | Present when the call failed. Absent on success. |
| notice | No | Populated when a period bound was set but some observations carry a time_period label the range filter does not recognize. Composes with staged retrieval_guidance when both apply. |
| source | No | Attribution string required by IMF data terms: "Source: International Monetary Fund, <dataflow name>, <link>". |
| staged | No | True when the complete observation set is stored on DataCanvas. canvas_id and table_name are present whenever true. |
| canvas_id | No | DataCanvas session ID — present when staged=true. Pass first to imf_dataframe_describe, then to imf_dataframe_query. |
| truncated | No | True only when observations is an incomplete preview of observation_count. A result can be staged=true and truncated=false when every observation also fits inline. |
| end_period | No | Latest period covered; absent when the full available range was used. |
| table_name | No | DuckDB table name on the canvas — present when staged=true; reference in SQL via FROM <table_name>. |
| dataflow_id | No | Dataflow identifier that was queried, e.g. WEO. |
| observations | No | Inline observation preview. For staged results this may contain the full set or a budget-limited prefix; observation_count remains the full count. |
| start_period | No | Earliest period covered; absent when the full available range was used. |
| series_metadata | No | Per-series attributes, one entry per distinct series_key in the result. Present only when the query resolved to more than one series; a single-series query carries its values in series_attributes instead. Unit and scale differ across series in one query — WEO NGDPD is USD at scale 9 while NGDP_RPCH is PT unscaled — so interpret each series against its own entry. |
| observation_count | No | Total observations in the result. |
| series_attributes | No | Attributes of the first series in the result — the same series as series_metadata[0]. A key with + or * resolves to several series whose scale and unit differ, and this field describes only the first of them: read series_metadata for the rest, and never apply these values to another series_key. |
| retrieval_guidance | No | Present on every staged result. Identifies the imf_dataframe_describe-before-imf_dataframe_query retrieval workflow. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, openWorldHint, and idempotentHint, so the safety profile is covered. The description adds valuable behavioral context beyond annotations: the key-to-series expansion behavior (one entry per series in series_metadata), the fact that valid codes can still return no_data, the inclusive period-bound semantics, and the spill-to-DataCanvas behavior. It doesn't contradict annotations. A small gap is that it doesn't explicitly state the result is read-only, but the annotations cover that.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but well-organized: it front-loads the core purpose, then covers key format, period semantics, and large-result handling. Every sentence earns its place, though it is long. The structure is logical and the most critical usage constraints (key format, period validation) appear early. Slightly verbose but not wasteful.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (8 params, 2 required, rich key-format rules, period semantics, spill behavior) and the presence of an output schema, the description is complete. It covers prerequisites, key construction, period validation, result expansion, no_data behavior, and the large-result workflow. An agent has everything needed to call it correctly and know what to expect.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 8 parameters thoroughly. The description adds meaning beyond the schema by explaining the key format semantics (dot-separated, + for union, * for wildcard, every position must carry a code), the period-bound inclusivity, and the series_metadata expansion behavior. It reinforces the ISO 3-letter country code requirement. This goes beyond the baseline 3 for full schema coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
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: 'Query an IMF SDMX dataflow by dimension key over a time range.' It clearly distinguishes this from siblings by naming the prerequisite (imf_get_database) and the downstream tools (imf_dataframe_describe/query) for large results. The scope is precise and an agent can tell it apart from imf_list_databases or imf_get_database without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use this tool vs alternatives: it requires imf_get_database first to obtain key_format and valid codes, and it directs large analytical result sets to imf_dataframe_describe then imf_dataframe_query. It also gives concrete examples of key formats and period bounds, so the agent knows exactly when this tool is appropriate and when to hand off.
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.
5 tool updates
- Changed
imf_dataframe_describe2 fields changed- added
Input schema / properties / canvas_id / patternAdded value: +"^[A-Za-z0-9_-]{10}$" - changed
Output schema / properties / error / properties / data / properties / reason / descriptionPrevious value: -"Machine-readable failure mode. Declared by this tool: `canvas_not_found`: canvas_id does not match any registered DataCanvas session (expired, wrong session, or canvas disabled) Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `canvas_not_found`: canvas_id does not match any registered DataCanvas session (expired, wrong session, or canvas disabled). Other values are possible when a failure originates below the handler."
- Changed
imf_dataframe_query2 fields changed- added
Input schema / properties / canvas_id / patternAdded value: +"^[A-Za-z0-9_-]{10}$" - changed
Output schema / properties / error / properties / data / properties / reason / descriptionPrevious value: -"Machine-readable failure mode. Declared by this tool: `canvas_not_found`: canvas_id does not match any registered DataCanvas session (expired, wrong session, or canvas disabled) `missing_table`: The canvas exists but sql references a table that is not staged on it — the table expired, was dropped, or the name is wrong `invalid_sql`: sql is not a single SELECT statement (a leading WITH … SELECT counts as one), or it is SELECT-shaped but fails to prepare — unknown column, unknown function, or a syntax error `sql_not_permitted`: sql parses as a SELECT but the read-only gate refuses it — it calls an external-data or PRAGMA table function, reads a system catalog, or plans an operator outside the read-only allowlist `response_too_large`: The first result row cannot fit in the complete structured and formatted response budget Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `canvas_not_found`: canvas_id does not match any registered DataCanvas session (expired, wrong session, or canvas disabled). `missing_table`: The canvas exists but sql references a table that is not staged on it — the table expired, was dropped, or the name is wrong. `invalid_sql`: sql is not a single SELECT statement (a leading WITH … SELECT counts as one), or it is SELECT-shaped but fails to prepare — unknown column, unknown function, or a syntax error. `sql_not_permitted`: sql parses as a SELECT but the read-only gate refuses it — it calls an external-data or PRAGMA table function, reads a system catalog, or plans an operator outside the read-only allowlist. `response_too_large`: The first result row cannot fit in the complete structured and formatted response budget. Other values are possible when a failure originates below the handler."
- Changed
imf_get_database5 fields changed- changed
Output schema / properties / error / properties / data / properties / reason / descriptionPrevious value: -"Machine-readable failure mode. Declared by this tool: `dataflow_not_found`: dataflow_id does not match any known dataflow on api.imf.org `dimension_not_found`: dimension_id does not match a dimension in the selected dataflow `structure_unavailable`: api.imf.org returns non-200 on the DSD endpoint `dataflow_list_unavailable`: The dataflow catalog that dataflow_id is resolved against could not be fetched — fires before the DSD lookup is attempted `availability_unavailable`: available_only is true and the dataflow-wide availability constraint cannot be fetched or parsed Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `dataflow_not_found`: dataflow_id does not match any known dataflow on api.imf.org. `dimension_not_found`: dimension_id does not match a dimension in the selected dataflow. `structure_unavailable`: api.imf.org returns non-200 on the DSD endpoint. `dataflow_list_unavailable`: The dataflow catalog that dataflow_id is resolved against could not be fetched — fires before the DSD lookup is attempted. `availability_unavailable`: available_only is true and the dataflow-wide availability constraint cannot be fetched or parsed. Other values are possible when a failure originates below the handler." - removed
Output schema / properties / time_period_end / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / time_period_end / typeAdded value: +[ + "string", + "null" +] - removed
Output schema / properties / time_period_start / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / time_period_start / typeAdded value: +[ + "string", + "null" +]
- Changed
imf_list_databases1 field changed- changed
Output schema / properties / error / properties / data / properties / reason / descriptionPrevious value: -"Machine-readable failure mode. Declared by this tool: `dataflow_list_unavailable`: The IMF SDMX structure endpoint that backs the dataflow catalog did not return a usable response Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `dataflow_list_unavailable`: The IMF SDMX structure endpoint that backs the dataflow catalog did not return a usable response. Other values are possible when a failure originates below the handler."
- Changed
imf_query_dataset18 fields changed- added
Input schema / properties / canvas_id / patternAdded value: +"^[A-Za-z0-9_-]{10}$" - changed
Output schema / properties / error / properties / data / properties / reason / descriptionPrevious value: -"Machine-readable failure mode. Declared by this tool: `dataflow_not_found`: dataflow_id does not match any known dataflow on api.imf.org `no_data`: Key is structurally valid but the dataflow holds no series for this code combination, or the dataflow publishes no series at all `no_data_in_range`: The key returned observations but start_period/end_period excluded every one of them `key_dimension_mismatch`: Number of dot-separated segments in key does not match the dataflow's DSD dimension count `empty_key_segment`: A dot-separated position in key is empty or blank, which matches no series upstream `invalid_period_format`: start_period or end_period is not one of the recognized period formats `invalid_period_range`: start_period is later than end_period `structure_unavailable`: The dataflow structure (DSD) cannot be fetched after the dataflow catalog resolved successfully `canvas_unavailable`: output_mode=\"canvas\" was requested but DataCanvas is disabled `response_too_large`: Fixed staged-result metadata exceeds the response budget before any observation preview can be included `dataflow_list_unavailable`: The dataflow catalog that dataflow_id is resolved against could not be fetched — fires before the DSD and data lookups are attempted Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `dataflow_not_found`: dataflow_id does not match any known dataflow on api.imf.org. `no_data`: Key is structurally valid but the dataflow holds no series for this code combination, or the dataflow publishes no series at all. `no_data_in_range`: The key returned observations but start_period/end_period excluded every one of them. `key_dimension_mismatch`: Number of dot-separated segments in key does not match the dataflow's DSD dimension count. `empty_key_segment`: A dot-separated position in key is empty or blank, which matches no series upstream. `invalid_period_format`: start_period or end_period is not one of the recognized period formats. `invalid_period_range`: start_period is later than end_period. `structure_unavailable`: The dataflow structure (DSD) cannot be fetched after the dataflow catalog resolved successfully. `canvas_unavailable`: output_mode=\"canvas\" was requested but DataCanvas is disabled. `response_too_large`: Fixed staged-result metadata exceeds the response budget before any observation preview can be included. `dataflow_list_unavailable`: The dataflow catalog that dataflow_id is resolved against could not be fetched — fires before the DSD and data lookups are attempted. Other values are possible when a failure originates below the handler." - removed
Output schema / properties / observations / items / properties / status / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / observations / items / properties / status / typeAdded value: +[ + "string", + "null" +] - removed
Output schema / properties / observations / items / properties / value / anyOfRemoved value: -[ - { - "type": "number" - }, - { - "type": "null" - } -] - added
Output schema / properties / observations / items / properties / value / typeAdded value: +[ + "number", + "null" +] - removed
Output schema / properties / series_attributes / properties / decimals / anyOfRemoved value: -[ - { - "type": "number" - }, - { - "type": "null" - } -] - added
Output schema / properties / series_attributes / properties / decimals / typeAdded value: +[ + "number", + "null" +] - removed
Output schema / properties / series_attributes / properties / scale / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / series_attributes / properties / scale / typeAdded value: +[ + "string", + "null" +] - removed
Output schema / properties / series_attributes / properties / unit / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / series_attributes / properties / unit / typeAdded value: +[ + "string", + "null" +] - removed
Output schema / properties / series_metadata / items / properties / decimals / anyOfRemoved value: -[ - { - "type": "number" - }, - { - "type": "null" - } -] - added
Output schema / properties / series_metadata / items / properties / decimals / typeAdded value: +[ + "number", + "null" +] - removed
Output schema / properties / series_metadata / items / properties / scale / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / series_metadata / items / properties / scale / typeAdded value: +[ + "string", + "null" +] - removed
Output schema / properties / series_metadata / items / properties / unit / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / series_metadata / items / properties / unit / typeAdded value: +[ + "string", + "null" +]
2 tool updates
- Changed
imf_get_database11 fields changed- added
Input schema / properties / available_onlyAdded value: +{ + "default": false, + "description": "Return only codes reported by the dataflow-wide availability constraint. Default false keeps ordinary codelist discovery unchanged.", + "type": "boolean" +} - added
Output schema / properties / available_onlyAdded value: +{ + "const": true, + "description": "True when dimensions contain published availability coverage rather than codelists.", + "type": "boolean" +} - changed
Output schema / properties / dimensions / items / descriptionPrevious value: -"A single dimension with its codelist."New value: +"A single dimension with its codelist or published availability coverage." - added
Output schema / properties / dimensions / items / properties / available_countAdded value: +{ + "description": "Codes reported with published data before codelist_filter. Present when available_only is true.", + "type": "number" +} - changed
Output schema / properties / dimensions / items / properties / codelist / descriptionPrevious value: -"Valid codes for this dimension. Unselected previews show up to 50 entries after optional filtering. Select dimension_id and use limit/offset for a bounded page of up to 200 entries. Empty means the filter matched nothing when codelist_filter is echoed back, and that the codelist could not be resolved when it is not — see notice."New value: +"Valid codelist codes for this dimension, or codes reported with published data when available_only is true. Unselected previews show up to 50 entries after optional filtering. Select dimension_id and use limit/offset for a bounded page of up to 200 entries. Empty means the filter matched nothing when codelist_filter is echoed back, no coverage was reported in availability mode, or the codelist could not be resolved in normal mode — see notice." - changed
Output schema / properties / dimensions / items / properties / unfiltered_count / descriptionPrevious value: -"Codes in the complete resolved codelist before codelist_filter is applied."New value: +"Source codes before codelist_filter: the complete resolved codelist normally, or published codes when available_only is true." - changed
Output schema / properties / error / properties / data / properties / reason / descriptionPrevious value: -"Machine-readable failure mode. Declared by this tool: `dataflow_not_found`: dataflow_id does not match any known dataflow on api.imf.org `dimension_not_found`: dimension_id does not match a dimension in the selected dataflow `structure_unavailable`: api.imf.org returns non-200 on the DSD endpoint `dataflow_list_unavailable`: The dataflow catalog that dataflow_id is resolved against could not be fetched — fires before the DSD lookup is attempted Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `dataflow_not_found`: dataflow_id does not match any known dataflow on api.imf.org `dimension_not_found`: dimension_id does not match a dimension in the selected dataflow `structure_unavailable`: api.imf.org returns non-200 on the DSD endpoint `dataflow_list_unavailable`: The dataflow catalog that dataflow_id is resolved against could not be fetched — fires before the DSD lookup is attempted `availability_unavailable`: available_only is true and the dataflow-wide availability constraint cannot be fetched or parsed Other values are possible when a failure originates below the handler." - changed
Output schema / properties / error / properties / data / properties / reason / examplesPrevious value: -[ - "dataflow_not_found", - "dimension_not_found", - "structure_unavailable", - "dataflow_list_unavailable" -]New value: +[ + "dataflow_not_found", + "dimension_not_found", + "structure_unavailable", + "dataflow_list_unavailable", + "availability_unavailable" +] - added
Output schema / properties / series_countAdded value: +{ + "description": "Total series published by the dataflow. Present when available_only is true.", + "type": "number" +} - added
Output schema / properties / time_period_endAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Latest period with published data, or null when the constraint omits it." +} - added
Output schema / properties / time_period_startAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Earliest period with published data, or null when the constraint omits it." +}
- Changed
imf_list_databases1 field changed- added
Input schema / properties / filter / minLengthAdded value: +1
1 tool update
- Changed
imf_dataframe_query5 fields changed- changed
Output schema / properties / error / properties / data / properties / reason / descriptionPrevious value: -"Machine-readable failure mode. Declared by this tool: `canvas_not_found`: canvas_id does not match any registered DataCanvas session (expired, wrong session, or canvas disabled) `missing_table`: The canvas exists but sql references a table that is not staged on it — the table expired, was dropped, or the name is wrong `invalid_sql`: sql is not a single SELECT statement (a leading WITH … SELECT counts as one), or it is SELECT-shaped but fails to prepare — unknown column, unknown function, or a syntax error `sql_not_permitted`: sql parses as a SELECT but the read-only gate refuses it — it calls an external-data or PRAGMA table function, reads a system catalog, or plans an operator outside the read-only allowlist Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `canvas_not_found`: canvas_id does not match any registered DataCanvas session (expired, wrong session, or canvas disabled) `missing_table`: The canvas exists but sql references a table that is not staged on it — the table expired, was dropped, or the name is wrong `invalid_sql`: sql is not a single SELECT statement (a leading WITH … SELECT counts as one), or it is SELECT-shaped but fails to prepare — unknown column, unknown function, or a syntax error `sql_not_permitted`: sql parses as a SELECT but the read-only gate refuses it — it calls an external-data or PRAGMA table function, reads a system catalog, or plans an operator outside the read-only allowlist `response_too_large`: The first result row cannot fit in the complete structured and formatted response budget Other values are possible when a failure originates below the handler." - changed
Output schema / properties / error / properties / data / properties / reason / examplesPrevious value: -[ - "canvas_not_found", - "missing_table", - "invalid_sql", - "sql_not_permitted" -]New value: +[ + "canvas_not_found", + "missing_table", + "invalid_sql", + "sql_not_permitted", + "response_too_large" +] - changed
Output schema / properties / row_count / descriptionPrevious value: -"Number of rows materialized in rows. Equals the canvas row limit when truncated is true — DataCanvas does not report a pre-cap total, so this is never larger than rows.length."New value: +"Number of materialized rows returned in rows. Always equals rows.length and never claims a pre-cap total." - changed
Output schema / properties / rows / descriptionPrevious value: -"Query result rows, capped at the canvas row limit (default 10,000)."New value: +"Largest result-row prefix whose complete structured and formatted response fits the 100,000-character response budget, after the canvas row limit (default 10,000) is applied." - changed
Output schema / properties / truncated / descriptionPrevious value: -"True when the query matched more rows than the canvas row limit and the result was capped. Page the remainder with a stable ORDER BY plus LIMIT/OFFSET, or narrow the query with WHERE or aggregation."New value: +"True when DataCanvas capped the query at its row limit or the server omitted materialized rows to fit the response-size budget. Page the remainder with a stable ORDER BY plus LIMIT/OFFSET, or narrow the query with WHERE or aggregation."
3 tool updates
- Changed
imf_dataframe_describe1 field changed- changed
Input schema / properties / canvas_id / descriptionPrevious value: -"Canvas ID returned by imf_query_dataset when results were too large for inline delivery."New value: +"Canvas ID returned by imf_query_dataset whenever staged=true, from automatic spillover or output_mode=\"canvas\"."
- Changed
imf_dataframe_query1 field changed- changed
Input schema / properties / canvas_id / descriptionPrevious value: -"Canvas ID returned by imf_query_dataset when results were too large for inline delivery."New value: +"Canvas ID returned by imf_query_dataset whenever staged=true. Call imf_dataframe_describe with it before writing SQL."
- Changed
imf_query_dataset13 fields changed- changed
Input schema / properties / canvas_id / descriptionPrevious value: -"Existing canvas ID to accumulate results into across multiple queries. Omit to allocate a fresh canvas; the response includes a canvas_id when results spill to DataCanvas."New value: +"Existing canvas ID to accumulate results into across multiple queries. This selects the destination only; it does not force staging. Use output_mode=\"canvas\" to stage an under-budget result." - added
Input schema / properties / output_modeAdded value: +{ + "default": "auto", + "description": "Result placement. auto returns an under-budget result inline and spills only when needed. canvas explicitly stages the full result, using canvas_id when supplied or allocating a fresh canvas.", + "enum": [ + "auto", + "canvas" + ], + "type": "string" +} - changed
Input schema / properties / start_period / descriptionPrevious value: -"Start of time range (inclusive). Accepts any of YYYY (annual), YYYY-SN (semi-annual, e.g. 2023-S1), YYYY-QN (quarterly, e.g. 2023-Q1), YYYY-MM (monthly), or YYYY-MM-DD (daily), whatever the dataflow's frequency. The bound covers the whole period it names, so start_period 2023 admits 2023-M01 and 2023-Q1. Observations before this period are excluded from the result."New value: +"Start of time range (inclusive). Accepts any of YYYY (annual), YYYY-SN (semi-annual, e.g. 2023-S1), YYYY-QN (quarterly, e.g. 2023-Q1), YYYY-MM (monthly), or a calendar-valid YYYY-MM-DD (daily), whatever the dataflow's frequency. The bound covers the whole period it names, so start_period 2023 admits 2023-M01 and 2023-Q1. Observations before this period are excluded from the result." - changed
Output schema / anyOfPrevious value: -[ - { - "not": { - "required": [ - "error" - ] - }, - "required": [ - "dataflow_id", - "key", - "observations", - "series_attributes", - "observation_count", - "truncated", - "source" - ] - }, - { - "required": [ - "error" - ] - } -]New value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "dataflow_id", + "key", + "observations", + "series_attributes", + "observation_count", + "staged", + "truncated", + "source" + ] + }, + { + "required": [ + "error" + ] + } +] - changed
Output schema / properties / canvas_id / descriptionPrevious value: -"DataCanvas session ID — present when truncated=true. Pass to imf_dataframe_query or imf_dataframe_describe to query the full result."New value: +"DataCanvas session ID — present when staged=true. Pass first to imf_dataframe_describe, then to imf_dataframe_query." - changed
Output schema / properties / error / properties / data / properties / reason / descriptionPrevious value: -"Machine-readable failure mode. Declared by this tool: `dataflow_not_found`: dataflow_id does not match any known dataflow on api.imf.org `no_data`: Key is structurally valid but the dataflow holds no series for this code combination, or the dataflow publishes no series at all `no_data_in_range`: The key returned observations but start_period/end_period excluded every one of them `key_dimension_mismatch`: Number of dot-separated segments in key does not match the dataflow's DSD dimension count `empty_key_segment`: A dot-separated position in key is empty or blank, which matches no series upstream `invalid_period_format`: start_period or end_period is not one of the recognized period formats `invalid_period_range`: start_period is later than end_period `structure_unavailable`: api.imf.org returns non-200 on the data endpoint `dataflow_list_unavailable`: The dataflow catalog that dataflow_id is resolved against could not be fetched — fires before the DSD and data lookups are attempted Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `dataflow_not_found`: dataflow_id does not match any known dataflow on api.imf.org `no_data`: Key is structurally valid but the dataflow holds no series for this code combination, or the dataflow publishes no series at all `no_data_in_range`: The key returned observations but start_period/end_period excluded every one of them `key_dimension_mismatch`: Number of dot-separated segments in key does not match the dataflow's DSD dimension count `empty_key_segment`: A dot-separated position in key is empty or blank, which matches no series upstream `invalid_period_format`: start_period or end_period is not one of the recognized period formats `invalid_period_range`: start_period is later than end_period `structure_unavailable`: The dataflow structure (DSD) cannot be fetched after the dataflow catalog resolved successfully `canvas_unavailable`: output_mode=\"canvas\" was requested but DataCanvas is disabled `response_too_large`: Fixed staged-result metadata exceeds the response budget before any observation preview can be included `dataflow_list_unavailable`: The dataflow catalog that dataflow_id is resolved against could not be fetched — fires before the DSD and data lookups are attempted Other values are possible when a failure originates below the handler." - changed
Output schema / properties / error / properties / data / properties / reason / examplesPrevious value: -[ - "dataflow_not_found", - "no_data", - "no_data_in_range", - "key_dimension_mismatch", - "empty_key_segment", - "invalid_period_format", - "invalid_period_range", - "structure_unavailable", - "dataflow_list_unavailable" -]New value: +[ + "dataflow_not_found", + "no_data", + "no_data_in_range", + "key_dimension_mismatch", + "empty_key_segment", + "invalid_period_format", + "invalid_period_range", + "structure_unavailable", + "canvas_unavailable", + "response_too_large", + "dataflow_list_unavailable" +] - changed
Output schema / properties / notice / descriptionPrevious value: -"Populated when a period bound was set but some observations carry a time_period label the range filter does not recognize — those rows are returned unfiltered, so the requested range did not apply to them."New value: +"Populated when a period bound was set but some observations carry a time_period label the range filter does not recognize. Composes with staged retrieval_guidance when both apply." - changed
Output schema / properties / observations / descriptionPrevious value: -"Inline observations. Empty when results spilled to canvas (see canvas_id / table_name)."New value: +"Inline observation preview. For staged results this may contain the full set or a budget-limited prefix; observation_count remains the full count." - added
Output schema / properties / retrieval_guidanceAdded value: +{ + "description": "Present on every staged result. Identifies the imf_dataframe_describe-before-imf_dataframe_query retrieval workflow.", + "type": "string" +} - added
Output schema / properties / stagedAdded value: +{ + "description": "True when the complete observation set is stored on DataCanvas. canvas_id and table_name are present whenever true.", + "type": "boolean" +} - changed
Output schema / properties / table_name / descriptionPrevious value: -"DuckDB table name on the canvas — present when truncated=true; reference in SQL via FROM <table_name>."New value: +"DuckDB table name on the canvas — present when staged=true; reference in SQL via FROM <table_name>." - changed
Output schema / properties / truncated / descriptionPrevious value: -"True when the result exceeded the inline limit and was staged on a DataCanvas table; canvas_id and table_name are populated and imf_dataframe_query provides SQL access to the full set."New value: +"True only when observations is an incomplete preview of observation_count. A result can be staged=true and truncated=false when every observation also fits inline."
1 tool update
- Changed
imf_get_database20 fields changed- changed
Input schema / properties / codelist_filter / descriptionPrevious value: -"Optional case-insensitive substring to search within each dimension's codelist (code ID and name). When set, returns all matching entries per dimension instead of the first-50 window — useful for large codelists like WEO INDICATOR (145 entries). Example: \"CPI\" or \"PCPIPCH\" surfaces consumer price index codes without hitting the 50-entry cap."New value: +"Optional case-insensitive substring to search within each dimension's codelist (code ID and name). Filtering runs before the 50-entry preview or selected-dimension page. Example: \"CPI\" or \"Constant prices\" surfaces matching WEO indicator codes." - added
Input schema / properties / codelist_filter / minLengthAdded value: +1 - added
Input schema / properties / dimension_idAdded value: +{ + "description": "Exact dimension ID from this tool, e.g. INDICATOR. Select one dimension to page beyond its preview.", + "minLength": 1, + "type": "string" +} - added
Input schema / properties / limitAdded value: +{ + "description": "Entries to return from the selected dimension. Valid only with dimension_id; default 50, maximum 200.", + "maximum": 200, + "minimum": 1, + "type": "integer" +} - added
Input schema / properties / offsetAdded value: +{ + "description": "Matching entries to skip in the selected dimension before this page. Valid only with dimension_id; default 0.", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" +} - changed
Output schema / anyOfPrevious value: -[ - { - "not": { - "required": [ - "error" - ] - }, - "required": [ - "dataflow_id", - "agency_id", - "version", - "name", - "key_format", - "dimensions", - "source" - ] - }, - { - "required": [ - "error" - ] - } -]New value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "dataflow_id", + "agency_id", + "version", + "name", + "key_format", + "truncated", + "dimensions", + "source" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / dimension_idAdded value: +{ + "description": "Selected dimension ID. Absent when previews for every dimension were returned.", + "type": "string" +} - changed
Output schema / properties / dimensions / descriptionPrevious value: -"All dimensions of this dataflow with their codelists."New value: +"All dimension previews, or the one selected dimension page." - changed
Output schema / properties / dimensions / items / properties / codelist / descriptionPrevious value: -"Valid codes for this dimension. Up to 50 entries shown when no codelist_filter is set; use codelist_filter to search large codelists or the imf://database resource for the full list. Empty means the filter matched nothing when codelist_filter is echoed back, and that the codelist could not be resolved when it is not — see notice."New value: +"Valid codes for this dimension. Unselected previews show up to 50 entries after optional filtering. Select dimension_id and use limit/offset for a bounded page of up to 200 entries. Empty means the filter matched nothing when codelist_filter is echoed back, and that the codelist could not be resolved when it is not — see notice." - changed
Output schema / properties / dimensions / items / properties / codelist_truncated / descriptionPrevious value: -"True when the codelist has more than 50 entries and was truncated."New value: +"True when matching codes were omitted before or after this page." - added
Output schema / properties / dimensions / items / properties / matched_countAdded value: +{ + "description": "Codes matching codelist_filter before limit and offset are applied.", + "type": "number" +} - added
Output schema / properties / dimensions / items / properties / next_offsetAdded value: +{ + "description": "Offset for the next page when later matching codes remain.", + "type": "number" +} - added
Output schema / properties / dimensions / items / properties / offsetAdded value: +{ + "description": "Matching codes skipped before this dimension page.", + "type": "number" +} - added
Output schema / properties / dimensions / items / properties / returned_countAdded value: +{ + "description": "Codes returned in this dimension page.", + "type": "number" +} - added
Output schema / properties / dimensions / items / properties / unfiltered_countAdded value: +{ + "description": "Codes in the complete resolved codelist before codelist_filter is applied.", + "type": "number" +} - changed
Output schema / properties / dimensions / items / requiredPrevious value: -[ - "id", - "name", - "position", - "codelist", - "codelist_truncated" -]New value: +[ + "id", + "name", + "position", + "codelist", + "codelist_truncated", + "unfiltered_count", + "matched_count", + "returned_count", + "offset" +] - changed
Output schema / properties / error / properties / data / properties / reason / descriptionPrevious value: -"Machine-readable failure mode. Declared by this tool: `dataflow_not_found`: dataflow_id does not match any known dataflow on api.imf.org `structure_unavailable`: api.imf.org returns non-200 on the DSD endpoint `dataflow_list_unavailable`: The dataflow catalog that dataflow_id is resolved against could not be fetched — fires before the DSD lookup is attempted Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `dataflow_not_found`: dataflow_id does not match any known dataflow on api.imf.org `dimension_not_found`: dimension_id does not match a dimension in the selected dataflow `structure_unavailable`: api.imf.org returns non-200 on the DSD endpoint `dataflow_list_unavailable`: The dataflow catalog that dataflow_id is resolved against could not be fetched — fires before the DSD lookup is attempted Other values are possible when a failure originates below the handler." - changed
Output schema / properties / error / properties / data / properties / reason / examplesPrevious value: -[ - "dataflow_not_found", - "structure_unavailable", - "dataflow_list_unavailable" -]New value: +[ + "dataflow_not_found", + "dimension_not_found", + "structure_unavailable", + "dataflow_list_unavailable" +] - changed
Output schema / properties / notice / descriptionPrevious value: -"Populated when a codelist_filter matched no entries anywhere, or when a dimension has no resolvable codelist — the two produce the same empty array and need opposite next steps."New value: +"Populated when a codelist_filter matched no entries anywhere, or when a dimension has no resolvable codelist, or when offset is past the final match." - added
Output schema / properties / truncatedAdded value: +{ + "description": "True when any returned dimension page omits matching codes.", + "type": "boolean" +}
5 tool updates
- Changed
imf_dataframe_describe6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "canvas_id", + "tables", + "table_count" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded 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: `canvas_not_found`: canvas_id does not match any registered DataCanvas session (expired, wrong session, or canvas disabled) Other values are possible when a failure originates below the handler.", + "examples": [ + "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" +} - removed
Output schema / requiredRemoved value: -[ - "canvas_id", - "tables", - "table_count" -]
- Changed
imf_dataframe_query6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "rows", + "row_count", + "truncated" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded 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: `canvas_not_found`: canvas_id does not match any registered DataCanvas session (expired, wrong session, or canvas disabled) `missing_table`: The canvas exists but sql references a table that is not staged on it — the table expired, was dropped, or the name is wrong `invalid_sql`: sql is not a single SELECT statement (a leading WITH … SELECT counts as one), or it is SELECT-shaped but fails to prepare — unknown column, unknown function, or a syntax error `sql_not_permitted`: sql parses as a SELECT but the read-only gate refuses it — it calls an external-data or PRAGMA table function, reads a system catalog, or plans an operator outside the read-only allowlist Other values are possible when a failure originates below the handler.", + "examples": [ + "canvas_not_found", + "missing_table", + "invalid_sql", + "sql_not_permitted" + ], + "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" +} - removed
Output schema / requiredRemoved value: -[ - "rows", - "row_count", - "truncated" -]
- Changed
imf_get_database6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "dataflow_id", + "agency_id", + "version", + "name", + "key_format", + "dimensions", + "source" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded 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: `dataflow_not_found`: dataflow_id does not match any known dataflow on api.imf.org `structure_unavailable`: api.imf.org returns non-200 on the DSD endpoint `dataflow_list_unavailable`: The dataflow catalog that dataflow_id is resolved against could not be fetched — fires before the DSD lookup is attempted Other values are possible when a failure originates below the handler.", + "examples": [ + "dataflow_not_found", + "structure_unavailable", + "dataflow_list_unavailable" + ], + "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" +} - removed
Output schema / requiredRemoved value: -[ - "dataflow_id", - "agency_id", - "version", - "name", - "key_format", - "dimensions", - "source" -]
- Changed
imf_list_databases6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "dataflows", + "total_count", + "returned_count", + "offset" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded 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: `dataflow_list_unavailable`: The IMF SDMX structure endpoint that backs the dataflow catalog did not return a usable response Other values are possible when a failure originates below the handler.", + "examples": [ + "dataflow_list_unavailable" + ], + "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" +} - removed
Output schema / requiredRemoved value: -[ - "dataflows", - "total_count", - "returned_count", - "offset" -]
- Changed
imf_query_dataset6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "dataflow_id", + "key", + "observations", + "series_attributes", + "observation_count", + "truncated", + "source" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded 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: `dataflow_not_found`: dataflow_id does not match any known dataflow on api.imf.org `no_data`: Key is structurally valid but the dataflow holds no series for this code combination, or the dataflow publishes no series at all `no_data_in_range`: The key returned observations but start_period/end_period excluded every one of them `key_dimension_mismatch`: Number of dot-separated segments in key does not match the dataflow's DSD dimension count `empty_key_segment`: A dot-separated position in key is empty or blank, which matches no series upstream `invalid_period_format`: start_period or end_period is not one of the recognized period formats `invalid_period_range`: start_period is later than end_period `structure_unavailable`: api.imf.org returns non-200 on the data endpoint `dataflow_list_unavailable`: The dataflow catalog that dataflow_id is resolved against could not be fetched — fires before the DSD and data lookups are attempted Other values are possible when a failure originates below the handler.", + "examples": [ + "dataflow_not_found", + "no_data", + "no_data_in_range", + "key_dimension_mismatch", + "empty_key_segment", + "invalid_period_format", + "invalid_period_range", + "structure_unavailable", + "dataflow_list_unavailable" + ], + "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" +} - removed
Output schema / requiredRemoved value: -[ - "dataflow_id", - "key", - "observations", - "series_attributes", - "observation_count", - "truncated", - "source" -]
1 tool update
- Changed
imf_query_dataset3 fields changed- changed
Output schema / properties / series_attributes / properties / unit / descriptionPrevious value: -"Unit of measure, e.g. Percent, USD."New value: +"Unit of measure as the upstream code, e.g. PT (percent), USD, XDC (domestic currency), NUM (count). Null when the response carries no unit for the series — many dataflows publish none." - changed
Output schema / properties / series_metadata / descriptionPrevious value: -"Per-series attributes, one entry per distinct series_key in the result. Present only when the query resolved to more than one series; a single-series query carries its values in series_attributes instead. Scale differs across series in one query — WEO NGDPD is scale 9 while NGDP_RPCH is unscaled — so interpret each series against its own entry."New value: +"Per-series attributes, one entry per distinct series_key in the result. Present only when the query resolved to more than one series; a single-series query carries its values in series_attributes instead. Unit and scale differ across series in one query — WEO NGDPD is USD at scale 9 while NGDP_RPCH is PT unscaled — so interpret each series against its own entry." - changed
Output schema / properties / series_metadata / items / properties / unit / descriptionPrevious value: -"Unit of measure for this series, e.g. Percent."New value: +"Unit of measure for this series as the upstream code, e.g. PT (percent), USD, XDC (domestic currency). Null when the response carries none for it."
3 tool updates
- Changed
imf_get_database1 field changed- changed
Output schema / properties / description / descriptionPrevious value: -"This dataflow's own description, matching what imf_list_databases reports for the same id — not the shared DSD's. Absent when the dataflow publishes none."New value: +"This dataflow's own description in full — not the shared DSD's, and not the shortened preview imf_list_databases returns for the same id. Absent when the dataflow publishes none."
- Changed
imf_list_databases12 fields changed- added
Input schema / properties / limitAdded value: +{ + "default": 50, + "description": "Maximum dataflows to return in this call. Default 50, ceiling 200; total_count reports how many matched, so a partial page is always recognizable as one.", + "maximum": 200, + "minimum": 1, + "type": "integer" +} - added
Input schema / properties / offsetAdded value: +{ + "default": 0, + "description": "Number of matching dataflows to skip before this page. Combine with limit to page through a broad or unfiltered catalog.", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" +} - added
Output schema / properties / capAdded value: +{ + "description": "The limit that bounded this page.", + "type": "number" +} - changed
Output schema / properties / dataflows / descriptionPrevious value: -"Matching dataflows; pass the id to imf_get_database to resolve dimension codelists."New value: +"This page of matching dataflows; pass the id to imf_get_database to resolve dimension codelists." - changed
Output schema / properties / dataflows / items / properties / description / descriptionPrevious value: -"Extended description of the dataflow, if available."New value: +"Short description, cut to 200 characters and ended with … when longer. imf_get_database and the imf://database/{dataflow_id} resource return the full text." - changed
Output schema / properties / notice / descriptionPrevious value: -"Populated when the filter matches nothing — explains why and suggests next steps."New value: +"Populated when the filter matches nothing, or when matches remain beyond this page — explains why and names the next offset to request." - added
Output schema / properties / offsetAdded value: +{ + "description": "Number of matching dataflows skipped before this page.", + "type": "number" +} - added
Output schema / properties / returned_countAdded value: +{ + "description": "Dataflows in this page — the length of dataflows.", + "type": "number" +} - added
Output schema / properties / shownAdded value: +{ + "description": "Dataflows returned in this page.", + "type": "number" +} - changed
Output schema / properties / total_count / descriptionPrevious value: -"Total number of matching dataflows returned."New value: +"Dataflows matching filter and include_vintages, before limit and offset are applied. Exceeds returned_count when more pages remain." - added
Output schema / properties / truncatedAdded value: +{ + "description": "True when matching dataflows remain beyond this page.", + "type": "boolean" +} - changed
Output schema / requiredPrevious value: -[ - "dataflows", - "total_count" -]New value: +[ + "dataflows", + "total_count", + "returned_count", + "offset" +]
- Changed
imf_query_dataset3 fields changed- changed
Output schema / properties / series_attributes / descriptionPrevious value: -"Series-level attributes (unit, scale, decimals)."New value: +"Attributes of the first series in the result — the same series as series_metadata[0]. A key with + or * resolves to several series whose scale and unit differ, and this field describes only the first of them: read series_metadata for the rest, and never apply these values to another series_key." - changed
Output schema / properties / series_attributes / properties / scale / descriptionPrevious value: -"Scale multiplier, e.g. Billions."New value: +"Scale multiplier as the upstream code, e.g. 9 for billions. \"0\" means no multiplier — the values are unscaled." - added
Output schema / properties / series_metadataAdded value: +{ + "description": "Per-series attributes, one entry per distinct series_key in the result. Present only when the query resolved to more than one series; a single-series query carries its values in series_attributes instead. Scale differs across series in one query — WEO NGDPD is scale 9 while NGDP_RPCH is unscaled — so interpret each series against its own entry.", + "items": { + "additionalProperties": false, + "description": "Unit, scale, and decimals for one series in the result.", + "properties": { + "decimals": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "description": "Number of decimal places shown for this series." + }, + "scale": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Scale multiplier for this series as the upstream code, e.g. 9 for billions. \"0\" means no multiplier." + }, + "series_key": { + "description": "Series these attributes belong to, matching observations[].series_key.", + "type": "string" + }, + "unit": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Unit of measure for this series, e.g. Percent." + } + }, + "required": [ + "series_key", + "unit", + "scale", + "decimals" + ], + "type": "object" + }, + "type": "array" +}
2 tool updates
- Changed
imf_get_database1 field changed- changed
Output schema / properties / description / descriptionPrevious value: -"Extended description, if available."New value: +"This dataflow's own description, matching what imf_list_databases reports for the same id — not the shared DSD's. Absent when the dataflow publishes none."
- Changed
imf_query_dataset5 fields changed- changed
Input schema / properties / end_period / descriptionPrevious value: -"End of time range (inclusive). Same format as start_period, and must be greater than or equal to start_period. Observations after this period are excluded from the result."New value: +"End of time range (inclusive). Same formats as start_period, and must not be earlier than it. The bound covers the whole period it names, so end_period 2023 admits 2023-M12 and 2023-Q4. Observations after this period are excluded from the result." - changed
Input schema / properties / key / descriptionPrevious value: -"Dot-separated dimension codes in DSD keyPosition order. Call imf_get_database to get key_format and valid codes first. Use + to specify multiple codes (e.g. USA+GBR.NGDP_RPCH.A). Country codes are ISO 3-letter: USA not US, GBR not GB, DEU not DE."New value: +"Dot-separated dimension codes in DSD keyPosition order. Call imf_get_database to get key_format and valid codes first. Use + to combine codes at one position (e.g. USA+GBR.NGDP_RPCH.A). Use * to match every code at a position — *.NGDP_RPCH.A returns the indicator for all countries, and CAN.*.A every indicator for Canada. Every position needs a code or a *; an empty segment (USA..A) is rejected. Country codes are ISO 3-letter: USA not US, GBR not GB, DEU not DE." - changed
Input schema / properties / start_period / descriptionPrevious value: -"Start of time range (inclusive). Format matches the dataflow frequency: YYYY (annual), YYYY-QN (quarterly, e.g. 2023-Q1), YYYY-MM (monthly). Observations before this period are excluded from the result."New value: +"Start of time range (inclusive). Accepts any of YYYY (annual), YYYY-SN (semi-annual, e.g. 2023-S1), YYYY-QN (quarterly, e.g. 2023-Q1), YYYY-MM (monthly), or YYYY-MM-DD (daily), whatever the dataflow's frequency. The bound covers the whole period it names, so start_period 2023 admits 2023-M01 and 2023-Q1. Observations before this period are excluded from the result." - added
Output schema / properties / noticeAdded value: +{ + "description": "Populated when a period bound was set but some observations carry a time_period label the range filter does not recognize — those rows are returned unfiltered, so the requested range did not apply to them.", + "type": "string" +} - changed
Output schema / properties / observations / items / properties / time_period / descriptionPrevious value: -"Time label as emitted by the upstream API. Annual: YYYY (e.g. 2023). Quarterly: YYYY-QN (e.g. 2023-Q1). Monthly: YYYY-MNN (e.g. 2023-M01, not YYYY-MM). start_period/end_period accept both YYYY-MM and YYYY-MNN for monthly comparisons."New value: +"Time label as emitted by the upstream API. Annual: YYYY (e.g. 2023). Semi-annual: YYYY-SN (e.g. 2023-S1). Quarterly: YYYY-QN (e.g. 2023-Q1). Monthly: YYYY-MNN (e.g. 2023-M01, not YYYY-MM). Daily: YYYY-MM-DD (e.g. 2023-01-05). Every one of these is also accepted as a start_period/end_period bound, so a label from this field can be passed straight back in."
1 tool update
- Changed
imf_get_database4 fields changed- added
Output schema / properties / codelist_filterAdded value: +{ + "description": "Echo of the codelist_filter that produced this result. Absent when no filter was applied — an empty codelist then means the codelist could not be resolved, not that the filter missed.", + "type": "string" +} - changed
Output schema / properties / dimensions / items / properties / codelist / descriptionPrevious value: -"Valid codes for this dimension. Up to 50 entries shown when no codelist_filter is set; use codelist_filter to search large codelists or the imf://database resource for the full list."New value: +"Valid codes for this dimension. Up to 50 entries shown when no codelist_filter is set; use codelist_filter to search large codelists or the imf://database resource for the full list. Empty means the filter matched nothing when codelist_filter is echoed back, and that the codelist could not be resolved when it is not — see notice." - changed
Output schema / properties / dimensions / items / properties / name / descriptionPrevious value: -"Human-readable dimension name."New value: +"Human-readable dimension label from the DSD concept scheme, e.g. Weight Type for WGT_TYPE. Falls back to the dimension id when the structure names no concept." - added
Output schema / properties / noticeAdded value: +{ + "description": "Populated when a codelist_filter matched no entries anywhere, or when a dimension has no resolvable codelist — the two produce the same empty array and need opposite next steps.", + "type": "string" +}
1 tool update
- Changed
imf_dataframe_query4 fields changed- changed
Input schema / properties / sql / descriptionPrevious value: -"Read-only SQL SELECT statement. Must start with SELECT. Reference tables by the names returned by imf_dataframe_describe. Example: SELECT time_period, value FROM spilled_abc123 WHERE time_period >= '2010' ORDER BY time_period."New value: +"Read-only SQL SELECT statement — exactly one statement, starting with SELECT or with a WITH … SELECT common table expression. Reference tables by the names returned by imf_dataframe_describe. Example: SELECT time_period, value FROM spilled_abc123 WHERE time_period >= '2010' ORDER BY time_period." - changed
Output schema / properties / row_count / descriptionPrevious value: -"Total matching rows before the cap — may exceed rows.length."New value: +"Number of rows materialized in rows. Equals the canvas row limit when truncated is true — DataCanvas does not report a pre-cap total, so this is never larger than rows.length." - added
Output schema / properties / truncatedAdded value: +{ + "description": "True when the query matched more rows than the canvas row limit and the result was capped. Page the remainder with a stable ORDER BY plus LIMIT/OFFSET, or narrow the query with WHERE or aggregation.", + "type": "boolean" +} - changed
Output schema / requiredPrevious value: -[ - "rows", - "row_count" -]New value: +[ + "rows", + "row_count", + "truncated" +]
1 tool update
- Changed
imf_query_dataset1 field changed- changed
Input schema / properties / end_period / descriptionPrevious value: -"End of time range (inclusive). Same format as start_period. Observations after this period are excluded from the result."New value: +"End of time range (inclusive). Same format as start_period, and must be greater than or equal to start_period. Observations after this period are excluded from the result."
1 tool update
- Changed
imf_get_database2 fields changed- added
Output schema / properties / dsd_versionAdded value: +{ + "description": "Version of the underlying data structure definition (DSD) that backs this dataflow. Differs from version when the dataflow references a shared DSD (e.g. IIP → DSD_BOP at 24.0.0).", + "type": "string" +} - added
Output schema / properties / structure_refAdded value: +{ + "description": "Identifier of the underlying DSD, e.g. DSD_BOP. Several dataflows can share one DSD.", + "type": "string" +}
3 tool updates
- Changed
imf_get_database2 fields changed- added
Input schema / properties / codelist_filterAdded value: +{ + "description": "Optional case-insensitive substring to search within each dimension's codelist (code ID and name). When set, returns all matching entries per dimension instead of the first-50 window — useful for large codelists like WEO INDICATOR (145 entries). Example: \"CPI\" or \"PCPIPCH\" surfaces consumer price index codes without hitting the 50-entry cap.", + "type": "string" +} - changed
Output schema / properties / dimensions / items / properties / codelist / descriptionPrevious value: -"Valid codes for this dimension. Up to 50 entries shown; full list available via the imf://database resource."New value: +"Valid codes for this dimension. Up to 50 entries shown when no codelist_filter is set; use codelist_filter to search large codelists or the imf://database resource for the full list."
- Changed
imf_list_databases1 field changed- changed
Input schema / properties / filter / descriptionPrevious value: -"Optional name or ID substring to filter results. Case-insensitive. Example: \"exchange rate\" returns ER and related dataflows."New value: +"Optional name, ID, or description substring to filter results. Case-insensitive. Example: \"exchange rate\" returns ER and related dataflows."
- Changed
imf_query_dataset3 fields changed- changed
Input schema / properties / end_period / descriptionPrevious value: -"Requested end of time range. Same format as start_period. See start_period note: the API returns the full series; this parameter is passed through but may not filter observations."New value: +"End of time range (inclusive). Same format as start_period. Observations after this period are excluded from the result." - changed
Input schema / properties / start_period / descriptionPrevious value: -"Requested start of time range. Format matches the dataflow frequency: YYYY (annual), YYYY-QN (quarterly, e.g. 2023-Q1), YYYY-MM (monthly). Note: the IMF SDMX 3.0 compact JSON endpoint returns the full available series regardless of this parameter — observations outside the requested range may still appear."New value: +"Start of time range (inclusive). Format matches the dataflow frequency: YYYY (annual), YYYY-QN (quarterly, e.g. 2023-Q1), YYYY-MM (monthly). Observations before this period are excluded from the result." - changed
Output schema / properties / observations / items / properties / time_period / descriptionPrevious value: -"Time label, e.g. 2023 or 2023-Q1 or 2023-01."New value: +"Time label as emitted by the upstream API. Annual: YYYY (e.g. 2023). Quarterly: YYYY-QN (e.g. 2023-Q1). Monthly: YYYY-MNN (e.g. 2023-M01, not YYYY-MM). start_period/end_period accept both YYYY-MM and YYYY-MNN for monthly comparisons."
5 tool updates
- First observed
imf_dataframe_describe - First observed
imf_dataframe_query - First observed
imf_get_database - First observed
imf_list_databases - First observed
imf_query_dataset
Related MCP Connectors
Macro indicators from World Bank, FRED, IMF, and OECD via unified query surface.
Search and query 1,500+ OECD statistical datasets via SDMX. Keyless.
Macroeconomic and other official data from 170+ publishers, resolved from natural language with provenance.
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceEnables searching, exploring, and querying over 1,500 OECD statistical datasets via SDMX, covering national accounts, employment, trade, PISA, health, and more.228 npm2Apache 2.0

@pipeworx/bisofficial
AlicenseNot gradedqualityBmaintenanceEnables querying Bank for International Settlements central-bank and global financial statistics via the SDMX v2 API, including credit-to-GDP gaps, curated dataflows, and full registry search with dataset fetching, without authentication.149 npm1MIT- AlicenseNot gradedqualityCmaintenanceProvides access to European Central Bank statistical data through SDMX data flows, enabling querying and listing of data flows via natural language or direct tool calls.1 npmMIT
- AlicenseNot gradedqualityCmaintenanceEnables discovery and retrieval of National Bank of Belgium statistical data across 221 SDMX dataflows, with search, descriptions, custom queries, and comparisons of economic indicators.25 PyPI3MIT
Glama MCP Gateway
Add one secure layer between your agents and this server.