Skip to main content
Glama
HugoOu
by HugoOu

Commerce MCP Gateway

在 Agent 与商户 / 支付 MCP Server 之间,执行可验证的授权、预算、审批与审计。

把「一次调用是否合法」扩展为「整条交易是否合法」。

CI License: MIT Python 3.12 MCP 2026-07-28

中文 · English

这是一个面向 Agentic Commerce / AI Pay 的治理型 MCP Gateway demo。它把 Agent Harness 的 Control Plane 做成可执行、可测试、可复算的代码,而不是停留在架构图里。它不是生产支付网关,也不声称能单独防住提示词注入。

为什么做这个

Agent 可以让每一次工具调用看起来都合法,但整条交易仍然是错的:

  • 先完成订单,再扣款——用户拿到货,钱却没付;

  • 只捕获商品小计,少付运费和税;

  • 同一个购物车创建两个支付 intent,扣两次;

  • 把一次授权拆成多笔购买;

  • 用一个可拼出来的假支付令牌完成订单;

  • 商户在结算时把报价从 49.99 改成 60.00。

这些不是「某一次调用参数不合法」,而是 跨调用的交易上下文 没有被绑定。本项目用五条不变量把边界写进执行点,并为每一条留下测试或明确的边界说明。

Related MCP server: dingdawg-agent-wallet

在 Agent Harness 中的位置

平面

典型职责

本项目

Orchestration Plane

Agent Loop、模型调用、工具选择、上下文管理

只保留一个约 100 行的薄 driver,用来把网关放进真实回路

Control Plane

授权、预算、审批、审计、策略执行

本项目的主体

这样可以单独讨论一个经常被含糊带过的问题:谁有权替用户花钱,凭什么,花完之后拿什么证明。

架构

flowchart LR
  subgraph OP["Orchestration plane"]
    A["Agent / Harness<br/>thin loop · MCP client"]
  end

  subgraph CP["Commerce MCP Gateway · control plane"]
    F["Front door<br/>Streamable HTTP + stdio"]
    E["Enforce<br/>single execution point"]
    P["Policy<br/>deny by default"]
    B["Budget<br/>reserve / commit / release"]
    AP["Approval<br/>durable queue"]
    S["Sanitize<br/>injection screening · PII"]
    V["Evidence<br/>hash chain · replay"]
  end

  M["Mock merchant MCP"]
  PS["Mock PSP MCP<br/>fault injection"]
  DB[("SQLite<br/>budget · approvals · ledger")]

  A --> F
  F --> E
  E --> P
  E --> B
  E --> AP
  E -->|"allow"| M
  E -->|"allow"| PS
  M --> S
  PS --> S
  S -->|"sanitized result"| A
  E --> V
  B --> DB
  AP --> DB
  V --> DB

所有被拦截的方法调用走同一条路径:

authorize → decide → enforce → record_pending → forward
          → sanitize → settle → record_done

record_pending 在转发之前落盘,保证 证据先于副作用。没有第二条可以绕过 enforce 的写路径。

五条不变量

编号

不变量

当前证据

I1

不存在未经 Decision 就放行的方法调用

单一执行点、分层契约、T1–T9、139 passed / 1 xfailed

I2

sum(committed) + sum(active holds) ≤ limit

50 路并发 reserve,0 超支

I3

篡改任一证据记录必然 verify 失败

4/4 篡改场景检出,干净链通过

I4

同一证据包可以重构决策序列

6/6 条可重构,输入件撤下后链仍可验

I5

跨调用交易一致性:一个 checkout 一个有效 intent、完成前必须 capture、金额与 token 绑定、mandate 限制交易笔数

demo 版已落地;仅单进程成立

I5 是后来补上的架构层:P0 状态攻击证明 I1–I4 全部成立时,整条交易仍然可能免单、少扣或双扣。这个发现和修复过程保留在 评测文档 与 决策记录 中。

实际执行了什么

  • 默认拒绝:工具、商户、金额、资源 URI 不在策略内就不放行;

  • 两阶段预算:reserve → commit / release,SQLite WAL + 进程内单写者 + 数据库约束;

  • 审批绑定动作:协议原生 input_required / MRTR,CLI 兜底;审批绑定 action_hash,老客户端 fail-closed;

  • 可验证证据:哈希链 + 运行证据包 + Merkle 根;链上只留摘要,可复算输入单独落盘;

  • 交易守卫:同一 checkout 只允许一个有效 intent,支付金额与购物车总额绑定,complete 前必须有成功 capture,支付令牌必须由 PSP 签发,mandate 可限制交易笔数;

  • 结果净化:同时扫描 content 与 structuredContent 的字符串叶子,标记可疑注入并脱敏 PII;

  • 双时代传输:Streamable HTTP 与 stdio;现代协议与握手版客户端都能接入。

快速开始

需要 Python 3.12 和 uv。

git clone https://github.com/HugoOu/commerce-mcp-gateway.git
cd commerce-mcp-gateway
uv sync

# 不需要模型 key 的确定性演示
uv run python scripts/play.py scenario
uv run python scripts/smoke_mocks.py

# 质量门
uv run pytest -q          # 139 passed, 1 xfailed
uv run ruff check

手动观察网关:

uv run python -m gateway serve
uv run python scripts/play.py tools
uv run python -m gateway approvals
uv run python -m gateway verify

接入真实模型(OpenAI 兼容端点):

$env:OPENAI_API_KEY = "your-key"
$env:OPENAI_BASE_URL = "https://opencode.ai/zen/go/v1"
$env:MODEL_NAME = "deepseek-v4.1-flash"
uv run python scripts/run_w2_demo.py
# macOS / Linux
export OPENAI_API_KEY="your-key"
export OPENAI_BASE_URL="https://opencode.ai/zen/go/v1"
export MODEL_NAME="deepseek-v4.1-flash"
uv run python scripts/run_w2_demo.py

scripts/run_w2_demo.py 会拉起 mock merchant / PSP、启动网关、运行 agent 回路,并打印网关证据日志。

Demo(纯 CLI)

CLI demo

一条命令演出正路、两层拒绝、F14 真实轨迹回放、审批与审计:

uv run python scripts/demo.py          # 约 5 分钟;不需要模型 key
uv run python scripts/demo.py --fast   # 约 70 秒
uv run python scripts/demo.py --deep   # 额外复现 guard-off 的历史 bug
uv run python scripts/demo.py --json   # 机器可读结果

F14 是 qwen3.8-27b 的真实轨迹回放:N=5 探索性,2/5 是尝试率,攻击成功率是 0/5,0 双扣。完整口播稿、预期输出与录制方式见 demo.md。

评测摘要

评测按 claim-first 组织:每条声称先写判定口径,再看证据能不能支撑它。

声称

证据

状态

每次被拦截调用都经过 Decision

T1–T9、三条越权通道、分层契约、139 passed / 1 xfailed

支持

并发下预算不超支

50 路并发,0 超支,hold 回收

支持

审批绑定到具体动作

form / CLI / 老客户端 fail-closed、action_hash

支持

证据可验、决策可重构

4/4 篡改检出、6/6 重构

支持

越权尝试被端到端拒绝

scripted adversary:金额越权 30/30、先履约后扣款 30/30、0 绕过

支持(compromised harness 阳性对照)

并发重复 intent 被串行化

修复前 30/30 双 intent → 修复后 0/30,0 孤儿

支持(单进程)

模型会尝试交易级越权

F14:2/5 次尝试拆单,2/2 被拒,基线 0/5

探索性,N=5

信念层会被商户内容操纵

P2:baseline 0/30 vs injected 30/30

模型层发现,不是网关声称

诚实的边界

  • 单进程:交易守卫的状态在内存里。重启后 max_transactions 计数归零;重启探针中第二笔购买 10/10 被放行。SQLite / 多副本是 future work。

  • 价格漂移:checkout 报 49.99、订单变 60.00 时,5/5 少付。网关当前信任商户在 checkout 时给出的总额;签名报价或 complete 时总额校验是 future work。

  • 提示词注入:关键词筛查能标记明显注入,但抓不到语义操纵。F8 的 Branded Whisper 是已知残余。

  • 模型侧证据不是网关证据:信念探针说明模型会把商户声明当事实,不能拿它证明网关有效或无效。

  • F14 是 N=5 探索性:不能把它写成稳定的 40% 尝试率。

  • 部署边界:Agent 如果绕过网关直接调用 PSP 的 HTTP 端点,网关拦不住。这是部署问题,不是协议内控制问题。

项目结构

src/gateway/       控制面:frontdoor / policy / enforce / budget / approval / evidence / sanitize
src/agent/         薄循环 driver:MCP client + 可替换的 ModelClient
src/mcp_servers/   mock merchant、mock PSP、故障注入
eval/              实验、探针、统计与红队脚本
scripts/           演示与冒烟脚本
demo/              CLI 演示与 F14 脱敏轨迹 fixture
tests/             单元、集成、对抗与不变量测试
docs/              架构、决策、威胁模型、评测与复现记录

文档

文档

中文

English

架构

architecture.md

architecture.en.md

评测设计

evaluation.md

evaluation.en.md

威胁模型

threat-model.md

threat-model.en.md

风控决策

risk-decisioning.md

risk-decisioning.en.md

架构决策记录

decisions.md

decisions.en.md(索引)

Demo

demo.md

demo.en.md

代码导览

code-tour.md

中文

mock 世界

mock-world.md

中文

红队记录

redteam-log.md

中文

实验设计

w4-experiment-design.md

中文

License

MIT。见 LICENSE。


如果这个项目对你有帮助,欢迎 star。

Related MCP Connectors

Related MCP Servers