
Connects Claude to the UN Comtrade database for querying international merchandise and services trade statistics. Nine tools cover the full workflow: resolve country names to M49 codes, search HS commodity classifications by keyword, fetch bilateral trade flows with partner and commodity breakdowns, compute trade balances, rank top partners or commodities by value, and check data availability before expensive queries. Free tier allows 500 records per call and 500 requests per day, so you'll want to use the aggregation and filtering options carefully. Requires your own UN Comtrade subscription key. Reach for this when building trade analysis workflows, export/import dashboards, or policy research tools that need structured access to official trade statistics without scraping Excel files.
Access UN Comtrade international merchandise and services trade statistics — country lookups, HS commodity search, bilateral trade flows, balances, rankings, and data availability — via MCP. STDIO or Streamable HTTP.
Public Hosted Server: https://un-comtrade.caseyjhand.com/mcp
International merchandise and services trade statistics from UN Comtrade. Resolve country and HS commodity codes, fetch bilateral trade flows and services trade, and compute balances, partner/commodity rankings, and data availability from any MCP client. Runs as a stdio process, a local Streamable HTTP server, or the public hosted endpoint above.
| Tool | Description |
|---|---|
comtrade_lookup_countries | Resolve country and area names to Comtrade M49 numeric codes. |
comtrade_search_commodities | Find HS commodity codes by keyword, description, or code prefix. |
comtrade_list_service_categories | List EBOPS 2010 service trade categories by keyword or parent code. |
comtrade_get_trade_flows | Fetch bilateral trade flow records — value, quantity, and weight per period/commodity/partner. |
comtrade_get_trade_balance | Compute a country's trade balance (exports minus imports) across one or more periods. |
comtrade_get_top_partners | Rank trading partners by trade value for a reporter, commodity, and flow direction. |
comtrade_get_top_commodities | Rank commodity categories by trade value for a reporter and flow direction. |
comtrade_get_data_availability | Check which reporter/period/classification combinations have published data. |
comtrade_get_services_trade | Fetch international trade-in-services data (EBOPS 2010). |
| Resource | Description |
|---|---|
comtrade://countries | Complete country/area code list with M49 codes, ISO identifiers, and reporter validity. |
comtrade://hs-classification/{level} | Top-level HS commodity hierarchy at chapter, heading, or subheading level. |
Both resources are also reachable via tools — comtrade_lookup_countries and comtrade_search_commodities cover the same data with keyword search.
comtrade_lookup_countries toolrole filters to "reporter", "partner", or "any" (default)validAsReporter flag on each match — regional groupings (e.g. World, EU) are valid partners but not valid reportersinclude_groups (default true) toggles regional/economic groupings in the resultscomtrade_search_commodities toolclassification selects HS (combined dataset, default) or a specific edition H0–H6aggr_level narrows to 2 (chapter), 4 (heading), or 6 (subheading); omit for all levelslimit defaults to 50; values above 200 return all matches. truncated: true when matches exceed a smaller limitrecommendedQueryCode on each result — the best code to pass as cmd_code in trade queriescomtrade_list_service_categories toolparent_codelimit defaults to 100; values above 500 return all categories. truncated: true when matches exceed a smaller limitid is the service_code for comtrade_get_services_tradecomtrade_get_trade_flows toolreporter_code, flow_code (M import / X export / RX re-export / RM re-import), and period values (YYYY or YYYYMM). Serves the first 12 periods; inputs up to 120 disclose remaining unservedPeriodspartner_code: 0 aggregates all partners (World total); omit for a per-partner breakdownclassification supports HS, H0–H6, and SITC S1–S4/SS. HS search remains HS-only; supply known SITC codes from the selected revisioncmd_code[] serves the first 20 HS or SITC codes; inputs up to 200 disclose unservedCmdCodes. Omitted or empty arrays and ["TOTAL"] request cross-commodity totalstruncated: true plus truncationHint means a raw response reached 500 and may be incomplete; totalCount sums upstream counts before filtering, not a known full match countisReported flags directly-reported rows vs. UN-estimated/aggregated ones; joins country and commodity descriptions from the startup reference cachecomtrade_get_trade_balance toolX) and import (M) calls batch periods in parallel, then compute the balance locallybalanceUsd (signed), exportsUsd, importsUsd, and coverageRatio (exports / imports) per periodcmd_code[] restricts the balance to HS or SITC commodities. Serves 12 periods and 20 codes per call; input ceilings 120/200, with unservedPeriods/unservedCmdCodes for the remaindernotice discloses possibly incomplete balance values when either raw preview flow reaches 500; referenceNotice discloses unavailable SITC descriptions without discarding trade valuesmirrorCaveat on every response — the balance reflects this reporter's own values, not the mirror partner'scomtrade_get_top_partners toolreporter_code + flow_code (M/X) + single period, then sorts retrieved rows locally by valuecmd_code; omit for total merchandise tradelimit partners (default 10); above 50 returns all retrieved partners. Each has rank, primaryValueUsd, and sharePercenttruncated: true when the underlying fetch hit the 500-record capcomtrade_get_top_commodities toolreporter_code + flow_code + single periodaggr_level selects 2 (HS chapter, default) or 4 (heading), requested with AG2/AG4. Omitted partner_code defaults to World (0); explicit partners scope to a bilateral relationshiplimit categories (default 10); above 50 returns all retrieved categories. Each has rank, primaryValueUsd, and sharePercenttruncated: true when the underlying fetch hit the 500-record capcomtrade_get_data_availability toolreporter_code, period, freq (A/M, default A), type_code (C goods / S services, default C), classification (omitted or blank resolves to HS for goods, EB10 for services)totalRecords, firstReleased, and lastReleased, preserving first release and latest revision independently; omit all filters to browse goods availabilitycomtrade_get_services_trade toolcomtrade_get_trade_flows: reporter_code, flow_code (M/X), period values, optional partner_code (0 for all partners combined). Serves the first 12 periods from inputs up to 120, disclosing unservedPeriodsservice_code filters to one EBOPS category; resolve it with comtrade_list_service_categoriestruncated: true plus a truthful truncationHintcomtrade://countries resourceapplication/json — M49 code, ISO identifiers, validAsReporter, and isGroupcomtrade_lookup_countries searchescomtrade://hs-classification/{level} resourcelevel path param accepts 2 (chapters), 4 (headings), or 6 (subheadings); any other value throws a validation errordescription, parent, and isLeaf; full leaf enumeration is too large to inject — use comtrade_search_commodities for keyword searchBuilt 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.
Comtrade-specific:
data/v1/get) and public preview (public/v1/preview) endpoints — tools fall back to the preview endpoint when no subscription key is setcomtrade_get_trade_balance runs export and import fetches concurrently)Retry-After header when present*Desc fieldsAgent-friendly output:
truncated: true plus a recovery hint when a public preview response reaches 500 recordsisReported flag on trade flow records distinguishes directly-reported values from UN-estimated/aggregated rowsvalidAsReporter on country lookups prevents constructing invalid queries with partner-only area codesmirrorCaveat on trade-balance output surfaces the methodological caveat without parsing error textA public instance is available at https://un-comtrade.caseyjhand.com/mcp — no installation required. It runs on the keyless public preview endpoint (500 records per upstream request), splitting served periods into paced requests at least one second apart. Balance needs two requests per period, so longer arrays take more time. Point any MCP client at it via Streamable HTTP:
{
"mcpServers": {
"un-comtrade-mcp-server": {
"type": "streamable-http",
"url": "https://un-comtrade.caseyjhand.com/mcp"
}
}
}
Prerequisites: A UN Comtrade subscription key is optional. Without one, tools use the public preview endpoint (500 records per upstream request). A key selects authenticated access; retrieval and request limits depend on UN Comtrade and the subscription.
Add the following to your MCP client configuration file.
{
"mcpServers": {
"un-comtrade-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/un-comtrade-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info",
"COMTRADE_SUBSCRIPTION_KEY": "your-key-here"
}
}
}
}
Or with npx (no Bun required):
{
"mcpServers": {
"un-comtrade-mcp-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@cyanheads/un-comtrade-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info",
"COMTRADE_SUBSCRIPTION_KEY": "your-key-here"
}
}
}
}
Or with Docker:
{
"mcpServers": {
"un-comtrade-mcp-server": {
"type": "stdio",
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "MCP_TRANSPORT_TYPE=stdio",
"-e", "COMTRADE_SUBSCRIPTION_KEY=your-key-here",
"ghcr.io/cyanheads/un-comtrade-mcp-server:latest"
]
}
}
}
For Streamable HTTP, set the transport and start the server:
MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 COMTRADE_SUBSCRIPTION_KEY=... bun run start:http
# Server listens at http://localhost:3010/mcp
comtrade_lookup_countries, comtrade_search_commodities, comtrade_list_service_categories) never require a key — they query static UN reference files.git clone https://github.com/cyanheads/un-comtrade-mcp-server.git
cd un-comtrade-mcp-server
bun install
cp .env.example .env
# edit .env and set COMTRADE_SUBSCRIPTION_KEY if you have one
All configuration is validated at startup via Zod schemas in src/config/server-config.ts.
| Variable | Description | Default |
|---|---|---|
COMTRADE_SUBSCRIPTION_KEY | Azure API Management subscription key from comtradedeveloper.un.org. Without it, tools use the public preview endpoint (500-record cap). | — |
COMTRADE_API_BASE_URL | Override the Comtrade API base URL. | https://comtradeapi.un.org |
MCP_TRANSPORT_TYPE | Transport: stdio or http. | stdio |
MCP_HTTP_PORT | HTTP server port. | 3010 |
MCP_HTTP_ENDPOINT_PATH | HTTP endpoint path. | /mcp |
MCP_PUBLIC_URL | Public origin override for reverse-proxy deployments. | — |
MCP_SESSION_MODE | HTTP session posture: auto, stateful, or stateless. No tool asks the caller for input mid-handler, so src/index.ts declares stateless and every deployment surface restates it. | stateless |
MCP_AUTH_MODE | Auth mode: none, jwt, or oauth. | none |
MCP_LOG_LEVEL | Log level (debug, info, warning, error). | info |
LOGS_DIR | Directory for log files (Node.js only). | <project-root>/logs |
LOG_TOOL_FAILURE_PAYLOADS | Log failed tool arguments and results, redacted by key name and capped at LOG_TOOL_FAILURE_PAYLOAD_MAX_BYTES (default 16384). Secrets inside free-form values are not redacted. | false |
STORAGE_PROVIDER_TYPE | Storage backend: in-memory, filesystem, supabase, cloudflare-kv/r2/d1. | in-memory |
OTEL_ENABLED | Enable OpenTelemetry instrumentation. | false |
OTEL_EXPORTER_OTLP_ENDPOINT | OTLP base URL for traces (/v1/traces) and metrics (/v1/metrics). | — |
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT | Opt-in OTLP log endpoint, used as-is; the base URL does not enable logs. | — |
See .env.example for the full list of optional overrides.
Build and run:
# One-time build
bun run rebuild
# Run the built server
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 un-comtrade-mcp-server .
docker run --rm -e COMTRADE_SUBSCRIPTION_KEY=your-key -p 3010:3010 un-comtrade-mcp-server
The Dockerfile defaults to HTTP transport, stateless session mode, and logs to /var/log/un-comtrade-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 | Environment variable parsing and validation with Zod. |
src/mcp-server/tools | Tool definitions (*.tool.ts). Nine tools across reference resolution, trade data, and workflow aggregations. |
src/mcp-server/resources | Resource definitions (*.resource.ts). Country list and HS hierarchy resources. |
src/services/comtrade-data | ComtradeDataService — authenticated/preview request builder with retry and key fallback. |
src/services/comtrade-reference | ComtradeReferenceService — reference data loader (countries, HS, EBOPS), startup cache, keyword search. |
src/services/comtrade-meta | ComtradeMetaService — data availability and dataset metadata endpoints. |
tests/ | Unit and integration tests mirroring src/. |
See CLAUDE.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.tsUse UN Comtrade data in accordance with the UN Comtrade license agreement, including its redistribution terms.
Issues are welcome. Run checks and tests before submitting:
bun run devcheck
bun run test
Apache-2.0 — see LICENSE for details.
COMTRADE_SUBSCRIPTION_KEYAzure API Management key from comtradedeveloper.un.org. Optional — without it, tools fall back to the public preview endpoint (500-record cap).
MCP_LOG_LEVELdefault: infoSets the minimum log level for output (e.g., 'debug', 'info', 'warn').
MCP_HTTP_HOSTdefault: 127.0.0.1The hostname for the HTTP server.
MCP_HTTP_PORTdefault: 3010The port to run the HTTP server on.
MCP_HTTP_ENDPOINT_PATHdefault: /mcpThe endpoint path for the MCP server.
MCP_AUTH_MODEdefault: noneAuthentication mode to use: 'none', 'jwt', or 'oauth'.