Skip to main content
Glama
vryahn

Payment Orchestrator MCP Server

by vryahn

支付路由编排器

热路径上靠的是证据,AI 只做边界上的事。

给定一笔即将发送的银行卡授权请求,它决定应由哪家支付服务提供商(PSP)来接收——依据的是实证性的授权通过证据,以及操作者以真实单位给出的费用容忍度。如果该尝试被拒绝,一个以拒绝错误类别为键的状态机会决定下一步做什么:同一 PSP 稍后重试、现在故障转移、换不同渠道,或者停止。路由决策本身是确定性的、可审计的;其内部不运行任何语言模型。

它是用 Claude Code 构建并发布的:引擎、AI 边界层、评测框架、Web UI、API 和这份 README 都是在智能体会话中产生的——一个编排式会话把子任务下发给子代理(后端、UI、发布、案例研究)——并且由你可以自行运行的测试和评估门禁把关。这里所用的工程纪律与 nutri. 中描述的保持一致:代理必须加载的约定、结构性的护栏,以及用一个机器——而非一个承诺——来作为“完成”的定义。护栏拦住了那些本来会被发出去的东西:一个丢掉了所有 API 路径的重写(部署后验证发现)、一个把有效发卡机构错标为“未见”的 UI,以及作者两个被判断为错误的假设(一个“页数规则”、一项 DNS 配置),子代理们拒绝照做。

在线演示 https://orchestrator.vryahn.com · 案例研究 https://vryahn.com/work/routing · API 实践中的 API 查看 · MCP MCP.md

在 84,011 笔 TEST 交易上进行样本外回放(第 22–31 天,表格在第 1–21 天训练):在 cost_bias=0 时,预期委付成功率为 72.02%,而实际观察为 66.13%——+5.89 个百分点,这是方向性的,不是A/B 结果。见 限制。

运行

Python 3.11。requirements.txt 是运行时——fastapi 加标准库,也是 Vercel 唯一安装的东西。requirements-dev.txt 增加了离线技术栈(duckdb、pandas、numpy、pyarrow、mcp、uvicorn、httpx),用来重新生成数据、运行回测、启用 MCP 或本地测试。

python3.11 -m venv .venv && .venv/bin/pip install -r requirements-dev.txt
.venv/bin/python cli.py --txn-file demo_transactions.json   # 8 decision-boundary cases
.venv/bin/uvicorn api.index:app --reload --port 8000        # API on /api/*, UI from public/

引擎读取的表(routing_tables.json、routing_meta.json)已经提交,所以全新克隆即可完成路由——也可以部署——不需要离线 Pipeline。仅当数据模型变化时才需要重新生成它们:

.venv/bin/python synth_attempts.py         # seeded ~300k attempts -> attempts.parquet
.venv/bin/python build_routing_tables.py   # -> routing_tables.json, routing_meta.json
.venv/bin/python backtest.py --json        # -> backtest_summary.json
.venv/bin/python tests.py                  # engine
.venv/bin/python tests_ai.py               # AI edges + HTTP contract
.venv/bin/python evals/decline_eval.py     # normalizer against the golden set

Related MCP server: kong-ai-gateway-mcp

架构

flowchart LR
    subgraph offline["OFFLINE — batch, once per rebuild"]
        G["synth_attempts.py<br/>seeded generator"] --> A[("attempts.parquet<br/>1 row = 1 attempt, ~300k")]
        A -->|"build_routing_tables.py"| T[("routing_tables.json + routing_meta.json<br/>segment x PSP: n, approvals, p_hat, Wilson LB<br/>4-level hierarchy")]
        A -->|"backtest.py — train d1-21, test d22-31"| B["backtest_summary.json<br/>out-of-sample lift"]
    end

    subgraph edgein["EDGE IN — language to enum"]
        RAW["raw PSP decline<br/>ISO 8583 / decline_code / refusalReason / bank prose"] --> N{"decline_normalizer.py<br/>table -> LLM -> safe fallback"}
        EV["evals/ — 48 golden declines<br/>accuracy by route, hallucination gate"] -.->|"scores"| N
    end

    subgraph online["ONLINE — pure engine, never touches raw data"]
        X["txn: amount, bin6/issuer, funding,<br/>channel, attempt #, error history"] --> D{"decide(txn, config)"}
        T --> D
        N -->|"error_class"| D
        D --> S1["1. resolve segment per PSP<br/>walk L0 to L3 until n >= min_support"]
        S1 --> S2["2. score = Wilson LB x amount x (1 - fee)<br/>= expected net collected"]
        S2 --> S3["3. pick PSP — cost_bias 0..1 maps to<br/>fee tolerance 0..10pp; psps_down excluded"]
        S3 --> S4["4. retry state machine<br/>keyed on last error_class"]
        S4 --> R["Decision: route_psp, eligible_psps with scores,<br/>retry policy, reasoning lines"]
    end

    R --> OPS["ops.py — route, explain, simulate,<br/>evidence, normalize, backtest"]
    B --> OPS
    OPS --> CLI["cli.py"]
    OPS --> API["api/index.py — FastAPI on Vercel<br/>+ public/ web UI, same origin"]
    OPS --> MCP["mcp_server.py — 6 MCP tools"]

为什么这样设计

  • 离线/在线切分。 decide(txn, config) -> Decision 是纯函数。它只加载一次已经物化好的表,而且永远不会读取原始尝试记录,所以决策在微秒级完成、没有数据库也可测试、事后也可追溯审计。这正是你在生产环境里对账层与路由层之间会画的那条边界。

  • 带次级层级的分层租化。 L0 是 gateway_group × funding × issuer_bucket × amount_band;L3 只有一个 gateway_group。支持量按 PSP 逐配置维度解析(量段 → 发卡方 → 资金来源),直到某个单元格达到 min_support(默认 200),并会把所用到的层级随决策一起上报。渠道是一等公民,从不会被丢弃:会话在线和会话偏好是两个不同的世界。

  • 用 Wilson 下限,而不用原始通过率。 一个 3/3 通过是的分段,并不等于 100% 的分段。当样本变薄时,这个边界会向零逼近 压,所以一个有足够证据的 78% 会胜过一次运气好的 100%,而不需要一个外挂的置信度规则。

  • cost_bias 是个“显式调节旋钮”,以真实单位表示。 这个取舍被描述为“我愿为了一个更便宜的 PSP 放弃几个百分点的审批率”——tolerance = cost_bias × 10pp,并且比最优授权率相差不超过该容忍度的最便宜的 PSP 胜出。任何混合式评分都会让一个零点几个百分点的费用差异悄悄压过两位数的授权率鸿沟;而容忍过滤器则不会。回测给这个旋钮定值:cost_bias=0 为 72.02% / +5.89 pp,0.5 为 71.56% / +5.43 pp,1.0 为 69.57% / +3.44 pp。

  • 按错误类型重试,而不是盲目按计数。 无钱 是账户问题,会在下一个账期重试同一个 PSP;bank_auth_required 在会话偏好之外且没有顾客在场时无法完成,应重新安排到一个用户在场的渠道,而不是白耗尝试次数;fraud_risk 会永久终止这条链路;generic_decline 会按分数来故障转移到下一个 PSP。一个无法识别的类则会降级到通用故障转移策略,明确上层默认会说的内容。

AI 该在哪里——以及它不该在哪里

decide() 内部没有 LLM。 钱不该靠一个被采样的 token 来转移。语言模型被限制在两个交互真正需要自然语言的位置。

在这里——decline_normalizer.py。 每个 PSP 拒绝的“方言”都不一样:ISO 8583 的多种数值、类似 Stripe 的 decline_code、类似 Adyen 的 refusalReason,或者原始银行文本。重试状态机聊的是唯一一个枚举,所以这些方言必须在引擎看到它们之前先被归并。一个确定性的表,处理大宗流量类代码——置信度 1.0、没有延迟、没有成本。只有表未命中,才会走进模型链(先是 Gemini,后是 Mistral),它在一个受限枚举 schema 下作答。任何落在枚举之外或置信度低于 0.6 的答案,都会丢弃,并代之以 generic_decline——这是它本身的安全默认值,也是全新部署的。仓库在不配置任何 API 密钥时也能保持全绿。

被测量,而非信任——evals/。 48 个黄金标准拒绝样本:大约 60% 落在命中表中,约 40% 是故意挠表(拼写错误、啰嗦的银行文本、罕见代码),加上几个真正模糊、其中 generic_decline 才是正确答案的情形。evals/baseline.json 记录了两条基线。仅用表(没有 key):32/48 = 66.67%——即 28 个表路由例子上 100%,以及 20 个落到 default 的例子上采取了安全的 generic_decline 默认。LLM(配置了密钥,并使用 --remote 对已部署的 API 运行):48/48 = 100%——28 个来自表,19 个由 gemini-3.6-flash 答复, 1 个由低置信回退说出,但 generic_decline 才是预期答案。此 runner 按 route 报告准确率,并逐类生成混淆矩阵;它能断言零幻觉,如果准确率比相应基线下降超过 2%,构建就会失败。

不在——mcp_server.py。 六个 MCP 工具——route_transaction、explain_decision、simulate、segment_evidence、normalize_decline、backtest_summary——让代理可以用英语驱动引擎。可查询每一个决策,但它们一个都不能改。见 MCP.md。

局限性

  • 数据是合成的。该结构设计成让路由决策不平凡,而不是要复刻任何真实投资组合。

  • 没有部署任何在线 PSP 连接器;引擎只做决定,不负责真正网络发送。

  • 没有欺诈评分、3DS 编排、网络令牌或卡组织重试规则来执行。

  • 回测是方向性的。历史路由不是随机化的,容量没有被模型化,“预期通过”是训练期 Wilson lower bound 应用于测试期的率,而不是一次结论,因为原理验证并不是实地 A/B 结果。

  • 这些表聚合了所有尝试,而 backtest 训练并在首次尝试时“最后回放”;所以更接近生产的方式是:在一组样本上只做首次尝试。

  • LLM 评估只有 48 个样本并且跑过一次。这个规模的黄金测试 $100$ 主要作为防回归闸门,而不是关于顶尖的长期信息很假望的断言。

文件地图

文件

用途

synth_attempts.py

attempts.parquet 的种子生成器;渠道混合、渠道结构、PSP 费用、授权率模型、误差混合和重试行为都在文件顶部文档中说明

build_routing_tables.py

生成 routing_tables.json(segment × PSP:n、approvals、p_hat、wilson_lb,所有 4 层)以及 routing_meta.json(金额档位边界、发卡方白名单、bin6 → issuer 映射、PSP 费用、error-class 枚举)

orchestrator.py

引擎:decide(txn, config) -> Decision,Config 数据类。仅依赖标准库

decline_normalizer.py

PS神的拒绝错误各类 → 引擎的 error_class 枚举:先查表,未命中才调 LLM,安全兜底

ops.py

API 与 MCP 共享的操作函数(route、explain、simulate、evidence、normalize、backtest)

api/index.py

Vercel 上的 FastAPI;接口契约见 api/README.md

mcp_server.py

MCP stdio 服务器,六个工具;详见 MCP.md

cli.py

CLI 前端:用 flag 传单笔交易,或用 --txn-file 传批量文件

public/

静态 Web UI,由 Vercel 在与 API 同源下提供

demo_transactions.json

8 个位于平衡边界上的交易,附 why_interesting 注释

backtest.py

TRAIN 第 1–21 天 / TEST 第 22–31 天在 cost_bias 0 / 0.5 / 1.0 下回放;--json 可重新生成 backtest_summary.json

evals/

48 个 golden 拒绝例子、打分 runner 和记录好的 baseline

tests.py / tests_ai.py

基于断言的检查:先引擎,再 AI 以及 HTTP 契约


Bryan Rodríguez Abarca · vryahn.com · 从一个技术练习开始,最终扩展为个人项目。数据全部为合成数据。

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    B
    maintenance
    Enables read-only investigation of payment transactions by building normalized timelines, detecting anomalies like duplicate charges and stuck refunds, and creating diagnostic escalations for human review. Never executes or modifies payment actions.
    -
  • F
    license
    A
    quality
    B
    maintenance
    Enables an LLM agent to investigate a Kong Gateway through fourteen read-only, schema-validated tools and a deterministic diagnostic engine, so it can trace routes, services, plugins and upstream health and explain faults such as why authentication is failing on a path. Every fact comes from the gateway itself, and the model only selects tools and writes the evidence-backed explanation.
    14
    -
  • A
    license
    A
    quality
    B
    maintenance
    Enables AI agents to investigate synthetic fraud cases by pulling transactions, running deterministic rules evaluations, pivoting across devices, and recording auditable case files with provenance.
    4
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables AI clients to run read-only yes/no checks, classifications, and ordered scores with probabilities, supporting triage, routing, sentiment, and lead-fit decisions through hosted or self-hosted MCP tools.
    41 npm
    AGPL 3.0