迁移 AML 工具集上网
B6 从 Day 51 的规范精读、Day 52 的官方 TS SDK 起步、Day 53 的 Zod schema、Day 54-55 的 tools/list/tools/call 网络语义一路铺到今天——前 5 天我们都在「用一个玩具工具(assessTypology)练管线」,今天第一次把真业务能力(仓库里已存在的 AML 三件套)按 MCP 契约拆成 3 个工具暴露上网。这是 B6 从「
阶段: B6 · 真 MCP server (2026-07-28 spec)(Day 51-60) 标签: #mcp #aml-copilot #tool-contract #hitl
今日导引(由浅入深)
B6 从 Day 51 的规范精读、Day 52 的官方 TS SDK 起步、Day 53 的 Zod schema、Day 54-55 的 tools/list/tools/call 网络语义一路铺到今天——前 5 天我们都在「用一个玩具工具(assessTypology)练管线」,今天第一次把真业务能力(仓库里已存在的 AML 三件套)按 MCP 契约拆成 3 个工具暴露上网。这是 B6 从「协议练习」转向「把作品②变成可被任意 MCP 客户端调用的服务」的转折点。承接 Day 53「以 Zod 为单一真相源」,今天把单工具扩成工具集;明天(Day 57)让 DeepSeek-V3 当客户端真去调它们。今日「最小可判定产出」:3 个 AML 工具在 MCP Inspector 里逐个 tools/call 调通(git commit 为证)。
1. 机理精读
MCP 工具契约的本质是「把内部函数声明成可被外部 LLM 发现 + 调用的能力」。
仓库里 src/aml/ 下已经有一套确定性的 AML 流水线:
typology.ts——类型学规则引擎(structuring / layering / mule_network 阈值判定)。sarDraft.ts——SAR 草稿模板生成(规则模板,非 LLM)。sarNarrative.ts——LLM prompt 构造 + 规则模板基线。auditTrail.ts——哈希链审计 trail。
这些是函数,不是工具——它们没有对外暴露的 name / description / inputSchema,外部 LLM 无从发现,也无从调用。今天的工作就是给它们套上 MCP 契约外壳,让任意 MCP 客户端(明天就是 DeepSeek-V3)能「看见」并「调用」它们。
契约设计的第一性原理是「输入最小化、输出结构化便于 HITL」。 按 Day 56 seed 的拆法,把 AML 能力拆成 3 个 MCP 工具:
assessCase(证据 → 类型学比对):输入一个案件标识 / 案件对象,输出命中的类型学规则、聚合得分、证据交易 id。委托给typology.ts的规则引擎。draftSar(SAR 草稿):输入案件 + 评估结果,输出按 5W1H 结构化的 SAR 段落。委托给sarDraft.ts的draftSar()。listTypologies(枚举):无输入或最小输入,返回已建模的类型学清单(structuring / layering / mule_network)。
为什么是「输入最小化」? MCP 工具的入参由 LLM 在运行时填充。入参越复杂、越自由:
- LLM 填错的概率越高(多一个必填字段就多一处幻觉机会)。
- 攻击面越大(Day 57 会讲 description 是攻击面,Day 58 会讲入参是攻击面)。
- 敏感 PII 越容易随调用日志外泄。
所以 assessCase 的理想入参就是一个 caseId,让 server 端去取真实案件数据,而不是让 LLM 把整个交易数组塞进入参。
为什么是「输出结构化便于 HITL」? AML 是强合规域,最终 SAR 上报必须有人复核(Human-in-the-Loop)。工具输出若是一坨自由文本,调查员无法逐条核对证据;若是结构化的「命中规则 + 证据交易 id 列表 + 得分」,UI 就能把每条引用高亮、可点击跳转到原始交易。这正是 sarDraft.ts 里 draftSar() 返回 citedTxIds 字段、把段落拆成 SarSection[] 的原因——结构化是为复核服务的,不是为美观。
工具粒度的权衡:为什么是 3 个工具而不是 1 个「万能 AML 工具」或 10 个细粒度工具?
- 1 个万能工具:LLM 难以区分「现在该做评估还是该出草稿」,且入参会膨胀。
- 太多细粒度工具:
tools/list菜单变长,LLM 选择负担加重,选错率上升。 - 3 个工具对齐 AML 调查的三个自然阶段(枚举类型学 → 评估案件 → 出草稿),粒度与业务语义一一对应,是可解释的拆法。
与相邻概念的边界:今天只做「把内部函数封装成工具并调通」,不做让 LLM 自动选工具(那是 Day 57)、不做零信任输入校验的对抗测试(那是 Day 58)、不做进程内 vs 网络的对拍回归(那是 Day 59)。背景类型学知识引 IBM AMLworld(2024-04)合成 AML 数据集与类型学分类。
2. 推导 / 手算 / 代码走读
Day 56 的 handler 委托给仓库已有真实模块。逐条走读关键符号(均来自 Read 验证):
src/aml/sarDraft.ts导出draftSar(c: AmlCase, assessment: TypologyAssessment): SarDraft(第 61 行)。它是规则模板生成(非 LLM)——文件头部第 2-4 行明确标注「W1 原型为【规则模板生成(非 LLM)】,按 FinCEN SAR 叙述 5W1H 结构拼装中文段落」。draftSar的draftSar是draftSar工具的真实底层实现。draftSar内部先dedupe(assessment.hits.flatMap((h) => h.evidenceTxIds))抽出引用交易 id(第 64 行),再按 dayOffset 排序证据交易(第 66-68 行),输出 6 个固定SarSection:引言/主体身份(Who)/可疑活动(What·When·Where)/可疑原因(Why)/作案手法(How)/总结建议。返回对象带generatedBy: 'rule-template'(第 167 行)——这是诚信标签,下游 UI 据此显示「非 LLM 输出」。src/aml/sarNarrative.ts导出buildSarPrompt(第 121 行)与ruleTemplateSar(第 247 行)。文件头第 18-20 行写明「本仓库当前【未接入任何 LLM】。凡 LLM 化部分一律是 prompt+rubric+接口,无 key 时 graceful 降级到 ruleTemplateSar」。所以draftSar工具的诚实状态是「规则模板」,不能对外宣称「LLM 生成的 SAR」。src/aml/typology.ts(第 1-49 行)是assessCase的底层:定义了CTR_THRESHOLD_CENTS = 1_000_000($10,000)、ASSESS_THRESHOLD = 0.5、SCORE_PRIMARY = 0.6/SCORE_SECONDARY = 0.4等阈值常量,规则 id 如 STRUCT-01/LAYER-01/MULE-01。assessCase工具就是把这套确定性规则引擎的判定结果结构化返回。src/aml/auditTrail.ts导出AuditTrail类(第 123 行)与fnv1a哈希(第 24 行)。SOTA 检查里强调的「保留auditTrail.ts审计轨迹」就指这里:append-only + 哈希链,任意历史事件被改则其后所有 hash 校验失败(第 10-11 行注释)。- 封装层用
src/agent/mcp/toolRegistry.ts的register(spec, handler)(第 151 行)把这 3 个工具注册进McpToolRegistry,每个 handler 内部委托给上述真实模块。register会校验 name 合法(第 152 行/^[a-zA-Z][\w.-]*$/)、拒绝重名(第 155 行)、强制inputSchema.type === 'object'(第 158 行)。
一个 tools/call 往返的报文形状(基于 handle() 第 199-218 行的真实行为):
请求侧 —— assessCase 一次合法调用:
{ "jsonrpc": "2.0", "id": 7,
"method": "tools/call",
"params": { "name": "assessCase", "arguments": { "caseId": "C-1024" } } }
响应侧 —— handle() 把 call() 的返回包进 result.content(第 209 行 { ...base, result: { content: result } }):
{ "jsonrpc": "2.0", "id": 7,
"result": { "content": {
"topTypology": "structuring",
"scores": { "structuring": 0.6, "layering": 0, "mule_network": 0 },
"hits": [ { "ruleId": "STRUCT-01", "evidenceTxIds": ["T0003","T0005","T0009"] } ],
"threshold": 0.5
} } }
注意:content 里全是结构化字段——evidenceTxIds 让 UI 能逐笔高亮、scores/threshold 让调查员判断「为何过阈」。这就是「输出结构化便于 HITL」在报文层的落地。draftSar 的 result.content 同理会带 sections: SarSection[] + citedTxIds + generatedBy: 'rule-template'。
3. 今日实战
- 在 Day 52 起的 server 进程里,用
server.tool()(官方 SDK)或McpToolRegistry.register()(进程内对照基线)注册 3 个工具:assessCase/draftSar/listTypologies。 - 为每个工具写清
description(明天就是 LLM 的选工具依据)与inputSchema(最小必填):assessCase:description说明「对给定案件运行类型学规则引擎,返回命中规则与证据交易」;inputSchema仅含caseId: string(必填)。draftSar:description说明「基于评估结果生成 SAR 草稿(规则模板,非 LLM),输出需人工复核」;入参caseId+ 可选评估结果。listTypologies:description说明「枚举已建模的洗钱类型学」;无入参。
- 每个 handler 内部委托真实模块:
assessCase→typology.ts的规则引擎;draftSar→src/aml/sarDraft.ts的draftSar(c, assessment);listTypologies→ 枚举structuring/layering/mule_network。 - 入参设计遵循「最小化」:
assessCase入参用caseId(让 server 取数据)而非整包交易数组。 - 用
npx @modelcontextprotocol/inspector连 server,逐个tools/call三个工具,确认各自返回结构化result.content。 - 确认
draftSar输出透传generatedBy: 'rule-template'标签到result.content,UI 据此显示「非 LLM 输出 / 需人工复核」。 - git commit:标题写明「3 个 AML 工具 Inspector 调通」,并在 commit body 诚实标注「上网封装为待建 / 底层
src/aml/*为真实已有」。
4. 今日实测 / 产出
- 状态:待建——git commit:3 个 AML 工具全部 Inspector 调通。
- 底层
src/aml/sarDraft.ts、sarNarrative.ts、auditTrail.ts均为仓库已有真实文件(本日已 Read 核实存在)。 - 上网封装为待建。
- 纯结构化逻辑,无需 key。
(按诚信纪律:上述「待建」状态逐字保留,不升级为「已完成」。)
5. 常见误区 / 陷阱
- 把整包交易数据塞进入参:违反「输入最小化」,既放大 LLM 填错概率,也把敏感 PII 暴露在工具调用日志里。正解是传
caseId,server 端取数。 - 让工具直接生成最终 SAR 并上报:SOTA 检查明确 AVOID——必须保留 HITL 与
auditTrail.ts审计轨迹,合规上不可全自动。draftSar返回的是「草稿」,不是「报告」。 - 伪造
generatedBy:draftSar返回'rule-template',绝不能在工具输出里谎称「LLM 生成」。诚信标签必须透传到 UI。 - 重名注册静默覆盖:
McpToolRegistry.register第 155 行对重名直接抛错,这是好设计;若用别的注册方式要确认它不会静默覆盖同名工具。
6. 学习资源(每条带 YYYY-MM)
- MCP 规范(2026-07-28,写作时未最终定稿,硬复查点 07-28)—— tools 章节定义
tools/list/tools/call契约。 - MCP TypeScript SDK server 文档(2026-03)——
McpServer+server.tool()注册接口。 - FIS × Anthropic「Financial Crimes AI Agent」(2026-05-04 宣布,GA 2026 H2)—— 证据汇集 → 类型学比对 → SAR 叙述的产品主线。
- IBM AMLworld 合成 AML 数据集(2024-04)—— 类型学(structuring/layering/mule)分类背景。
- FinCEN SAR 叙述指引(2003-11;2025-10-09 新增 4 条 FAQ 强调「质量优于数量」)—— 5W1H 叙述结构出处(见
sarNarrative.ts头注)。
SOTA检查 (2026-06 更新)
- 当前主流方案:复刻 FIS+Anthropic 2026-05 AML Copilot 模式(证据汇集 → 类型学比对 → SAR 草稿 → HITL → 审计轨迹)仍是当前主线,2026-06 无更优替代。
- 是否仍 SOTA:是。金融机构 GenAI 合规叙事在 2026 H1 集中落地(FIS GA 排在 2026 H2),把 AML 调查从数天压到分钟级。
- 过时黑名单 / AVOID:禁止在工具里直接生成最终 SAR 上报——必须保留 HITL 与
auditTrail.ts审计轨迹,合规上不可全自动。禁止把generatedBy='rule-template'标签去掉伪装成 LLM 输出。 - 下次复查点:07-28 MCP 规范定稿后重验工具契约字段(content 结构);08-02 EU AI Act Article 50 透明义务生效后,确认 AI 生成内容标注义务对
draftSar输出的要求。
衔接
- 昨天:Day 55 — tools/call 网络往返 + content 封装(学会单工具的成功/失败报文形状)。
- 今天:把仓库真业务 AML 三件套按 MCP 契约拆成 3 个工具暴露上网,输入最小化、输出结构化便于 HITL。
- 明天:Day 57 — DeepSeek-V3 经 OpenRouter 作 MCP 客户端,让模型自己从
tools/list选工具并调用。