Skip to main content
Glama

tariff-resolver

npm version CI coverage: ≥95% lines, CI-enforced npm downloads node MCP Registry license: MIT

An MCP server that turns your AI assistant into a US import duty research tool — built on official USITC Harmonized Tariff Schedule data (US Government public domain, 35,000+ tariff lines).

  • 🔍 HTS code candidates from plain product descriptions, with CBP CROSS ruling links

  • 🧮 Landed-cost components: MFN/FTA base rates + Chapter 99 additional duties (IEEPA / Section 301 / 232) + MPF/HMF fees

  • 📡 Tariff change tracking: watchlist your HTS codes, diff rates between HTS revisions

  • 🤖 AI-optimized, hallucination-resistant: returns the actual Chapter 99 rule text with parsed rates, so your LLM reasons over real exception chains instead of inventing 2024-era numbers

Demo: resolving duties for a vacuum flask from China, then switching product and origin — the full Chapter 99 stack recalculates live

Why now: since the de minimis exemption ended (Aug 29, 2025), every US-bound shipment needs an HTS code and duty payment — and 2025–26 rates keep changing by executive order.

Not affiliated with any government agency. Outputs are candidates/estimates for pre-broker screening — not customs, legal, or tax advice. Estimates exclude AD/CVD duties.

Install

Requires Node.js ≥ 18.

claude mcp add tariff-resolver -- npx -y tariff-resolver

Or in any MCP client config:

{ "mcpServers": { "tariff-resolver": { "command": "npx", "args": ["-y", "tariff-resolver"] } } }

Claude Desktop (one-click): download tariff-resolver-<version>.mcpb from Releases and double-click it — no terminal needed.

Related MCP server: tariffmonitor-mcp

💡 Try these prompts

  • Basic search: "Find the HTS code for a men's 100% cotton t-shirt."

  • Full scenario: "Calculate the tariff scenario for HTS 6109.10.00, origin China, customs value $5,000, ocean freight."

  • Sourcing decision: "I'm importing $10k of stainless steel vacuum flasks. Compare landed cost if I source from China vs Vietnam."

  • Stay current: "Watch tariff changes for my catalog: 6109.10.00, 8507.60.00, 9617.00.10."

Tools

Tool

What it does

search_hs_candidates

Product description → top HTS candidates with rates + CBP CROSS ruling links

calculate_tariff_scenario

HTS code + origin + value (+ weight) → structured JSON: base MFN/FTA rate, candidate Chapter 99 layers with per-layer match/confidence, sourced possibly_expired bucket, MPF/HMF

watch_tariff_changes

Register HTS codes to a local watchlist

check_tariff_updates

Diff current vs previous HTS revision — see exactly which rates changed

dataset_info

Data revision date, row counts, source, license

Design

The server does the retrieval; your LLM does the reasoning. Chapter 99 rules are returned verbatim (with parsed adder_pct where applicable) so the model reads the actual exception chains instead of trusting a black-box calculation. Rates for 10-digit statistical suffixes inherit from their parent rate line. Headings the schedule marks as dead — terminated, suspended, expired — are filtered out and counted, and the USITC's own compiler_note rides along with any rule that carries one.

Status overrides. data/status_overrides.json is a short, sourced list of Chapter 99 headings whose collection has stopped, expired, or been suspended even though the schedule still prints them. A layer matching an entry is returned under possibly_expired with the entry's status, reason, source URL and as_of date instead of in layers. Every entry carries a CBP, Federal Register or USITC source; pull requests adding entries must include one.

What the data cannot tell you. The published schedule is wrong in both directions at any given moment, so every result carries a stacking_warning and the snapshot date. Provisions whose collection has already stopped keep printing with no end date — IEEPA and Section 122 headings are the recurring case — and newly proclaimed actions appear in the schedule days after they take effect. Totalling every layer the schedule prints yields a rate nobody is charged. Treat the layers as candidates, and verify collection status against CBP CSMS messages before relying on a stack.

One core, two front doors. All duty logic lives in tariff-resolver/core (pure TypeScript, no filesystem or network): resolveDuty(dataset, { hts, origin, value_usd?, ocean? }) — origin takes an ISO-3166 alpha-2 code or an English country name — returns the base line, separate MPF/HMF, every candidate Chapter 99 layer with match and confidence, a sourced possibly_expired bucket, and the snapshot date. The MCP tool calls it; so can any Node or edge runtime. A country name that is not recognised returns the ORIGIN_UNKNOWN error rather than a partial match, so a misspelled origin can never quietly resolve to a thinner stack of layers.

Data

Ships with a full HTS snapshot, fetched from USITC's official JSON API (US Government public domain). Refresh anytime:

python3 scripts/fetch_hts.py   # ~2 min, fails hard rather than write a partial dataset

dataset_info reports the revision date your queries run against.

Privacy Policy

tariff-resolver runs entirely on your machine and collects nothing:

  • Data collection: none. No queries, telemetry, analytics, or usage data are collected or transmitted.

  • Usage and storage: your watchlist is stored in a local JSON file on your machine; all lookups run against the bundled local dataset.

  • Third-party sharing: none. The server makes no network requests at runtime. (The optional scripts/fetch_hts.py refresh script contacts only the official USITC API.)

  • Data retention: nothing to retain — delete the local watchlist file at any time.

  • Contact: tom@opsloft.dev

Full policy: https://opsloft.dev/privacy

License

MIT. Tariff data is a work of the US Government (public domain).

Available Tools

5 tools
calculate_tariff_scenarioCalculate tariff scenarioA
Read-only

Returns the HTS code's MFN/FTA base rate, ALL active chapter 99 rules (IEEPA/301/232 additional duties) matching the origin as verbatim text, and MPF/HMF fees. The LLM should walk the chapter-99 exception chains itself to stack the right duty layers, explain each step to the user, and always note this is an estimate.

Inputs: hts_code (required), origin_country (required), customs_value_usd (required), quantity, +2 more.

check_tariff_updatesCheck tariff changes between revisionsD
Read-only

Compares the current HTS snapshot with the previously fetched one. Call without codes to check the whole watchlist. Returns each change: code, column (general/special/other/additionalDuties), old → new value.

Inputs: hts_codes.

dataset_infoDataset infoA
Read-only

Fetch date, source, license, row counts — use to check data freshness.

Inputs: no named parameters.

search_hs_candidatesSearch HTS code candidatesA
Read-only

Returns top 8-10 digit HTS code candidates (with MFN/FTA rates and CBP CROSS ruling links) for a product description. Results are CANDIDATES for pre-broker screening, not a classification ruling. IMPORTANT: the HTS uses legal terminology, not trade names — BEFORE CALLING, rewrite the product description into HTS-style material + use nouns (e.g. 'pink kids backpack' → 'travel bags of man-made fibers'; 'water bottle' → 'vacuum flask' or 'bottle of plastics'). If you get 0 results, retry with 2-3 different phrasings.

Inputs: product_description (required), limit.

watch_tariff_changesWatch HTS codes for tariff changesA
Idempotent

Saves HTS codes (with optional origin) to a local watchlist. After each dataset refresh, call check_tariff_updates to see whether the rates on these codes changed. This is how you track 2025-2026 tariff volatility without manual re-checking.

Inputs: hts_codes (required), origin_country.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    B3.2/5.0

    Scored across 5 tools

    Disambiguation5/5

    Each tool has a clearly distinct role: candidate search, detailed scenario calculation, watchlist management, update checking, and dataset metadata. Even the paired watch/check tools are unambiguous because one saves codes and the other compares snapshots.

    Naming Consistency4/5

    Four tools follow a consistent verb_noun pattern: search_hs_candidates, calculate_tariff_scenario, watch_tariff_changes, check_tariff_updates. dataset_info breaks the pattern as a noun-only name, which is a minor deviation but not confusing.

    Tool Count5/5

    Five tools is well-scoped for a focused tariff-resolution server. Each tool covers a distinct part of the workflow without redundancy or unnecessary breadth.

    Completeness4/5

    The core workflow is covered: search candidates, calculate duty scenarios, track changes, and verify data freshness. A minor gap is that watch_tariff_changes has no corresponding unwatch or list-watchlist tool, so watchlist management is slightly incomplete.

    Maintenance

    ActivityStale
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      C
      maintenance
      Enables AI agents to search EU/French customs codes, get duty rates, and monitor tariff changes via natural language, using the DouaneCode API.
      MIT
    • A
      license
      A
      quality
      C
      maintenance
      Live US import tariff calculator covering 19,856 HTS codes, allowing AI to look up stacked tariff rates and project the November 10, 2026 cliff impact on any product.
      2
      739 npm
      MIT
    • A
      license
      Not graded
      quality
      C
      maintenance
      Provides access to US import tariff rates via the USITC Harmonized Tariff Schedule, enabling natural language queries for tariff data.
      127 npm
      MIT
    • A
      license
      Not graded
      quality
      C
      maintenance
      Enables AI agents to search Chinese HS commodity codes, retrieve detailed tariff and regulatory information, and calculate import taxes using 2026 import/export tariff data.
      MIT