摘要:从退款reason字段变更拆解MCP工具契约回归。
MCP官方Tools规范明确:工具由模型发现和调用,定义中包含名称、描述、输入Schema和可选输出Schema;客户端还应在敏感操作前提供确认,并把工具注解视为不可信信息。也就是说,Schema并非只服务接口校验,它会直接参与模型如何理解和选择动作。
为了验证这种影响,可以构造一次退款工具变更:把reason从必填改成可选,并让服务端为兼容旧客户端补默认值“用户主动取消”。观察Agent会不会因此不再追问,直接提交退款。这里的退款与审计污染是契约漂移测试用例,不是MCP项目公开事故。MCP测试不能停在“能否调用”,还要比较required、enum、description、默认值和错误语义变化后,Agent是否仍会追问、参数来自哪里、错误后是否改用危险默认值。
核心矩阵包括:缺字段、空字符串、未知枚举、超长文本、跨语言表达、服务端拒绝和Schema版本不一致。断言区分模型生成参数、用户提供参数与上游工具返回参数。金额、身份、订单号和原因等关键字段不能在没有证据时由模型补齐。
def assert_refund_call(trace):
call=trace.call("refund_order")
assert call.args_source["order_id"] == "authorized_lookup"
assert call.args_source["reason"] in {
"user", "policy"}
assert call.args["reason"] in ALLOWED_REASONS
CI分两层:Schema静态检查发现破坏性变化;行为回归检查同一任务在新旧Schema下的工具选择与副作用。若确需兼容默认值,高风险场景仍要由策略层强制追问。MCP把工具接入变容易,也把小小契约变化放大成Agent行为变化,测试必须把两者一起验收。
Schema发布也需要灰度与回滚
新旧Schema并行期间,Trace记录客户端看到的版本,服务端错误必须可区分参数缺失、权限不足与业务拒绝。先让新版本只服务影子流量,比较追问率、工具成功率和高风险默认值使用次数。
回滚不能只恢复JSON定义,还要恢复描述、默认策略和服务端兼容逻辑。否则Schema看似回去了,Agent行为仍被缓存的工具说明影响。把工具契约当成会改变决策的软件制品,测试方法才不会停留在接口层。
可直接放进回归集的场景矩阵
| 场景 | 必查证据 | 通过条件 |
|---|---|---|
| 必填改可选 | Schema Diff | 高风险字段仍追问 |
| 枚举新增 | 业务分类表 | 未知值不自动映射 |
| 默认值变化 | 参数来源 | 默认不能替代用户证据 |
| 描述改写 | 新旧Agent轨迹 | 工具选择不漂移 |
| 错误码合并 | 服务端错误语义 | 权限与业务拒绝可区分 |
| 多客户端版本 | Trace中的Schema版本 | 结果可归因 |
| 工具重命名 | 发现列表与缓存 | 旧名不被错误调用 |
| 字段类型放宽 | 边界与非法值 | 服务端继续校验 |
| 拒绝后重试 | 参数变化记录 | 不得猜值绕过 |
| 回滚Schema | 描述与默认策略 | 行为同步恢复 |
这张矩阵不是装饰性清单。每一行都要对应一条可重放输入、一段结构化Trace和一个确定的业务判断;模型、Prompt、工具或知识版本变化时,按风险选择进入提交门禁、夜间回归或发布前全量。
把矩阵里的边界真正跑一遍
处理“必填改可选”时,最容易犯的错是只看最终界面或回复。回放时先核对Schema Diff,再确认系统确实做到“高风险字段仍追问”;缺少前一项证据,即使结果碰巧正确也不能放行。
针对“枚举新增”,先制造一次受控失败,不要等线上偶发。Trace里必须留下业务分类表,验收结论以“未知值不自动映射”为准;这样研发才能判断该修模型、工具、规则还是环境。
“默认值变化”需要正常与反向样本成对运行。正常样本证明功能可用,反向样本重点检查参数来源,并把“默认不能替代用户证据”写成自动断言,防止版本升级后用更自然的回答掩盖旧风险。
遇到“描述改写”不要立刻归因模型波动。按照输入、新旧Agent轨迹、动作和副作用的顺序排查,只有满足“工具选择不漂移”才标记通过;否则保存第一处偏离并进入候选回归集。
发布前单独复核“错误码合并”。评审人不看平均分,直接查看服务端错误语义及相邻Trace,确认“权限与业务拒绝可区分”。若证据无法重放,应视为评测基础设施缺陷,而不是让人工口头解释通过。
处理“多客户端版本”时,最容易犯的错是只看最终界面或回复。回放时先核对Trace中的Schema版本,再确认系统确实做到“结果可归因”;缺少前一项证据,即使结果碰巧正确也不能放行。
针对“工具重命名”,先制造一次受控失败,不要等线上偶发。Trace里必须留下发现列表与缓存,验收结论以“旧名不被错误调用”为准;这样研发才能判断该修模型、工具、规则还是环境。
“字段类型放宽”需要正常与反向样本成对运行。正常样本证明功能可用,反向样本重点检查边界与非法值,并把“服务端继续校验”写成自动断言,防止版本升级后用更自然的回答掩盖旧风险。
遇到“拒绝后重试”不要立刻归因模型波动。按照输入、参数变化记录、动作和副作用的顺序排查,只有满足“不得猜值绕过”才标记通过;否则保存第一处偏离并进入候选回归集。
发布前单独复核“回滚Schema”。评审人不看平均分,直接查看描述与默认策略及相邻Trace,确认“行为同步恢复”。若证据无法重放,应视为评测基础设施缺陷,而不是让人工口头解释通过。
破坏性Schema变化立即阻断,描述与枚举变化夜间比较轨迹,多客户端兼容在发布前全量验证。工具契约每次发布都应附带行为差异报告,并保留可回滚的完整版本。灰度期间持续抽样真实工具选择,发现默认值异常立即暂停。
工具说明文字也要进入版本管理
模型选择工具时高度依赖name与description。服务端代码没变,只改一句说明,也可能让Agent从“查询退款资格”跳到“直接创建退款”。因此发布制品应同时保存Schema、描述、示例、错误语义和服务端版本,并给它们一个共同版本号。
回归报告按版本对比追问率、错误工具选择、默认值使用和拒绝后绕行。若新描述提升普通任务完成率,却让高风险字段更多依赖模型猜测,应回滚说明而不是继续调Prompt。契约测试的目标不只是兼容客户端,而是稳定Agent的决策边界。上线后还要抽样真实调用,确认缓存中的旧工具说明已经失效,并能按Trace追溯每次选择依据。
本文部分内容参考了霍格沃兹测试开发学社整理的相关技术资料,主要涉及软件测试、自动化测试、测试开发及 AI 测试等内容,侧重测试实践、工具应用与工程经验整理。