第 9 / 21 篇

第8章 MCP 是接入协议,权限仍然属于业务

工具发现不会自动授予工具能力

MCP 帮助客户端发现和调用工具,统一能力描述与消息交互。它可以减少每个 Agent 对接每个系统的重复工作,但工具名称、描述与 JSON Schema 不是访问控制策略。一个客户端看到了 refund 工具,不意味着当前用户可以退款;一个服务没有把工具列出来,也不意味着攻击者不能直接构造调用。

将本书实验接到 MCP 时,协议处理层应把已验证的请求上下文和经过结构校验的参数转交工具代理,后面的身份、租户、对象、审批与撤权保持相同。MCP session ID 是会话路由信息,不能代替访问凭据。客户端提供的元数据、工具描述和工具结果都不应直接改变当前用户身份。

本书不包含完整 MCP 服务端实现,也不测试 SDK 互操作性。我们实际运行的是 HTTP 工具代理与业务服务,MCP 章节提供协议接入设计和评审方法。这样划清范围,读者才能知道实验已经证明什么,以及在引入具体 SDK 后需要补什么测试。

受众与令牌透传

MCP 官方安全最佳实践讨论 token passthrough 与 confused deputy 风险。一个面向 MCP server 的令牌不应被直接当作所有下游 API 的令牌。授权服务器、受保护资源和客户端之间应明确令牌受众。工具服务还要防止把自己持有的高权限下游凭据无条件借给上游调用者。

实验中的 tool-proxy 与 business-api 受众区分,正好可以用来理解这一点。即使协议层通过认证,订单服务仍要求自己的受众凭据,并独立判断租户、scope 和审批。MCP 接入后若把这些检查删掉,只保留“SDK 已经认证”,就会退回跨服务凭据混用。

失败案例是一个多租户 MCP server 缓存上次调用的下游 Authorization,并按工具名称复用。Alice 的会话退出后,Bob 的调用命中了同一缓存,得到 Alice 的业务权限。修复需要把缓存和任务上下文明确绑定身份、租户、受众与授权版本,且避免保存不必要的原始令牌。会话 ID 不能承担这一切,因为它通常不是密码学绑定的权限凭据。

远程服务与本地工具的不同

远程 HTTP MCP 的授权设计涉及受保护资源元数据、授权服务器发现和 OAuth 客户端行为;本地 stdio 工具往往继承进程环境与宿主权限。两者的凭据存储、用户授权界面、网络暴露与执行隔离不同。不能因为都叫 MCP,就使用一套“连接成功即可信”的规则。

本地工具尤其需要注意环境变量、磁盘文件和继承凭据。若它拿到长期管理员密钥,即使远程服务授权完美,本地进程泄漏仍会绕过链路。这个问题与沙箱设计相接,但本书只要求明确凭据的接收者、作用域、寿命和业务端验证。执行隔离需要单独工程验收。

可运行的协议无关实验

运行 go test -race -run 'TestSignedHTTPBoundaries|TestApprovalBindingsAndReplay|TestTenantScopeAndUntrustedToolInput' -v ./lab。把测试中的 /call 想成 MCP 工具调用适配后的内部入口,观察它的授权结果不依赖自然语言描述。之后真正增加 MCP transport 时,应让同一组业务攻击样本从新入口运行,而不是只测试 tools/list 与 tools/call 能够返回。

练习:设计一个 MCP adapter,写出请求认证上下文如何传递、session 如何隔离、令牌如何按受众获取、审批如何展示和绑定,以及工具结果中的恶意指令由哪一层当作数据处理。不要在工具 description 中写“只允许本租户”,然后把它视为完成了租户隔离。

工具目录变化应当被视作配置变化

当一个远程工具服务更新 description、输入结构或可用工具集合时,Agent 的行为范围可能随之改变。企业接入平台可以固定受信服务与工具版本,对新增副作用工具设置评审,并让工具授权配置与发布记录关联。自动发现不必意味着自动批准全部新能力。

多服务聚合还可能出现同名工具。一个服务声明 orders_refund,另一个恶意服务也声明相同名字,客户端若只按名字选择会发生混淆。应把工具身份与来源服务绑定,展示和审计中保留稳定来源。工具名称适合交互,不能取代签发方、资源服务器和业务权限的信任配置。

实际 MCP SDK 集成测试应至少覆盖会话混用、连接恢复、并发用户、授权失败传播与工具结果中的恶意文本。对 stdio 工具,还需检查启动命令和环境继承;对远程工具,则检查目标元数据和令牌受众。两类传输可以共享业务授权回归,但不能共享未经论证的环境信任假设。