2026年10月10日 2 分钟阅读

给 AI Agent 加上一层安全边界:MCP 工具调用治理实践

tinyash 0 条评论

给 AI Agent 加上一层安全边界:MCP 工具调用治理实践

当 AI Agent 能够读取文件、执行命令、访问数据库或调用第三方 API 时,真正需要关注的就不只是模型回答得准不准,而是它**准备做什么,以及谁来批准这次操作**。Model Context Protocol(MCP)让模型连接外部工具变得更标准,但标准化连接并不等于自动获得安全边界。

本文不把 Agent 当作一个“更聪明的脚本”,而是把每次工具调用视为一条需要审计的请求:先识别风险,再执行最小权限操作,最后留下可追溯记录。

先区分三类风险

第一类是**权限过大**。一个只需要查询数据库的 Agent,不应同时拥有删除表、修改生产配置或读取所有环境变量的权限。第二类是**输入注入**:网页、Issue、邮件和文档都可能携带诱导 Agent 调用危险工具的内容。第三类是**结果污染**:工具返回的内容可能被后续步骤当成可信指令,造成跨步骤的提示注入。

因此,安全控制不能只放在系统提示词里。提示词可以说明规则,却不能替代操作系统权限、网络策略和人工审批。

一个可落地的调用管道

可以把每次 MCP 调用拆成五步:

  1. **识别主体**:记录用户、Agent、会话和工作区。
  2. **校验工具**:只允许登记过的服务器和工具名。
  3. **评估参数**:检查路径、目标主机、SQL 类型和数据范围。
  4. **执行策略**:低风险操作自动放行,高风险操作要求审批。
  5. **记录结果**:保存请求摘要、决策、执行结果和耗时,避免记录密钥原文。

下面是一个与具体 MCP SDK 无关的策略示例,重点是决策结构,而不是某个产品的 API:

from dataclasses import dataclass
from pathlib import PurePosixPath

@dataclass
class Decision:
    action: str
    reason: str

READ_ONLY_TOOLS = {"read_file", "search_docs", "select_rows"}


def decide(tool_name: str, arguments: dict, workspace: str) -> Decision:
    if tool_name in READ_ONLY_TOOLS:
        return Decision("allow", "read-only tool")

    if tool_name == "write_file":
        path = PurePosixPath(arguments.get("path", ""))
        root = PurePosixPath(workspace)
        if root not in path.parents and path != root:
            return Decision("deny", "path is outside the workspace")
        return Decision("approval", "file mutation requires review")

    if tool_name in {"run_command", "delete_rows", "send_message"}:
        return Decision("approval", "side effect requires review")

    return Decision("deny", "unknown tool")

这个例子有三个关键点:默认拒绝未知工具;读操作和写操作分开;路径校验不能只检查字符串前缀。生产实现还应处理符号链接、路径规范化、命令参数白名单和超时。

不要把“允许执行”做成永久权限

更稳妥的做法是让授权绑定到具体上下文。例如,用户批准“在当前仓库创建测试文件”,不应自动等价于批准“向生产服务器发送请求”。授权至少应包含:工具名、参数摘要、工作区、有效期和调用次数。

对破坏性操作,可以采用两阶段确认:Agent 先生成拟执行计划,策略层检查计划,用户确认后才执行。确认界面展示的应是实际目标,例如数据库名、表名、文件路径和将要发送的域名,而不是一句模糊的“是否继续”。

审计日志要能回答四个问题

发生事故后,日志至少要回答:谁发起了调用?Agent 看到了什么上下文?策略为什么允许或拒绝?工具最终改变了什么?

推荐记录结构化 JSON,例如:

{
  "event": "tool_call_decision",
  "tool": "write_file",
  "decision": "approval",
  "workspace": "project-a",
  "reason": "file mutation requires review",
  "request_id": "req_2026_001"
}

日志本身也要遵守最小化原则。API Key、Cookie、完整提示词中的个人数据和工具返回的敏感字段不应无条件落盘。可以记录哈希、字段名和截断后的摘要,并为审计人员提供受控的解密流程。

上线前的检查清单

  • 是否默认拒绝未知 MCP 服务器和工具?
  • 是否区分只读、写入、删除和外发操作?
  • 是否对路径、域名、数据库和命令参数做了 allowlist 校验?
  • 工具返回内容是否被标记为“不可信数据”,不会直接升级成指令?
  • 高风险调用是否有一次性、可过期的审批?
  • 是否能用 request ID 把决策、执行和结果串起来?
  • 测试是否覆盖路径穿越、提示注入、重复调用和超时重试?

MCP 解决的是 Agent 与工具之间的互操作问题,治理层解决的是“互操作之后谁能做什么”。将工具调用放进显式的策略管道,采用默认拒绝、最小权限、短时授权和结构化审计,才能让 Agent 从“能调用工具”走向“可控地调用工具”。

相关链接

  • [Model Context Protocol 官方文档](https://modelcontextprotocol.io/docs)
  • [Model Context Protocol GitHub 仓库](https://github.com/modelcontextprotocol)
  • [OWASP Top 10 for LLM Applications](https://owasp.org/www-project-top-10-for-large-language-model-applications/)

发表评论

你的邮箱地址不会被公开,带 * 的为必填项。