Query IMF SDMX 3.0 macroeconomic dataflows — WEO, BOP, CPI, exchange rates, 190 countries.
Query IMF SDMX 3.0 macroeconomic data — hundreds of dataflows across 190 countries, WEO projections, BOP, CPI, exchange rates, and national accounts via MCP. STDIO or Streamable HTTP.
Public Hosted Server: https://imf.caseyjhand.com/mcp
IMF SDMX 3.0 macroeconomic data — hundreds of dataflows spanning WEO projections, balance of payments, CPI, exchange rates, and national accounts across 190 countries. Browse the dataflow catalog, resolve dimension codes, and query time series from any MCP client, with large multi-country results staged to DataCanvas for SQL analysis. Runs as a stdio process, a local Streamable HTTP server, or the public hosted endpoint above.
| Tool | Description |
|---|---|
imf_list_databases | List IMF SDMX dataflows available on the portal, a page at a time, with optional name/ID/description substring filtering |
imf_get_database | Fetch a dataflow's dimensions and page either its codelists or the codes with published data — resolves human terms to SDMX codes before querying |
imf_query_dataset | Query a dataflow by dimension key over a time range; large result sets spill to DataCanvas |
imf_dataframe_describe | List DataCanvas tables and columns staged by a prior imf_query_dataset call |
imf_dataframe_query | Run a read-only SQL SELECT across staged DataCanvas tables for multi-country comparisons and aggregations |
imf_dataframe_drop | Remove one staged table or view without affecting other tables on the canvas; disabled by default |
| Resource | Description |
|---|---|
imf://database/{dataflow_id} | Bounded discovery metadata for one IMF SDMX dataflow — dimensions, codelist previews, key_format, and continuation guidance |
Continuation beyond the resource's bounded codelist preview runs through imf_get_database.
imf_list_databases toolWEO_2025_OCT_VINTAGE are excluded by default; set include_vintages=true to include themlimit (default 50, max 200) and offset; total_count reports total matches, returned_count the page size, and a notice names the next offset while matches remainimf_get_database and the imf://database/{dataflow_id} resource return the full textimf_get_database toolUSA) and returns each dimension's DSD concept-scheme labelUSA, GBR, DEU), not ISO 2-letter (US, GB, DE)key_format names the exact dot-separated dimension order imf_query_dataset requiresdimension_id to page one dimension with limit/offset (max 200), and codelist_filter applies before pagingavailable_only=true to page codes the dataflow actually publishes, with series count and time coverage, instead of the full codelistcodelist_filter that matches nothing is reported distinctly from a codelist that could not be resolved — the two need opposite next stepsimf_query_dataset tool+ combines codes at one position, * matches every code there — every position needs a code or *, a blank segment is rejectedstart_period/end_period accept YYYY, YYYY-SN, YYYY-QN, YYYY-MM, or a calendar-valid YYYY-MM-DD; each bound covers its whole period (end_period: 2023 includes 2023-M12)time_period, value, status, and series attributes (unit, scale, decimals); a key resolving to multiple series carries one series_metadata entry per series, since attributes can differ between themunit/scale are upstream codes (PT, USD, XDC, IX, NUM); a null unit means the dataflow publishes none, and scale "0" means no multiplieroutput_mode: "canvas" forces staging); staged reports storage, truncated reports only whether observations is an incomplete preview — a staged result can still be untruncatedno_data errors carry availability context naming codes that do have coverage; a key with data entirely outside the requested range fails as no_data_in_range and reports the range that doesimf_dataframe_describe toolcanvas_id from a prior imf_query_dataset call that returned staged: trueimf_dataframe_query to confirm table and column namesimf_dataframe_query toolSELECT per call; a leading WITH … SELECT common table expression is accepted, DML and DDL are rejectedrow_count always equals the returned rows, and truncated: true means either cap trimmed the resultORDER BY plus LIMIT/OFFSET; response_too_large means even one row didn't fit and asks for fewer columns or aggregationCANVAS_PROVIDER_TYPE=duckdbimf_dataframe_drop toolimf_dataframe_describedropped: false rather than an errorIMF_ENABLE_DATAFRAME_DROP=true to register it in tools/listimf://database/{dataflow_id} resourcekey_format, name, descriptiondataflow_id comes from imf_list_databasescontinuation metadata pointing to imf_get_database (with dimension_id/limit/offset) for a codelist beyond the previewBuilt on @cyanheads/mcp-ts-core: stdio and Streamable HTTP transports, pluggable auth (none / jwt / oauth), swappable storage (in-memory, filesystem, Supabase, Cloudflare KV/R2/D1), structured logging with optional OpenTelemetry tracing.
IMF-specific:
Agent-friendly output:
key_format field in every dataflow response explicitly states the dimension order, removing guesswork for key constructionstatus flags (e.g. E for estimate) so agents can communicate data quality caveatsstaged distinguishes storage from truncated preview completeness, and staged results carry canvas_id, table_name, and retrieval guidanceA public instance is available at https://imf.caseyjhand.com/mcp — no installation required. Point any MCP client at it via Streamable HTTP:
{
"mcpServers": {
"imf-mcp-server": {
"type": "streamable-http",
"url": "https://imf.caseyjhand.com/mcp"
}
}
}
No API key required. Add the following to your MCP client configuration file.
{
"mcpServers": {
"imf-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/imf-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info"
}
}
}
}
Or with npx (no Bun required):
{
"mcpServers": {
"imf-mcp-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@cyanheads/imf-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info"
}
}
}
}
Or with Docker:
{
"mcpServers": {
"imf-mcp-server": {
"type": "stdio",
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "MCP_TRANSPORT_TYPE=stdio",
"ghcr.io/cyanheads/imf-mcp-server:latest"
]
}
}
}
To enable SQL analytics over large result sets, add CANVAS_PROVIDER_TYPE=duckdb to the env block. Add IMF_ENABLE_DATAFRAME_DROP=true only when agents should be able to remove staged tables.
For Streamable HTTP, set the transport and start the server:
MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 bun run start:http
# Server listens at http://localhost:3010/mcp
git clone https://github.com/cyanheads/imf-mcp-server.git
cd imf-mcp-server
bun install
cp .env.example .env
# edit .env as needed — no required vars for basic use
| Variable | Description | Default |
|---|---|---|
CANVAS_PROVIDER_TYPE | Set to duckdb to enable DataCanvas spill for large result sets. | — |
IMF_ENABLE_DATAFRAME_DROP | Advertise and enable destructive table-level DataCanvas cleanup. | false |
IMF_BASE_URL | IMF SDMX 3.0 base URL. Override for testing or proxied environments. | https://api.imf.org/external/sdmx/3.0 |
IMF_REQUEST_TIMEOUT_MS | Per-request timeout in milliseconds. | 30000 |
MCP_TRANSPORT_TYPE | Transport: stdio or http. | stdio |
MCP_HTTP_PORT | Port for HTTP server. | 3010 |
MCP_SESSION_MODE | HTTP session handling: stateful, stateless, or auto (the schema default, which resolves to stateful). This server declares stateless in src/index.ts, so a deployment that sets nothing still gets it; setting this to a meaningful value overrides the declaration. | stateless |
MCP_AUTH_MODE | Auth mode: none, jwt, or oauth. | none |
MCP_LOG_LEVEL | Log level (RFC 5424). | info |
OTEL_ENABLED | Enable OpenTelemetry instrumentation. | false |
See .env.example for the full list of optional overrides.
Build and run:
bun run rebuild
bun run start:stdio
# or
bun run start:http
Run checks and tests:
bun run devcheck # Lint, format, typecheck, security
bun run test # Vitest test suite
bun run lint:mcp # Validate MCP definitions against spec
docker build -t imf-mcp-server .
docker run --rm -p 3010:3010 imf-mcp-server
The Dockerfile defaults to HTTP transport, stateless session mode, and logs to /var/log/imf-mcp-server. OpenTelemetry peer dependencies are installed by default — build with --build-arg OTEL_ENABLED=false to omit them.
| Directory | Purpose |
|---|---|
src/index.ts | createApp() entry point — registers tools/resources and inits services. |
src/config/server-config.ts | Server-specific env var parsing and validation with Zod. |
src/mcp-server/tools/definitions/ | Tool definitions (*.tool.ts). |
src/mcp-server/resources/definitions/ | Resource definitions (*.resource.ts). |
src/services/canvas/ | DataCanvas accessor — wraps the framework canvas instance. |
src/services/imf-sdmx/ | IMF SDMX 3.0 API client — dataflow catalog, DSD fetching, data queries. |
tests/ | Unit and integration tests mirroring src/. |
docs/ | Design notes and directory tree. |
See CLAUDE.md/AGENTS.md for development guidelines and architectural rules. The short version:
try/catch in tool logicctx.log for request-scoped logging, ctx.state for tenant-scoped storagesrc/mcp-server/*/definitions/index.tsData is sourced from the International Monetary Fund SDMX 3.0 portal under the IMF Copyright and Terms of Use. The IMF's terms permit redistribution of statistical data with attribution. Each data-returning tool response includes a source field with the required attribution: Source: International Monetary Fund, <dataflow name>, https://data.imf.org/.
Issues are welcome. Run checks and tests before submitting:
bun run devcheck
bun run test
Apache-2.0 — see LICENSE for details.
Source-derived launch command. Check the maintainer’s required arguments and credentials before running:
npx -y @cyanheads/imf-mcp-serverMerge this template into ~/Library/Application Support/Claude/claude_desktop_config.json. Keep existing servers. Add any arguments, credentials, and permissions required by the maintainer; this template has not been install-tested.
{
"mcpServers": {
"io-github-cyanheads-imf-mcp-server": {
"command": "npx",
"args": [
"-y",
"@cyanheads/imf-mcp-server"
]
}
}
}Restart Claude Desktop completely for changes to take effect. Confirm the server appears connected in the client’s tool list, then try a read-only example from its documentation.
Claude Desktop setup referenceio.github.cyanheads/imf-mcp-server works with any MCP-compatible client. Copy the config snippet from the Configuration section above and add it to the file shown for your client, then restart the application.
~/Library/Application Support/Claude/claude_desktop_config.jsonRestart Claude Desktop completely for changes to take effect.~/.cursor/mcp.jsonRestart Cursor for changes to take effect..vscode/mcp.jsonReload VS Code window for changes to take effect.~/.codeium/windsurf/mcp_config.jsonRestart Windsurf for changes to take effect..mcp.jsonSave at the project root, then start Claude Code in that project and review the MCP server approval prompt. Keep real credentials out of shared files.