imf-mcp-server
Provides optional DuckDB-backed DataCanvas integration for staging large IMF SDMX query results and running read-only SQL SELECT queries across them, enabling multi-country comparisons and aggregations.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@imf-mcp-serverget real GDP growth for USA from 2020 to 2024"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Public Hosted Server: https://imf.caseyjhand.com/mcp
Overview
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.
Tools
Tool | Description |
| List IMF SDMX dataflows available on the portal, a page at a time, with an optional filter matching every word across ID, name, and description |
| Fetch a dataflow's dimensions and page either its codelists or the codes with published data — resolves human terms to SDMX codes before querying |
| Query a dataflow by dimension key over a time range; large result sets spill to DataCanvas when it is enabled, or return a bounded prefix with retrieval guidance |
| List DataCanvas tables and columns staged by a prior |
| Run a read-only SQL SELECT across staged DataCanvas tables for multi-country comparisons and aggregations |
| Remove one staged table or view without affecting other tables on the canvas; disabled by default |
Resources
Resource | Description |
| Bounded discovery metadata for one IMF SDMX dataflow — dimensions, codelist previews, |
Continuation beyond the resource's bounded codelist preview runs through imf_get_database.
Related MCP server: cnbs-mcp-server
Capability reference
imf_list_databases tool
filtersplits on spaces and commas and keeps a dataflow when every word appears, case-insensitively, in its ID, name, or description ("WEO outlook"finds WEO and the regional outlooks built on it), matched against the full text — not the shortened preview this tool returnsVintage (historical snapshot) dataflows such as
WEO_2025_OCT_VINTAGEare excluded by default; setinclude_vintages=trueto include themPaged:
limit(default 50, max 200) andoffset;total_countreports total matches,returned_countthe page size, and a notice names the nextoffsetwhile matches remainDescriptions are cut to 200 characters here —
imf_get_databaseand theimf://database/{dataflow_id}resource return the full text
imf_get_database tool
Resolves human-readable terms to SDMX dimension codes (e.g. "United States" →
USA) and returns each dimension's DSD concept-scheme labelCountry codes are ISO 3-letter (
USA,GBR,DEU), not ISO 2-letter (US,GB,DE)key_formatnames the exact dot-separated dimension orderimf_query_datasetrequiresCodelist previews are capped at 50 entries by default; set
dimension_idto page one dimension withlimit/offset(max 200), andcodelist_filterapplies before pagingcodelist_filterkeeps codes whose ID or name contains every word given, in any order —"GDP constant prices"findsNGDP_RPCHand its constant-price siblings in WEOSet
available_only=trueto page codes the dataflow actually publishes, with series count and time coverage, instead of the full codelistA
codelist_filterthat matches nothing is reported distinctly from a codelist that could not be resolved — the two need opposite next steps
imf_query_dataset tool
Dot-separated key in DSD keyPosition order;
+combines codes at one position,*matches every code there — every position needs a code or*, a blank segment is rejectedCodes are trimmed and matched case-insensitively (
usa.ngdp_rpch.aqueriesUSA.NGDP_RPCH.A), as isdataflow_id; a code missing from its dimension's codelist fails before the query asinvalid_key_code, naming the nearest valid codes (US→USA), and a*inside a+list fails aswildcard_in_code_liststart_period/end_periodacceptYYYY,YYYY-SN,YYYY-QN,YYYY-MM, or a calendar-validYYYY-MM-DD; each bound covers its whole period (end_period: 2023includes2023-M12)last_n_observations(1–10,000) keeps each series' last N observations —1returns every series' latest value without downloading its history. "Latest" is per series, and a WEO series ends in projection years (2031); with a period bound, the last N inside the rangeReturns
time_period,value,status, and series attributes (unit,scale,decimals); a key resolving to multiple series carries oneseries_metadataentry per series, since attributes can differ between themunit/scaleare upstream codes (PT,USD,XDC,IX,NUM); anullunit means the dataflow publishes none.valueis already in base units, andscaleis the power of ten the IMF publishes the series in —"9"renderspublished in units of 10^9,"0"renderspublished in unitsA response is held to 100,000 serialized characters. With DataCanvas, larger multi-country or long-range results spill to it (
output_mode: "canvas"forces staging);stagedreports storage,truncatedreports only whetherobservationsis an incomplete preview — a staged result can still be untruncatedWithout DataCanvas, a larger result returns its earliest observations with
truncated: true, fullseries_metadata, andretrieval_guidancenaming the lasttime_periodreturned and how to narrow: a narrower key,start_period/end_period,last_n_observations, orCANVAS_PROVIDER_TYPE=duckdb. A key whoseseries_metadataalone overflows fails asresponse_too_largeno_dataerrors carry availability context naming codes that do have coverage; a key with data entirely outside the requested range fails asno_data_in_rangeand reports the range that does
imf_dataframe_describe tool
Lists every table staged on a canvas, with row count and column schema (name + DuckDB type)
Requires
canvas_idfrom a priorimf_query_datasetcall that returnedstaged: trueCall before
imf_dataframe_queryto confirm table and column namesListed only with
CANVAS_PROVIDER_TYPE=duckdb, like the other dataframe tools; without it the landing page shows it disabled with that hint
imf_dataframe_query tool
One read-only SQL
SELECTper call; a leadingWITH … SELECTcommon table expression is accepted, DML and DDL are rejectedResults are capped first by the canvas row limit (default 10,000), then by a 100,000-character serialized response budget —
row_countalways equals the returned rows, andtruncated: truemeans either cap trimmed the resultPage past a cap with a stable
ORDER BYplusLIMIT/OFFSET;response_too_largemeans even one row didn't fit and asks for fewer columns or aggregationListed only with
CANVAS_PROVIDER_TYPE=duckdb
imf_dataframe_drop tool
Removes one named table or view from a canvas without affecting the others; requires the exact name from
imf_dataframe_describeIdempotent — a repeated or absent drop returns
dropped: falserather than an errorDisabled by default; set
IMF_ENABLE_DATAFRAME_DROP=truealongsideCANVAS_PROVIDER_TYPE=duckdbto register it intools/list
imf://database/{dataflow_id} resource
Bounded discovery metadata for one dataflow — every dimension with up to 50 codelist entries, counts,
key_format, name, descriptiondataflow_idcomes fromimf_list_databasesCarries
continuationmetadata pointing toimf_get_database(withdimension_id/limit/offset) for a codelist beyond the preview
Features
Built 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:
Keyless access — no API key required; the IMF SDMX 3.0 portal is fully public
Type-safe SDMX 3.0 compact JSON client with dimension/codelist parsing and DSD validation
Key dimension count validated against the DSD before each query to catch format mismatches early
Dataflow catalog and full availability constraints cached in-session to minimize round trips on multi-step workflows
DuckDB-backed DataCanvas spill for large multi-country or long time-range observations
Agent-friendly output:
Codelist entries carry both the machine code and human-readable label — agents can present meaningful names without a follow-up lookup
key_formatfield in every dataflow response explicitly states the dimension order, removing guesswork for key constructionObservations include each dataflow's own
statusflags (e.g.T,C,NA) so agents can communicate data quality caveats; a missing value flagged only as not available is dropped as paddingCanvas placement is explicit —
stageddistinguishes storage fromtruncatedpreview completeness, and staged results carrycanvas_id,table_name, and retrieval guidance
Getting started
Public Hosted Instance
A 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"
}
}
}Self-Hosted / Local
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/mcpPrerequisites
Bun v1.4.0 or higher (or Node.js v24+).
No API key required.
Installation
Clone the repository:
git clone https://github.com/cyanheads/imf-mcp-server.gitNavigate into the directory:
cd imf-mcp-serverInstall dependencies:
bun installConfigure environment:
cp .env.example .env
# edit .env as needed — no required vars for basic useConfiguration
Variable | Description | Default |
| Set to | — |
| Advertise and enable destructive table-level DataCanvas cleanup. |
|
| IMF SDMX 3.0 base URL. Override for testing or proxied environments. |
|
| Per-request timeout in milliseconds. |
|
| Transport: |
|
| Port for HTTP server. |
|
| HTTP session handling: |
|
| Auth mode: |
|
| Log level (RFC 5424). |
|
| Enable OpenTelemetry instrumentation. |
|
See .env.example for the full list of optional overrides.
Running the server
Local development
Build and run:
bun run rebuild bun run start:stdio # or bun run start:httpRun 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
docker build -t imf-mcp-server .
docker run --rm -p 3010:3010 imf-mcp-serverThe 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.
Project structure
Directory | Purpose |
|
|
| Server-specific env var parsing and validation with Zod. |
| Tool definitions ( |
| Resource definitions ( |
| DataCanvas accessor — wraps the framework canvas instance. |
| IMF SDMX 3.0 API client — dataflow catalog, DSD fetching, data queries. |
| Unit and integration tests mirroring |
| Design notes and directory tree. |
Development guide
See CLAUDE.md/AGENTS.md for development guidelines and architectural rules. The short version:
Handlers throw, framework catches — no
try/catchin tool logicUse
ctx.logfor request-scoped logging,ctx.statefor tenant-scoped storageRegister new tools and resources via the barrels in
src/mcp-server/*/definitions/index.tsWrap external API calls: validate raw → normalize to domain type → return output schema; never fabricate missing fields
Data source
Data 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/.
Contributing
Issues are welcome. Run checks and tests before submitting:
bun run devcheck
bun run testLicense
Apache-2.0 — see LICENSE for details.
This server cannot be deployed
Maintenance
Related MCP Connectors
World Bank Data360 MCP — the World Bank's modern unified data platform.
Query US Treasury national debt, interest rates, exchange rates, and fiscal datasets via MCP.
490+ economic & demographic indicators for 218 countries from IMF, World Bank, UN, FRED.
Related MCP Servers
- AlicenseAqualityDmaintenanceThe server integrates with the free IMF data API and provides various features to facilitate data retrieval and analysis. The server is built using the FastMCP framework and offers the following functionalities:1014Apache 2.0
- AlicenseNot gradedqualityCmaintenanceEnables querying statistical data from China NBS, World Bank, IMF, OECD, BIS, census, and department statistics via MCP tools.Apache 2.0
- AlicenseNot gradedqualityAmaintenanceEnables querying 29,500+ World Bank development indicators for 200+ countries across 60+ years via MCP, with 7 tools for browsing topics, sources, countries, and indicators.1,057 npm3Apache 2.0
- AlicenseNot gradedqualityAmaintenanceEnables searching, exploring, and querying over 1,500 OECD statistical datasets via SDMX, covering national accounts, employment, trade, PISA, health, and more.95 npm2Apache 2.0