Tool、MCP 与安全:把模型意图变成受约束的现实动作
1. 第一性原理:Tool 是副作用边界
模型输出的是意图,Tool 执行的是真实动作。读文件、修改代码、发请求、运行命令和部署服务的风险完全不同,所以 Tool 不是“给模型增加几个函数”,而是把副作用放进一个有合同、有权限、有审计的执行边界。
每个 Tool 都应明确:输入 Schema、输出 Schema、所需权限、可访问资源、超时、重试语义、幂等键、取消方式、审计字段和验证方法。
2. Tool Gateway 的职责
不要让模型直接连接任意外部服务。Tool Gateway 位于模型和执行环境之间,负责:
解析 → Schema 校验 → 权限判断 → 风险分级 → 资源隔离
→ 执行/超时/取消 → 结果归一化 → 审计与轨迹记录
MCP 可以统一工具发现和调用协议,但协议统一不代表权限自动安全。每个 Server、Tool 和资源仍需独立授权,租户、Session 和用户身份不能只由模型参数传递。
3. 输入安全与提示注入
提示注入的本质是:不可信数据试图改变控制指令。网页、Issue、README、代码注释和 Tool 返回都可能包含“请忽略之前规则”之类文本。
第一性原则是分离数据和指令:不可信内容默认是证据,不是授权;Tool 返回应带来源和信任级别;系统规则和用户任务合同要放在更高优先级层;危险动作必须通过策略检查,而不是让模型自行判断。
可以维护一个风险矩阵:低风险读取、可回滚的局部编辑、不可逆文件删除、外网写操作、凭据使用和生产部署。风险越高,越需要显式审批、沙箱、双重验证和更细的审计。
4. Tool 错误为什么不能直接重试
错误分类先于重试。至少区分:
- 参数错误:修正输入后重试,不能原样重试。
- 权限错误:请求授权或换用合法能力。
- 资源不存在:重新探索或更新目标。
- 超时/限流:指数退避,并检查动作是否已经提交。
- 服务端错误:有限次数重试,超过预算后降级。
- 部分成功:读取真实状态,执行补偿或继续剩余部分。
- 未知错误:停止自动化并保留证据。
重试必须携带幂等键。对于创建资源、发消息、提交订单这类动作,“请求超时”不代表没有成功,直接重试可能造成重复副作用。更稳妥的流程是查询状态,再决定重试、确认或补偿。
5. 幂等、取消与排空
幂等不是让函数永远返回同一个结果,而是同一个逻辑操作重复提交不会产生额外副作用。幂等键应由 session_id + turn_id + tool_call_id 等字段组成,并有过期时间和状态记录。
取消也不是简单杀掉进程。Runtime 要先阻止新的 Tool Call,通知正在执行的工具,等待可安全取消的阶段,记录已提交动作,最后把 Session 置为可恢复状态。对于无法取消的动作,应进入排空和补偿流程。
6. 结果验证与最小权限
Tool 返回的成功状态只能证明接口调用成功,不能证明任务成功。文件修改要检查 diff 和测试;数据库写入要读取结果;部署要检查健康状态;研究任务要检查证据覆盖和来源可信度。
最小权限应按 Session、Tool、资源和动作拆分。只读任务不应持有写权限;某个 Skill 的权限不能自动扩散给嵌套 Skill;凭据尽量由 Gateway 代持,不能直接放进模型上下文。
7. MCP 的工程化边界
MCP Server 是能力提供者,Gateway 是策略执行者,Sandbox 是运行环境,Verifier 是结果裁判。四者职责要分开:Server 不应替调用方做最终授权,Sandbox 不应替业务验证结果,模型也不应替策略系统授予权限。
协议演进需要版本化 Schema 和兼容策略。新增字段应允许旧客户端忽略,改变字段语义要升级版本;Tool 的错误类型、分页、流式结果和取消事件都应写入契约测试。
8. 审计与学习者练习
一条可审计的 Tool 记录应关联任务、Turn、调用者、参数摘要、权限决定、执行环境、结果摘要、重试和验证证据。敏感参数要脱敏,但不能让审计失去定位能力。
练习:设计三个 Tool——读文件、编辑文件、运行测试。为每个 Tool 写 Schema、权限、超时、重试和验证策略;注入一个恶意 README;再模拟一次超时但实际已经提交的写操作,验证系统是否会重复副作用。