OECD MCP Server
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., "@OECD MCP Serversearch for PISA data"
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://oecd.caseyjhand.com/mcp
Overview
OECD statistical data via the SDMX 2.1 REST API — 1,500+ dataflows spanning national accounts, employment, trade, education, and health. Search datasets, inspect their dimensions, resolve codes, and query observations, with large multi-country time-series spilling to a queryable DataCanvas table for SQL analysis. Runs as a stdio process, a local Streamable HTTP server, or the public hosted endpoint above.
Tools
Five discovery and data tools plus two SQL analytics tools for large query results:
Tool | Description |
| List OECD SDMX agencies with their directorate and the number of dataflows each publishes |
| Search 1,500+ OECD dataflows by keyword or theme |
| Fetch a dataflow's dimensions, key order, and codelist references |
| Fetch valid codes and labels for one dimension (countries, measures, frequencies) |
| Fetch observations filtered by dimension key and time range; spills large results to DataCanvas |
| List DataCanvas tables and columns staged by a prior |
| Run a read-only SQL SELECT against DataCanvas tables |
Resources
Resource | Description |
| Dimension metadata for a single OECD dataflow — same content as |
All resource data is also reachable via tools. Use oecd_get_dataset_info for the same content.
Related MCP server: OECD Stats MCP
Capability reference
oecd_list_agencies tool
Returns agency IDs (e.g.
OECD.SDD.NAD,OECD.ELS.SPD,OECD.EDU.IMEP) and dataflow counts, sorted descending by countEach agency carries the name of its directorate —
OECD.CTP.TPSis the Centre for Tax Policy and Administration,OECD.SDD.NADthe Statistics and Data Directorate — so a department can be picked without decoding the identifierPublishers outside OECD that ship dataflows through the same catalog (
ESTAT,IAEG-SDGs) carry no directorateUseful for scoping
oecd_search_datasetsby department (national accounts, labour, education, etc.)
oecd_search_datasets tool
Token-matching across dataflow names and descriptions — reaches datasets whose name never carries the term, so
inflationreturnsEconomic Outlook 119andpovertyreturnsIncome inequality - RegionsEach result reports
matched_in(name,description, orboth) and a plain-text description trimmed to 240 charactersOptional
agency_idfilter scopes results to a specific statistical departmentlimit(1–100) andoffsetpage through the match list;total_matchesreports the full countReturns
flow_refvalues (e.g.OECD.SDD.NAD,DSD_NAAG@DF_NAAG_I) — pass directly tooecd_get_dataset_infooroecd_query_dataset. A handful of dataflows are catalogued without a datastructure prefix and come back in the bare{agencyID},{df_id}form (OECD.TAD.ARP,DF_AEI2024_DASHBOARD); both forms are accepted everywhere aflow_refisFetches and filters in-memory; the full catalog is ~5.9 MB and bounded (OECD adds datasets weekly, not continuously)
oecd_get_dataset_info tool
Returns all dimensions in key order (position 1, 2, 3 …) — dimension order is required to construct the dot-delimited key for
oecd_query_datasetEach dimension carries its concept name from the datastructure's concept scheme, so
INSTR_ASSETreads as "Financial instruments and non-financial assets" rather than repeating the id. A dimension the scheme does not cover keeps the idShows codelist references for each dimension — pass to
oecd_get_dimension_valuesto resolve human-readable names to SDMX codesSurfaces
NonProductionDataflowflag — marks experimental or deprecated dataflowsResolves a
flow_refwhose id prefix names no datastructure of its own by asking the dataflow for its structure —OECD.CFE.EDS,DSD_REG_LAB@DF_RATESis backed byDSD_REG_LABOUR, and answers here rather than reporting the dataflow as missingRequired before calling
oecd_query_dataseton an unfamiliar dataflow
oecd_get_dimension_values tool
Returns code + label pairs for a single dimension (e.g.
REF_AREA→USA/United States,DEU/Germany)querymatches a case-insensitive substring against both the code and its label, soPAandpercenteach reachPA/Percent per annumlimit(1–500, default 50) andoffsetpage the matching list. Both client surfaces carry the same page, so a 1,164-code dimension likeUNIT_MEASUREno longer ships 66 KB of pairs tostructuredContentto find one codeWhen matches remain beyond the page, the response reports the full match count and how to reach the rest
oecd_query_dataset tool
Dot-delimited key (e.g.
A.USA+DEU.B1GQ_R.PC.) with+-separated multi-values and empty wildcard segments; optionalstart_period/end_periodbound the range (ISO format:2010,2010-Q1)SDMX-JSON decoded into row objects — every dimension and observation attribute (
UNIT_MULT,OBS_STATUS,PRICE_BASE,DECIMALS, …) becomes its own column, so an estimated or break-flagged point is distinguishable from a confirmed onevalueis pre-multiplied byvalue_scale(the observation's unit multiplier) — a GDP figure OECD publishes as26054.614billions comes back as26054614000000; divide byvalue_scalefor the figure as OECD published it. Every row carriessource: "OECD"Small results return every observation inline with no
canvas_id; large results (multi-country, multi-year) spill to DataCanvas (CANVAS_PROVIDER_TYPE=duckdb) withtruncated: trueplus acanvas_id/table_nameforoecd_dataframe_describeandoecd_dataframe_query; without DataCanvas every row still returns instructuredContent, but the rendered table caps at a preview slice, reported viacontent_table_capped
oecd_dataframe_describe tool
Lists table and view names, row counts, and column names/types staged on a DataCanvas by a prior
oecd_query_datasetspillTakes the
canvas_idoecd_query_datasetreturnedOnly available when
CANVAS_PROVIDER_TYPE=duckdbis set — call beforeoecd_dataframe_queryto discover exact table and column names for SQL
oecd_dataframe_query tool
Runs a single read-only SQL
SELECTagainst the staged tables — aggregates, window functions, GROUP BY, ORDER BY, and standard DuckDB SQLWrites, DDL, and system-catalog access are rejected
Results capped at the canvas row limit;
row_countreports the full count before the capOnly available when
CANVAS_PROVIDER_TYPE=duckdbis set
oecd://dataflow/{agency_id}/{flow_id} resource
Dimension metadata for a single OECD dataflow as
application/json— same content asoecd_get_dataset_info{flow_id}is the combined{dsd_id}@{df_id}string with@percent-encoded as%40, or the bare{df_id}for a dataflow catalogued without a datastructure prefixExample:
oecd://dataflow/OECD.SDD.NAD/DSD_NAAG%40DF_NAAG_I
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.
OECD-specific:
Keyless access — no API key required; OECD SDMX 2.1 REST API is fully public
Covers 1,500+ dataflows across 20+ OECD statistical departments (national accounts, employment, inflation, trade, education, health, environment, taxation, inequality)
Delegated dataflows and codelist revisions resolved end to end — a dataflow OECD catalogues on one service root but defines on another follows the catalog's own link for structure, codes, and observations, and codes come from the revision the datastructure names rather than the endpoint's current latest
AllDimensionsobservation mode — one-pass SDMX-JSON decoding into flat row objects, no nested series key reconstructionoecd_query_datasetmaterializes large observation sets (multi-country time-series) on a DuckDB DataCanvas for in-conversation SQL analytics
Agent-friendly output:
Workflow-aware tool surface —
flow_reffrom search flows directly into info, values, and query tools without reconstructionSpill signaling —
truncated: true+canvas_idtells the agent to switch to SQL instead of parsing a truncated inline listFull SDMX decoding server-side — agents see
{ REF_AREA: "United States", MEASURE: "Gross domestic product", UNIT_MULT: "Billions", value: 26054614000000, value_scale: 1000000000 }, not raw index arrays
Getting started
Public Hosted Instance
A public instance is available at https://oecd.caseyjhand.com/mcp — no installation required. Point any MCP client at it via Streamable HTTP:
{
"mcpServers": {
"oecd-mcp-server": {
"type": "streamable-http",
"url": "https://oecd.caseyjhand.com/mcp"
}
}
}Self-Hosted / Local
Add the following to your MCP client configuration file.
{
"mcpServers": {
"oecd-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/oecd-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info"
}
}
}
}Or with npx (no Bun required):
{
"mcpServers": {
"oecd-mcp-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@cyanheads/oecd-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info"
}
}
}
}Or with Docker:
{
"mcpServers": {
"oecd-mcp-server": {
"type": "stdio",
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "MCP_TRANSPORT_TYPE=stdio",
"ghcr.io/cyanheads/oecd-mcp-server:latest"
]
}
}
}To enable DataCanvas SQL analytics for large query results, add CANVAS_PROVIDER_TYPE=duckdb:
{
"mcpServers": {
"oecd-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/oecd-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"CANVAS_PROVIDER_TYPE": "duckdb"
}
}
}
}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 — OECD SDMX is a free, public API.
Installation
Clone the repository:
git clone https://github.com/cyanheads/oecd-mcp-server.gitNavigate into the directory:
cd oecd-mcp-serverInstall dependencies:
bun installConfigure environment:
cp .env.example .env
# edit .env — most vars are optional; no API key requiredConfiguration
All configuration is validated at startup via Zod schemas in src/config/server-config.ts. Key environment variables:
Variable | Description | Default |
| OECD SDMX REST API base URL. Must be an https origin that answers directly — no redirect is followed, so a plaintext |
|
| Per-request timeout in milliseconds. |
|
| Canvas engine. Set to |
|
| Transport: |
|
| Port for HTTP server. |
|
| HTTP session posture: |
|
| Auth mode: |
|
| Log level (RFC 5424). |
|
| Directory for log files (Node.js only). |
|
| Enable OpenTelemetry instrumentation. |
|
See .env.example for the full list of optional overrides.
Running the server
Local development
Build and run:
# One-time build bun run rebuild # Run the built server 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 oecd-mcp-server .
docker run --rm -p 3010:3010 oecd-mcp-serverThe Dockerfile defaults to HTTP transport, stateless session mode, and logs to /var/log/oecd-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 environment variable parsing and validation with Zod. |
| Tool definitions ( |
| Resource definitions ( |
| Shared OECD fetch boundary — timeout and retry-classification corrections used by both services below, the origin check every delegated service root passes before it is addressed, the refusal of any redirect off the configured host, and the classification that gives an upstream refusal the same declared reason on every tool and resource. |
| OECD SDMX structure service — dataflows, data structures, codelists. |
| OECD SDMX data service — observations, SDMX-JSON decoding, DataCanvas spillover. |
| DataCanvas accessor — registers and exposes the framework canvas instance to tools. |
| Unit and integration tests mirroring |
Development guide
See CLAUDE.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/*/index.tsWrap external API calls: validate raw SDMX-JSON → normalize to domain type → return output schema; never fabricate missing fields
Contributing
Issues are welcome — see CONTRIBUTING.md for what makes one actionable, and CODE_OF_CONDUCT.md for how we work together. 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
Query IMF SDMX 3.0 macroeconomic dataflows — WEO, BOP, CPI, exchange rates, 190 countries.
Macroeconomic and other official data from 170+ publishers, resolved from natural language with provenance.
Global economic data from World Bank and OECD
UK Office for National Statistics dataset catalogue + Beta JSON API
Related MCP Servers
- AlicenseAqualityFmaintenanceProvides AI assistants access to over 5,000 OECD economic and statistical datasets via the SDMX API for search, analysis, and comparison across 38 countries.929 npm8MIT
- AlicenseAqualityBmaintenanceProvides OECD statistical data (employment, wages, etc.) through SDMX API, supporting Korean-language queries. Enables listing indicators, retrieving stats, trends, comparisons, and rankings among OECD countries.8MIT
- AlicenseAqualityBmaintenanceEnables querying, exploring, and downloading ISTAT statistical datasets via SDMX REST API, with unified metadata, territorial code resolution, and data extraction.7MIT
- 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