Skip to content

io.github.cyanheads/imf-mcp-server

by cyanheads · remote · local (npm) · no sign-in to list tools · v0.4.4 · published by GitHub user cyanheads

Query IMF SDMX 3.0 macroeconomic dataflows — WEO, BOP, CPI, exchange rates, 190 countries.

Changes · 1

5 tools: 1 change things and 4 only read.

Scanned Oct 21, 2026

2 checks matched something in the tool definitions. No finding is not a safety guarantee. How the checks work.

claude mcp add --transport http imf https://imf.caseyjhand.com/mcp

Findings

Matches of fixed checks, with the text they matched.

1 warn1 info
  • The server marks "imf_dataframe_query" read-only (readOnlyHint: true), and its own name, description or input give the class "write".

    Matched text

    annotations: {"readOnlyHint":true,"idempotentHint":true,"openWorldHint":false}; The name "imf_dataframe_query" says "query": a word for reading.

    What this check looks for
  • The description is 2,704 characters long, over the 2,000 this check looks for.

    Matched text

    description ends: "...nd retrieval_guidance names the last period returned and how to narrow the query."

    What this check looks for

Tools

Open a tool for its reasons and full description. Descriptions are the publisher's own words, shown as they are.

5 tools

Changes things 1Claude Code: ask
  • imf_dataframe_queryRun a read-only SQL SELECT against a DataCanvas table staged by imf_query_dataset.1 finding

    Why it is in this group

    • The name "imf_dataframe_query" says "query": a word for reading.
    • The description's first verb is "run": a word for a change.
    • The input takes a statement or command to run (input.sql), which can change anything it can reach.
    • The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.

    Findings

    • Warn

      The server marks "imf_dataframe_query" read-only (readOnlyHint: true), and its own name, description or input give the class "write".

      Matched text

      annotations: {"readOnlyHint":true,"idempotentHint":true,"openWorldHint":false}; The name "imf_dataframe_query" says "query": a word for reading.

      What this check looks for
    Description, as the server wrote it
    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.

    Annotations the server declares

    • readOnlyHint: true
    • idempotentHint: true
    • openWorldHint: false
Only reads 4Claude Code: allow
  • imf_dataframe_describeList DataCanvas tables and columns staged by a prior imf_query_dataset call.No findings

    Why it is in this group

    • The name "imf_dataframe_describe" says "describe": a word for reading.
    Description, as the server wrote it
    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.

    Annotations the server declares

    • readOnlyHint: true
    • idempotentHint: true
    • openWorldHint: false
  • imf_get_databaseFetch a dataflow's dimension list with a codelist preview for each dimension.No findings

    Why it is in this group

    • The name "imf_get_database" says "get": a word for reading.
    Description, as the server wrote it
    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 codelist_filter, which keeps codes whose ID or name contains every word given. 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.

    Annotations the server declares

    • readOnlyHint: true
    • idempotentHint: true
    • openWorldHint: true
  • imf_list_databasesList IMF SDMX dataflows available on the portal.No findings

    Why it is in this group

    • The name "imf_list_databases" says "list": a word for reading.
    Description, as the server wrote it
    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 and at most 200, 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.

    Annotations the server declares

    • readOnlyHint: true
    • idempotentHint: true
    • openWorldHint: true
  • imf_query_datasetQuery an IMF SDMX dataflow by dimension key over a time range.1 finding

    Why it is in this group

    • The name "imf_query_dataset" says "query": a word for reading.

    Findings

    • Info

      The description is 2,704 characters long, over the 2,000 this check looks for.

      Matched text

      description ends: "...nd retrieval_guidance names the last period returned and how to narrow the query."

      What this check looks for
    Description, as the server wrote it
    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. An index series also carries the reference_period it is based on (e.g. 2010A, 2010=100) exactly as published, on the series and, where the dataflow publishes one per observation, on each observation. 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); * stands alone and cannot join a + list. Codes are matched case-insensitively and checked against each dimension's codelist before the query — an unknown code is rejected with the nearest valid codes. 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. When a + key returns data for some requested series and none for others, missing_series names each empty one with the reason a query for it alone gives (no_data or no_data_in_range). When the extra request that recovers the unit, scale, or decimals a + key suppresses fails, unresolved_attributes names them and how to get them. 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. last_n_observations keeps each series' last N observations — 1 is each series' latest value, the cheap way to ask many countries for their latest figure. Values are in base units everywhere, staged canvas rows included: scale is the power of ten the IMF publishes a series in (value / 10^scale is the published figure), never a factor still to apply. A response is held to 100,000 serialized characters. With DataCanvas enabled (CANVAS_PROVIDER_TYPE=duckdb), a larger result (multi-country, long time range) spills to it: call imf_dataframe_describe first to inspect staged tables and columns, then imf_dataframe_query for SQL analysis. Without DataCanvas, a larger result returns its earliest observations with truncated=true, and retrieval_guidance names the last period returned and how to narrow the query.

    Annotations the server declares

    • readOnlyHint: true
    • idempotentHint: true
    • openWorldHint: true

This is not a safety rating, and no finding is not a safety guarantee. The groups and findings come from fixed checks of the tool definitions the server returned on the date shown, not from its code or what it does when called. How the checks work.

Install

Pinned to version 0.4.4. Values in angle brackets are yours to fill in.

claude mcp add --transport http imf https://imf.caseyjhand.com/mcp

Run in a terminal.

Claude Code permissions

Allow the reads, ask before a change, deny the deletes. Paste into .claude/settings.json.

.claude/settings.json
{
  "permissions": {
    "allow": [
      "mcp__imf__imf_list_databases",
      "mcp__imf__imf_get_database",
      "mcp__imf__imf_query_dataset",
      "mcp__imf__imf_dataframe_describe"
    ],
    "ask": [
      "mcp__imf__imf_dataframe_query"
    ],
    "deny": []
  }
}

Tools that only read are allowed, tools that change things ask first, tools that delete or cancel are denied. It assumes the server is installed as imf. Review it before you use it.