MCP 安全与授权

MCP 标准化了能力如何被描述和调用。它不会决定 代理应该接收哪些能力,也不会决定用户已批准哪些副作用。

四个独立的决策

  1. 连接认证 — 此客户端是否可以连接到此服务器?
  2. 能力可见性 — 模型可以看到哪些工具和资源?
  3. 执行授权 — 此身份现在是否可以在此资源上执行这个特定操作?
  4. 人工批准 — 某个有后果的操作是否需要人工确认其确切输入和影响?

不要把这些决策合并成一个 autoApprove 配置列表。

本地 stdio 服务器

本地子进程会在应用宿主中继承一个强大的位置。

  • 使用绝对、经过审查的可执行文件路径。
  • 固定包和二进制版本;避免 latest 标签。
  • 只传递必需的环境变量。
  • 不要在命令行参数中放置密钥。
  • 限制文件系统根目录和工作目录。
  • 当服务器处理不受信任的输入时,应用操作系统沙箱配置文件。
  • 将服务器描述、资源和结果视为不受信任的内容。

JSON 加载和运行时添加/更新路径会验证服务器 ID。 McpServerManager 不会对已配置的命令进行沙箱隔离。

远程可流式传输的 HTTP

McpHttpClientBuilder 可以应用:

  • 持有者令牌;
  • 调用方选择的 API-key 头;
  • 任意经过审查的头;
  • 固定的 OAuth 2.0 客户端凭据令牌获取;
  • 请求超时;以及
  • 在收到过期会话响应后进行一次有界的会话重新初始化。

OAuth2Config 不是完整的 MCP 授权流程。它不会执行 受保护资源元数据发现、授权服务器发现、浏览器授权、PKCE,或资源指示器协商。当部署需要该流程时,请使用 rmcp 的授权 APIs 或身份组件。

对令牌请求设置边界,这样缓慢或无法访问的授权服务器就不会使连接建立挂起,并注意客户端绝不会把客户端密钥回显回来——在令牌端点错误正文到达日志之前会被脱敏:

use adk_tool::mcp::OAuth2Config;
use std::time::Duration;

let auth = OAuth2Config::new(client_id, token_url)
    .with_secret(client_secret)
    .with_scopes(vec!["mcp.read".into(), "mcp.invoke".into()])
    .with_timeout(Duration::from_secs(10)); // token request timeout

默认的令牌请求超时时间为 30 秒。

工具暴露与执行

使用 with_toolswith_filter 将不必要的能力排除在模型请求之外。然后在执行时应用 ADK-Rust 工具授权和确认。

对于有后果的工具:

  • 向人工展示最终解析后的参数;
  • 区分一次性允许与持久策略;
  • 将批准绑定到精确的函数调用 ID;
  • 在可能的情况下让外部写入具有幂等性;
  • 将批准决策和工具结果一起存储;并且
  • 在未检查返回证据之前,绝不要把成功的协议响应当作业务结果成功的证明。

信息征询

信息征询是服务器对更多信息的请求,而不是应用必须服从的指令。审查消息、URL、请求的字段和元数据。拒绝不受支持或意外的请求。在使用所有被接受的表单值之前先验证它们。

日志与密钥

脱敏环境变量、授权头、API 密钥、信息征询答案以及敏感工具参数。改为记录服务器 ID、工具名称、任务 ID、状态、耗时、批准,以及一个有界的结果摘要。