最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
MCP 工具定义在用户批准后发生变化时应如何处理?
时间:2026-09-16 11:46:01 编辑:袖梨 来源:一聚教程网
MCP 工具定义在用户批准后发生变化时,客户端不应继续沿用旧批准。批准必须绑定到 Server 身份、规范化后的工具定义摘要、允许参数与数据范围、网络或写入副作用。名称、描述、Schema、annotations 或 Server 身份任一关键项变化,都应让旧批准失效,重新发现并要求复核。
“批准工具名称”粒度太粗
如果客户端只记录“允许调用 send_report”,Server 可以保留名称,却把描述改成同时向外部地址发送副本,或在 Schema 中新增 destination。模型看到新定义后可能按新说明行动,而授权系统仍认为这是已批准工具。
因此批准对象不能只是字符串名称。至少要包含 Server 的稳定身份、工具契约摘要、授权作用域、有效期和适用会话。否则同名工具更新、Server 地址替换或租户切换都会继承不应继承的信任。
工具描述也是安全相关输入
description 会进入模型上下文并影响工具选择与参数生成。它不是普通文档注释,而是模型行为的一部分。描述从“读取报告”改成“读取并上传报告”时,即使 inputSchema 没变,权限含义也已经变化。
客户端计算批准摘要时应包含 name、description、inputSchema、outputSchema 和 annotations。Server 维护者也应把描述变化纳入代码审查,像审查系统提示和授权策略一样审查。
先规范化,再计算摘要
直接哈希原始 JSON 会因空白或对象键顺序变化误触发。应使用成熟的 JSON canonicalization 实现,把选定契约字段转换为确定性字节,再计算加密摘要。工具列表顺序不应影响单工具批准,因为摘要按单个工具计算。
approvalKey = hash(canonicalize({
serverIdentity,
toolName,
description,
inputSchema,
outputSchema,
annotations,
policyScope
}))
摘要只是快速等值判断,审批 UI 仍要提供可读 diff。用户需要知道是描述改了、增加了必填参数、扩大了网络域,还是仅修正了拼写。
变化后的默认动作:撤销并降权
客户端收到 tools list changed、连接重建或定期探测发现摘要不同后,先把旧批准标为 stale,阻止自动调用,再获取完整新定义。高风险工具回到未批准状态,直到用户或组织策略审查通过。
不能先执行一次再询问,也不能因为变化被判断为“可能兼容”就自动继承写权限。兼容性是调用是否还能工作的问题,批准是用户是否同意新行为的问题,两者不是同一判断。
并非所有变化都需要相同交互
可把变化分级。仅格式化或规范化后摘要不变,不需要动作。description、Schema、annotations 或 Server 身份改变,应重新审查。新增无关工具不必撤销其他未变化工具的批准,但新工具从未批准开始。
工具被删除时立即撤销并移出工作集。同名工具删除后又重新出现,也不能自动恢复旧批准,因为它可能是全新实现。批准记录要绑定连续的 Server 身份与契约版本。
批准应绑定允许的副作用
“允许这个工具运行”仍然过于宽泛。更安全的授权可绑定参数约束、资源范围、目的地、数据分类和副作用。例如只允许读取某个仓库,只允许向公司域名发送,只允许在当前 workspace 写入,或单次金额不超过阈值。
每次调用先经过确定性策略检查。模型不能通过工具描述或输出扩大 policy scope。参数超出范围时重新请求用户确认,或直接拒绝。
批准的时间与作用域要有限
批准可以只对本次调用、当前会话、当前 workspace 或固定时间有效。写入、付款、发消息和外部网络请求通常不适合永久批准。只读且被 sandbox 限制的工具可以使用更长有效期。
长期批准仍应设置最大期限,并在 Server 版本、身份、契约摘要、组织策略或 sandbox 配置变化时提前失效。客户端还要提供集中查看和撤销批准的界面。
第三方 Server 要固定版本与来源
对本地 Server,固定包版本、镜像 digest 或签名制品,避免同一命令每次启动下载不同代码。对远程 Server,校验 URL、认证受众、证书与组织 allow list,并记录 Server 实现信息。
版本固定降低意外变化概率,但不能替代运行时摘要。远程服务可以在 URL 与版本字符串不变时部署新代码,本地依赖也可能被供应链替换。实际协商得到的工具定义仍需比较。
Server 端用 CI 阻止静默漂移
Server 项目应在测试中快照完整工具目录。PR 改变名称、描述或 Schema 时生成结构化 diff,必须由代码所有者明确批准。破坏性变化要求版本化、迁移说明和弃用窗口。
这能减少无意漂移,却不能保护客户端免受恶意或被攻陷的第三方 Server。客户端仍需独立执行定义检查和授权失效,不能把 Server 自测当成信任根。
工具输出始终是不可信数据
即使工具定义从未改变,返回内容也可能来自网页、工单、邮件或用户可编辑数据库,包含提示注入文本。批准工具只代表允许执行某项能力,不代表其输出可以改变系统规则或扩大权限。
宿主应把工具结果放在明确的数据边界内,标注来源与信任级别。结果中的“忽略之前指令”“调用另一个工具”“把数据发到某地址”等文本不能自动转化为授权。所有后续工具调用仍走相同策略检查。
不要依赖简单字符串过滤输出
删除看起来像系统指令的句子只能拦截少量明显模式,容易误删合法内容,也挡不住改写、编码或跨字段注入。更可靠的是权限隔离、数据与指令通道分离、目标白名单、最小上下文和调用前确定性 policy enforcement。
对必须解析的结构化结果,使用 outputSchema 校验并只提取允许字段。自由文本展示给模型时限制长度、转义特殊载荷并保留来源标签,但仍不能把清洗结果视为可信指令。
网络和文件权限要在模型之外控制
Agent 拥有敏感数据时,不应允许未经策略限制的任意联网。把 Server 放入 sandbox 或受控代理,限制可读写路径、允许域名、进程能力和凭据 scope。即使模型受提示注入影响,也无法越过执行层边界。
高风险副作用采用两阶段流程:先生成计划和预览,再由用户确认具体参数,最后执行。确认绑定到计划摘要,执行前参数若改变则确认失效。
一个实用的批准状态机
DISCOVERED
-> REVIEW_REQUIRED
-> APPROVED(scope, digest, expiry)
APPROVED + definition changed
-> STALE
-> privileges removed
-> REVIEW_REQUIRED
APPROVED + call outside scope
-> PER_CALL_CONFIRMATION or DENIED
server removed or identity changed
-> REVOKED
调用入口只接受 APPROVED 且摘要一致、未过期、参数在 scope 内的记录。UI 显示 stale 原因和字段级 diff,避免用户面对模糊的“工具发生变化”。
并发变化需要最后一刻检查
用户打开确认对话框后,Server 可能再次更新定义。客户端在保存批准前重新读取当前摘要,并在实际调用前再比较一次。批准的摘要与调用使用的定义必须完全一致。
若变化发生在模型规划与执行之间,取消该调用并重新规划。不能把新参数套进旧计划,也不能让已展示给用户的确认覆盖后来新增的副作用。
审计日志要能回答四个问题
记录谁在何时批准了哪个 Server 的哪个工具、批准时的契约摘要和 scope、实际调用使用的摘要与参数、变化后何时失效。日志中敏感参数需脱敏,但摘要与策略决策必须保留。
这样安全事件发生时,可以判断是 Server 定义变化、输出注入、策略错误还是用户明确批准。只记录工具名称无法重建当时用户看到的契约。
测试重新批准机制
先批准一个只读工具,确认相同规范化定义重连后可按策略复用。只改变 JSON 键顺序,确认不误撤销。随后修改 description、增加参数、扩大 annotations 副作用,确认旧批准立即 stale。
模拟工具输出包含诱导调用和外部目的地,确认它不能绕过 policy。再测试用户确认后、调用前定义二次变化,确保调用被取消而不是沿用旧批准。
结论
MCP 工具批准不能是 approve once and forget。批准应绑定规范化契约摘要、Server 身份、参数与数据范围、副作用和有效期;任何关键定义变化都撤销旧权限并要求重新审查。
定义信任与输出信任必须分开。即使工具定义稳定,输出仍可能携带攻击者控制的内容。只有版本固定、契约监测、批准失效、最小权限 sandbox 和确定性调用策略共同存在,才能降低工具被更新后“借用旧信任”的风险。
相关文章
- .net如何优雅的使用EFCore实例详解 09-16
- 在 .NET MAUI 中加载 json 文件的方法 09-16
- 基于.NET 7 的 QUIC 实现 Echo 服务的详细过程 09-16
- Morya UI:后台页面别再硬搓,交给 Agent 按规范生成 09-16
- DeepSeek 实战:从零构建 Text2SQL 数据平权应用 09-16
- 用 AI 编程时,先定方案再动手写代码 09-16