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.
Note: The UN Comtrade license agreement (§5) prohibits redistributing data without prior written UN permission. Connect with your own Comtrade subscription key.
9 tools covering the full UN Comtrade workflow — reference resolution, trade data retrieval, aggregated rankings, and coverage checking:
| Tool | Description |
|---|---|
comtrade_lookup_countries | Resolve country and area names to Comtrade M49 numeric codes. Accepts partial names or ISO alpha-2/alpha-3 codes. Returns matching entries with validAsReporter flag — regional groupings are valid partner codes but not reporter codes. |
comtrade_search_commodities | Find HS commodity codes by keyword, partial description, or code prefix. Returns codes at 2-, 4-, or 6-digit aggregation with descriptions, parent code, leaf status, and a recommended_query_code field. |
comtrade_list_service_categories | List EBOPS 2010 service trade categories — the services-domain equivalent of comtrade_search_commodities. Returns codes, descriptions, and parent codes. Filter by keyword or browse from a parent code. |
comtrade_get_trade_flows | Fetch bilateral trade flow records. Returns primaryValue (USD, FOB for exports / CIF for imports), quantity, net weight, and period/commodity/partner metadata per row. Accepts multiple periods and commodity codes in one call. |
comtrade_get_trade_balance | Compute trade balance (exports minus imports) for a country over one or more periods with optional commodity filter. Fetches export and import totals in parallel; returns signed balance, component values, and coverage ratio. |
comtrade_get_top_partners | Rank trading partners for a reporter by trade value for a given commodity and flow direction. Returns top N partners sorted by descending value for a single period. |
comtrade_get_top_commodities | Rank commodity categories for a reporter by trade value for a given flow direction and period. Returns top N HS chapters (2-digit) or headings (4-digit) sorted by descending value. |
comtrade_get_services_trade | Fetch international trade-in-services data (EBOPS 2010). Same bilateral structure as goods trade: returns flow value, period, and reporter/partner/category metadata. |
comtrade_get_data_availability | Check which reporter/period/classification combinations have published data before constructing expensive queries. Returns record count and publication date per dataset. |
comtrade_lookup_countriesResolve reporter and partner codes from natural-language names or ISO identifiers.
US), or ISO alpha-3 (USA)role filter: "reporter", "partner", or "any" — narrows results to only valid reporters or all partner areasvalidAsReporter flag on each result — regional groupings (e.g., Africa, ASEAN) are valid as partners but cannot be used as reporter_codeinclude_groups to surface regional aggregate codescomtrade_search_commoditiesFind the HS code for any product before querying trade flows.
"semiconductors", "crude oil")"8471" returns the matching chapter and all descendantsaggr_level: 2 (chapters) to scope a sector, then narrow to 4 or 6 for specific headings or subheadingsrecommended_query_code field on each result — the best level for downstream comtrade_get_trade_flows callscomtrade_get_trade_flowsFetch bilateral trade records — the primary data retrieval tool.
reporter_code + flow_code (M import / X export / RX re-export / RM re-import) + period[] requiredperiod accepts annual (YYYY) or monthly (YYYYMM); pass multiple years as an array for time-series in one request (avoids multiple API calls against the 500-req/day free limit)partner_code: 0 aggregates across all partners (World total) — no partner lookup neededcmd_code[] accepts comma-separated HS codes; omit or use TOTAL for cross-commodity totalstruncated: true + hint when the cap is hit*Desc fieldscomtrade_get_trade_balanceCompute signed trade balance from parallel export + import fetches.
flowCode=X) and import (flowCode=M) requests in parallel, then computes locallybalance (USD, signed), exports, imports, and coverageRatio (exports / imports)cmd_code filter for commodity-specific balance (e.g., energy trade balance)comtrade_get_top_partnersRank trading partners by value for a single period.
limit controls N returned (default 10)comtrade_get_top_commoditiesRank commodity chapters or headings by value for a single period.
aggr_level: 2 for HS chapter ranking (21 sections), 4 for heading rankingpartner_code to scope the ranking to a specific bilateral relationshipcomtrade_get_top_partnerscomtrade_get_data_availabilityCheck data coverage before querying.
reporter_code, period, freq (A annual / M monthly), and classification filterscomtrade_get_services_tradeFetch services trade data (EBOPS 2010 classification).
comtrade_get_trade_flowsservice_code accepts an EBOPS category code — use comtrade_list_service_categories to find the right code| Type | Name | Description |
|---|---|---|
| Resource | comtrade://countries | Complete country/area code list — M49 numeric codes, ISO identifiers, validAsReporter flag, and group membership. Loaded from UN reference data at startup. |
| Resource | comtrade://hs-classification/{level} | Top-level HS commodity hierarchy at aggregation level 2 (chapters), 4 (headings), or 6 (top ~1 200 subheadings). Full leaf enumeration is too large to inject — use comtrade_search_commodities for keyword search. |
All resource data is also reachable via tools. comtrade://hs-classification/{level} provides a browsable hierarchy; for keyword resolution use comtrade_search_commodities instead.
Built on @cyanheads/mcp-ts-core:
none, jwt, oauthin-memory, filesystem, Supabase, Cloudflare KV/R2/D1UN Comtrade-specific:
data/v1/get) and public preview (public/v1/preview) endpoint support — tools fall back to the preview endpoint when no subscription key is setcomtrade_get_trade_balance runs export + import fetches concurrently)*Desc fieldsAgent-friendly output:
truncated: true + hint on any response where the 500-record free-tier cap was hit — agents know when results are incomplete and can narrow the queryisReported flag on trade flow records — distinguishes directly reported values from UN-estimated/aggregated rows so agents can reason about data reliabilityvalidAsReporter on country lookups — prevents agents from constructing invalid queries with partner-only area codesPrerequisites: A UN Comtrade subscription key is optional but recommended. Without one, tools fall back to the public preview endpoint (500 records/call, lower rate limit). With a free-tier key you get the same record cap but higher request headroom.
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"
}
}
}
}
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_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 |
STORAGE_PROVIDER_TYPE | Storage backend: in-memory, filesystem, supabase, cloudflare-kv/r2/d1. | in-memory |
OTEL_ENABLED | Enable OpenTelemetry instrumentation. | false |
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.tsIssues and pull requests 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'.