Skip to main content
Glama
annayastremska

Import Sourcing Advisor

进口采购顾问

一个面向乌克兰宏观层面进口采购筛选的领域特定数据代理。 询问它某个产品组应从哪些国家采购,它会通过开放的贸易数据来处理这个问题:哪些原产地实际供应该产品、供应集中度如何、每个候选国的到岸成本是多少,以及候选国之间的排名如何。

该代理通过两个 MCP 连接进行扩展:

服务器

角色

现有

Microsoft Playwright MCP

读取乌克兰当局仅以网页形式发布的当年贸易额数据,以便代理了解其统计数据有多陈旧

自定义

trade-sourcing-mcp(本仓库,mcp_server/)

针对 UN Comtrade、World Bank Indicators API 和 WITS TRAINS 的五个工具

一切均基于公开数据运行,无任何机密输入,且自定义服务器不需要任何形式的 API 凭据。

你首先看到的内容

一个工作清单,而不是聊天框。六条受跟踪的进口产品线,每行一条,按风险等级和金额排序:主要供应商、其份额、该份额的价值、其背后有多少有效原产地,以及一个单词的状态。展开一行会在原地展开其原产地详情;代理运行是从那里开始的刻意操作。

列表上方是一条聚合信息条。在当前窗口内:进口额 5.54 亿美元,其中 3.46 亿集中在每条产品线的单一原产地(62%),土耳其领先 6 条产品线中的 3 条——占风险敞口的 1.83 亿。 最后一个数字是任何按产品报告都无法显示的:会同时失败的产品线。

该列表是计算出来的,而非推理出来的。web/portfolio.py 打开一个 MCP stdio 会话,连接到代理使用的同一个自定义服务器,并直接调用工具,没有模型参与。访客加载的第一个屏幕不应等待代理或产生任何费用。

货币。 年度贸易序列滞后约两年,因此列表基于月度报告构建的滚动十二个月窗口运行,结束于源数据实际发布到的月份——目前为 2024 年 10 月至 2025 年 9 月,比最新的完整年度提前约十一个月。这并非表面功夫:在 2024 年年度数据上,新鲜番茄显示 71.8% 来自土耳其,并带有单一来源标志;在窗口数据上则为 64.6%,且没有该标志。


Related MCP server: supply-chain-mcp-server

先决条件

要求

测试版本

原因

Python

3.13.3

自定义 MCP 服务器、代理、Web 应用

Node.js

22 LTS

仅用于 Playwright MCP,它通过 npm 分发

Claude Code CLI 或 Anthropic API 密钥

CLI 2.1.232

代理运行在 Claude Agent SDK 上

git

2.49

—

三个数据 API 均不需要任何密钥、令牌或账户。


安装

git clone <repository-url> logistics_mcp
cd logistics_mcp

python -m venv .venv
# Windows
.venv\Scripts\activate
# macOS / Linux
source .venv/bin/activate

pip install -r requirements.txt

安装浏览器服务器和 Chromium 构建一次(PATH 上需有 Node 18+):

npm install
npx -y playwright install chromium

npm install 固定了 @playwright/mcp,代理随后将其作为 node node_modules/@playwright/mcp/cli.js 启动。它不通过 npx:在 Windows 上没有名为 npx 的可执行文件,且 Node 在没有 shell 的情况下拒绝生成 npx.cmd,因此 以该名称启动服务器会静默失败——运行继续,模型报告它没有浏览器工具。如果没有 npm install,代理会回退到 npx -y @playwright/mcp@latest,在 POSIX shell 能解析它的情况下有效。


配置

cp .env.example .env

.env 被 git 忽略。其中没有任何内容是自定义 MCP 服务器所必需的;这些值仅 影响代理和数据传输模式。

变量

默认值

含义

ANTHROPIC_API_KEY

未设置

代理的模型凭据。如果未设置,Claude Agent SDK 会回退到本地 Claude Code 登录(claude → /login)。两者只需其一。

SOURCING_ANALYSIS_MODEL

claude-sonnet-5

用于完整采购运行的模型。与 Opus 在同一运行上对比:两者均通过,595 秒对 620 秒,$0.398 对 $0.547,且 Sonnet 走完了整个时效性回退链,得到了可用数字,而 Opus 中途停止

SOURCING_CHAT_MODEL

claude-haiku-4-5

用于对已计算结果进行后续提问的模型:无浏览器,三个只读工具

SOURCING_MODE

live

live 调用开放 API,record 同时写入夹具,replay 从夹具提供数据,无网络访问

SOURCING_CACHE_TTL

86400

保留本地响应缓存(.cache/,git 忽略)的秒数


独立运行各个部分

自定义 MCP 服务器是一个独立进程,单独启动。它不依赖代理。

1. 自定义 MCP 服务器

python -m mcp_server.server

它通过 stdio 提供 MCP 服务,并在启动时将传输方式和数据模式打印到 stderr。要完全无需代理检查它发布的契约:

python scripts/inspect_tools.py           # summary of all five tool contracts
python scripts/inspect_tools.py --json    # full input and output JSON schemas

或使用官方检查器驱动它:

npx -y @modelcontextprotocol/inspector python -m mcp_server.server

2. Playwright MCP 服务器

代理自行生成它;仅为了检查才手动运行。

node node_modules/@playwright/mcp/cli.js --headless --isolated

3. 代理和 Web 应用

python -m web.app          # serves http://127.0.0.1:8000

Web 应用将两个 MCP 连接作为子进程启动,并显示每个连接暴露了哪些工具。


验证安装

python -m pytest tests -q        # 47 unit tests, no network, ~2s
python scripts/smoke_tools.py    # calls every tool end to end against the live APIs
REPLAY=1 python scripts/smoke_tools.py   # the same run, offline, from fixtures
python scripts/run_e2e.py        # the whole agent flow, both MCP servers, live
python scripts/run_failure_demo.py       # the same flow with the browser server broken

run_e2e.py 是演示所依赖的检查。除非两个服务器 都连接成功且全部五个自定义工具都被实际调用,否则它会使运行失败——如果自定义服务器 未能启动,运行仍会产生流畅的答案,因为模型只会报告它没有工具。每个事件都写入 scripts/last_e2e_trace.jsonl,以便之后检查运行,而不是仅凭信任。完整运行大约需要 10 分钟、20 轮对话和约 $0.55。在回退时效性 URL 上的导航失败,只要链中另一个页面已加载,就会被容忍——链是有序的,代理在第一个回答的页面处停止——但链中没有任何页面加载,以及自定义服务器的每个错误,仍会使运行失败。

run_failure_demo.py 是另一半:它将浏览器指向一个无法解析的主机,且没有回退, 并且仅当导航报告为错误、其他一切正常、且推荐结果中仍包含失败的检查名称时,才通过。要求不是“什么都不失败”——而是失败能与空答案区分开来。


离线 / 重放模式

自定义服务器调用三个网络 API,因此真实响应记录在 fixtures/ 下,可以在无网络访问的情况下重放:

# Offline
SOURCING_MODE=replay python -m mcp_server.server

# Re-record after changing a query
SOURCING_MODE=record python scripts/smoke_tools.py

替换发生在传输边界(mcp_server/sources/http.py):重放 返回与网络返回相同的原始 JSON,其上的每个解析器、去重步骤和 计算都原样运行。没有代码路径返回准备好的答案。

每个夹具都是一个信封,记录确切的 URL、检索时间戳和逐字的 响应体。

离线覆盖的内容。 产品组合、每个产品在落地屏幕上的排名, 以及代理流程。通过实时运行一个产品的排名并在重放模式下运行,比较每个字段来验证:完全相同到小数点后最后一位。这个检查值得保留——正是它发现了下面的关税错误,在排名夹具记录之前,也是它发现了折叠的离线分数。

它不覆盖的内容。 只记录了一个参考窗口(2024 年 10 月 – 2025 年 9 月),因此对任何其他尾随窗口的请求在离线模式下会失败,而不是回退。两个产品有一个候选在两种模式下都无法定价——杏仁的 USA 和 NLD,猕猴桃的 AZE 报告没有重量,因此无法推导出单位价值。这些行在屏幕上标记为不完整,并在注意事项中说明;它们是源数据中的缺口,而非记录中的缺口。


数据源

来源

端点

认证

提供内容

UN Comtrade(预览)

comtradeapi.un.org/public/v1/preview

无

按 HS 编码、伙伴和年份报告的贸易:重量、价值、单位价值

World Bank Indicators

api.worldbank.org/v2

无

物流绩效指数及子指数、集装箱港口吞吐量

WITS TRAINS

wits.worldbank.org/API/V1/SDMX/V21

无

按 HS6 应用的最惠国进口关税

Comtrade 参考文件

随附于 data/reference/

无

HS2022 术语、国家代码——预览 API 仅返回代码

国家海关总署

网页,通过 Playwright MCP

无

当年营业额,仅以 HTML 发布。对自动化客户端返回 403,因此首先尝试,通常会失败

乌克兰国家银行

网页,通过 Playwright MCP

无

外部部门统计指数——时效性检查的可达回退

已验证的端点行为、速率限制和怪癖记录在 docs/01-data-sources-verified.md 中。


仓库布局

mcp_server/          Custom MCP server (separate process)
  server.py          Five tool registrations, stdio entry point
  models.py          Pydantic input/output contracts
  sources/           http (rate limit, cache, fixtures), comtrade, worldbank, wits, reference
  domain/            costing and analysis calculations
agent/               Claude Agent SDK wiring, two model tiers, trace events
web/                 FastAPI application, portfolio over MCP, single-page UI
  app.py             Endpoints: portfolio, commodity detail, agent run, chat
  portfolio.py       The tracked lines, queried over an MCP stdio session
  index.html         Portfolio screen, line detail, MCP trace, chat panel
data/reference/      Vendored HS2022 and country reference data
fixtures/            Recorded genuine API responses for replay mode
scripts/             inspect_tools, smoke_tools, run_e2e
tests/               Unit tests
docs/                Requirements digest, verified sources, contracts, rationale, demo script

文档

文档

内容

docs/00-assignment-requirements.md

任务要求的精简说明

docs/01-data-sources-verified.md

每个实时探测的数据源:端点、实际值、限制、注意事项

docs/tool-contracts.md

每个自定义工具及所用 Playwright 工具的完整契约

docs/design-rationale.md

为何选择这些服务器、为何每个工具位于 MCP 边界、权衡与限制

docs/demo-checklist.md

演示脚本


已知限制

事先说明,而非隐藏:

  • 运费为估算值,而非报价。 没有开源数据源发布运费率。每个估算数字在工具输出中均标注为 estimated。

  • 关税采用最惠国税率。 WITS 对优惠税率返回 HTTP 404,因此欧盟 DCFTA 等协定会被标记为可能适用,但不会实际应用。

  • 年度序列滞后约两年。 2026 年 8 月,乌克兰已报告 2024 年数据,但尚未报告 2025 年。月度序列截至 2025 年 9 月,工作清单使用的正是该序列。到岸成本与排名工具仍基于年度序列运行,关税再次来自较早的观测值——每个结果都会注明其依据。

  • 单位价值并非价格。 Comtrade 的单位价值是总价值除以总重量,而非报价。

  • 物流绩效指数并非年度序列。 2022 年是最新的观测值。

  • 海关页面会拦截自动化客户端。 customs.gov.ua 在其 Akamai 边缘节点对任何非人工浏览器返回 HTTP 403,而人工访问则正常打开。因此,时效性检查步骤会回退到国家银行的外部部门页面,代理会注明其实际读取的页面。这能确认发布版本,但无法确认成交额数据,因此时效性检查是设计上的部分检查,而非偶然。

  • 产品组合为六条产品线,按信号强度选取。 苹果(HS 080810,50 万美元)和带壳核桃(HS 080231,接近零)被剔除:乌克兰本国种植并出口这两类产品,因此其进口数据为噪声。

  • 这是一个筛选工具。 它缩小值得调查的国家名单;它不能替代招标。

Related MCP Connectors

Related MCP Servers