Skip to main content
Glama

comtrade_get_bilateral_flows

Read-onlyIdempotent

Retrieve bilateral trade flows between a reporter and partner by product code and period, with values from UN Comtrade for exports, imports, re-exports, or re-imports.

Instructions

Trade between one reporter and one partner, one row per product code and period.

One data/v1/get call for goods (typeCode C), pinned to the total of every breakdown (partner2Code 0, customsCode C00, motCode 0, breakdownMode classic) and with descriptions (includeDesc), so each row is UN Comtrade's figure for the reporter's side of the trade in one product code and period. At TOTAL and chapter level these are mostly UNSD aggregates (is_aggregate true, is_reported false) with no quantity (qty 0, qty_unit_abbr "N/A", net_wgt 0 or None): read the trade values. Rows are TradeFlowRecord, sorted by period, then product code; a code or period upstream holds nothing for has no row. Bounded by construction at product codes times periods rows (at most 12 periods), so there is no count call; a bound above 100,000 raises QueryTooLarge before the call. Arguments are resolved and checked before the call; an unknown area raises UnknownCode, an InvalidRequestError naming the packaged list and the closest area, another mistake InvalidRequestError naming the closest valid value. meta.request holds the get_data arguments that were sent, codes resolved.

Args: reporter: The reporting area, as UN Comtrade's code or its ISO alpha-3 code: "757" or "CHE" Switzerland, "842" or "USA", "276" or "DEU" Germany, "156" or "CHN" China; list_reporters(search=...) finds them. Codes are UN Comtrade's, not ISO numeric (Switzerland is 757, not 756). An alpha-3 code that several codes share resolves to the one still in use ("DEU" is 276, not 280 Fed. Rep. of Germany until 1990). partner: The partner area, as code or ISO alpha-3 code: "842" or "USA" (842, the code the USA reports under, not 840), "276" or "DEU", "0" or "W00" World, the total over all partners; list_partners(search=...) finds them. commodities: Product codes of cl_code, comma-separated, each naming one code: "TOTAL" all goods, an HS chapter "27", heading "2709" or subheading "270900", e.g. "TOTAL,27". Levels such as "AG2" and wildcards such as "27??" are for get_data. list_commodities("HS", search="crude") finds codes. periods: Years "2022,2023" (annual data) or months "202301,202302" (monthly data), comma-separated, at most 12, one format: the format sets freqCode. flow: One trade flow: "X" exports, "M" imports, "RX" re-exports, "RM" re-imports. cl_code: Product classification, "HS" by default: all HS editions as each reporter reported them (rows name the edition in classification_code, e.g. "H6"); an edition "H0" to "H5", SITC "SS" or "S1" to "S4", BEC "B4", "B5" also work. "H6" is valid but upstream answered HTTP 500 to every try on 2026-10-23, so "HS" stays the default. EBOPS "EB", "EB02", "EB10", "EB10S" (services), "BE" and "TM" are accepted but untested with the pinned typeCode C.

Tool call template

Replace each placeholder with a value matching the input schema. Only required parameters are included; add optional parameters as needed.

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "arguments": {
      "reporter": "<reporter>",
      "partner": "<partner>",
      "commodities": "<commodities>",
      "periods": "<periods>",
      "flow": "<flow>"
    },
    "name": "comtrade_get_bilateral_flows"
  }
}

Input Schema

NameRequiredDescriptionDefault
flowYes
cl_codeNoHS
partnerYes
periodsYes
reporterYes
commoditiesYes

Schema Changelog

Changes observed during successful MCP inspections.

  1. First observedv0.1.0

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover the safety profile (readOnly, idempotent, non-destructive, open world), and the description goes well beyond them: pinned request settings, aggregate-only rows at TOTAL/chapter level with is_aggregate/is_reported flags, zeroed quantity fields the caller should ignore, sort order, the empty-row case, the 12-period and 100,000-row limits, QueryTooLarge raised before the call, and named errors (UnknownCode, InvalidRequestError) including which one names the closest valid value.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with a one-line scope statement, then a behavior paragraph, then per-argument notes - a structure an agent can navigate. Some sentences are dense and the 'H6 answered HTTP 500 on 2026-10-23' aside is operationally useful but verbose; overall length is justified by six params at 0% schema coverage.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema and no schema descriptions, the description supplies the return contract (TradeFlowRecord rows, sorted by period then product code, meta.request echoing resolved get_data arguments) and the failure modes. For a bounded, high-complexity query tool this leaves nothing an agent needs unanswered before calling.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description carries the whole burden and largely does: reporter/partner codes with worked examples and the non-ISO-numeric caveat (757 not 756, 842 not 840), ambiguous alpha-3 resolution, commodities grammar with TOTAL/chapter/heading examples, periods format-with-freqCode coupling and the 12 cap, flow enum, and cl_code defaults with edition ranges. Minor gap: cl_code's accepted values are numerous but the interaction of a specific edition with the 'H6 returns HTTP 500' note is left implicit.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening sentence states the exact resource and scope: 'Trade between one reporter and one partner, one row per product code and period.' The following sentence pins the underlying API call and its fixed settings (typeCode C, partner2Code 0, customsCode C00, motCode 0, breakdownMode classic), so the agent knows precisely which cut of the data this returns rather than a generic 'bilateral' query.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It routes the agent explicitly for code lookup (list_reporters, list_partners, list_commodities) and pushes level/wildcard queries to get_data ('Levels such as "AG2" and wildcards such as "27??" are for get_data'). What is missing is a comparison to its closest sibling, get_bilateral_data, whose difference in behavior is never stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.