当 AI Agent 只能搜索文档时,调用失败通常只是一次查询错误;当它能够更新工单、发送邮件、修改数据库甚至触发部署时,同一个错误就可能变成真实事故。Cloudflare 正在私有测试 WriteGuard,目标是为 MCP(Model Context Protocol)服务器提供细粒度安全控制,重点约束那些会修改数据或执行动作的工具,而不是把所有工具调用一视同仁。
真正需要隔离的是“读取”和“产生副作用”
MCP 让模型可以发现并调用外部工具,但不同工具的风险差异很大:
search_documents、get_ticket通常只读取信息;update_ticket、send_email会改变业务状态;delete_customer、deploy_production可能造成不可逆影响。
如果权限只停留在“能否连接这个 MCP Server”,那么获得连接权限的 Agent 往往也间接获得了服务器暴露的全部能力。WriteGuard 所强调的细粒度控制,正是把决策点下沉到具体工具和动作:允许读取,并不自动意味着允许写入。
落地时还不能只看工具名称。更稳妥的授权判断通常需要组合以下上下文:
- 调用者身份:是哪一个用户、Agent 或服务账号发起请求;
- 工具风险等级:只读、可恢复写入、外部动作或不可逆操作;
- 参数范围:更新哪条记录、发送给谁、部署到哪个环境;
- 运行环境:开发、测试还是生产;
- 审批状态:是否已经获得人类确认或短期授权令牌。
例如,同一个 deploy 工具可以允许 Agent 自动部署测试环境,但生产环境必须经过人工批准。细粒度控制的价值不只是“拒绝”,还包括根据上下文有条件地放行。
把策略放在 Agent 与 MCP Server 之间
一种可以这样实践的架构,是在 Agent 和 MCP Server 之间增加策略执行层:
AI Agent
│ MCP tool call
▼
Policy Enforcement / WriteGuard
├── allow ──▶ MCP Server ──▶ Database / SaaS / Deployment API
├── deny
└── require approval
这个位置有两个优势。其一,安全规则不依赖模型是否“听话”;即使提示词被注入,写操作仍需通过独立授权。其二,多个 MCP Server 可以共享一致的身份、审批和审计规则,不必在每个工具实现中重复编写权限代码。
不过,来源摘要没有披露 WriteGuard 私有测试版的具体 API、配置格式或集成方式。下面的示例不是 WriteGuard 官方接口,而是一个可运行的最小策略服务,用来演示接入时应如何区分只读、写入和高危工具。
可运行示例:为工具调用建立授权端点
下面的 Python 服务只使用标准库。它提供 /authorize 接口,并实施三条示例规则:
- 只读工具直接允许;
- 普通写工具需要 Agent 身份和审批令牌;
- 删除、生产部署等高危工具默认拒绝。
将以下内容保存为 policy_server.py:
from http.server import BaseHTTPRequestHandler, HTTPServer
import json
READ_TOOLS = {"search_documents", "get_ticket", "list_orders"}
WRITE_TOOLS = {"update_ticket", "send_email", "create_order"}
HIGH_RISK_TOOLS = {"delete_customer", "deploy_production"}
def authorize(agent_id, approval_token, tool, arguments):
if tool in READ_TOOLS:
return True, "read-only tool"
if tool in HIGH_RISK_TOOLS:
return False, "high-risk tool requires an external approval workflow"
if tool in WRITE_TOOLS:
if not agent_id:
return False, "missing agent identity"
if approval_token != "demo-approved":
return False, "write tool requires a valid approval token"
return True, f"approved write request from {agent_id}"
return False, "unknown tools are denied by default"
class Handler(BaseHTTPRequestHandler):
def do_POST(self):
if self.path != "/authorize":
self.send_error(404)
return
length = int(self.headers.get("Content-Length", "0"))
payload = json.loads(self.rfile.read(length) or b"{}")
tool = payload.get("tool", "")
arguments = payload.get("arguments", {})
agent_id = self.headers.get("X-Agent-Id", "")
approval = self.headers.get("X-Approval-Token", "")
allowed, reason = authorize(agent_id, approval, tool, arguments)
response = json.dumps({
"allowed": allowed,
"tool": tool,
"reason": reason
}).encode()
self.send_response(200)
self.send_header("Content-Type", "application/json")
self.send_header("Content-Length", str(len(response)))
self.end_headers()
self.wfile.write(response)
if __name__ == "__main__":
server = HTTPServer(("127.0.0.1", 8080), Handler)
print("Policy server listening on http://127.0.0.1:8080")
server.serve_forever()
启动服务:
python3 policy_server.py
只读调用不需要审批:
curl -s http://127.0.0.1:8080/authorize \
-H 'Content-Type: application/json' \
-d '{"tool":"search_documents","arguments":{"query":"refund policy"}}'
写操作在缺少审批令牌时会被拒绝:
curl -s http://127.0.0.1:8080/authorize \
-H 'Content-Type: application/json' \
-H 'X-Agent-Id: support-agent' \
-d '{"tool":"update_ticket","arguments":{"ticket_id":"T-42","status":"closed"}}'
加入演示令牌后才会放行:
curl -s http://127.0.0.1:8080/authorize \
-H 'Content-Type: application/json' \
-H 'X-Agent-Id: support-agent' \
-H 'X-Approval-Token: demo-approved' \
-d '{"tool":"update_ticket","arguments":{"ticket_id":"T-42","status":"closed"}}'
真实系统不应使用固定令牌。可以将它替换为短期签名令牌,并绑定用户、工具、参数摘要和过期时间,防止一次审批被重放到其他操作上。策略服务返回允许后,网关再把原始 tools/call 请求转发给 MCP Server;被拒绝时,则直接向 Agent 返回结构化错误。
不要把“允许写入”设计成一张永久通行证
细粒度安全控制仍有几个容易忽略的边界:
- 参数也需要授权:允许
send_email不代表可以发送给任意外部地址; - 默认拒绝未知工具:MCP Server 新增工具后,不应在未审查时自动开放;
- 审批必须绑定请求:批准“关闭工单 T-42”的令牌不能用于删除客户;
- 审计要记录结果:至少保存调用者、工具、参数摘要、策略版本、决策与执行结果;
- 防止名称伪装:名为
get_report的工具也可能在后台生成文件或触发计费,风险分级应基于真实副作用; - 控制凭据范围:即便策略层失效,MCP Server 使用的下游凭据也应遵循最小权限。
采用前的检查清单
WriteGuard 仍处于私有测试阶段,团队在评估时可以先梳理自己的 MCP 工具清单,而不是等产品接入后再补权限模型:
- 标记每个工具是只读、可恢复写入还是不可逆操作;
- 明确 Agent、最终用户和服务账号之间的身份映射;
- 为生产变更、外部通信和删除操作设置人工审批;
- 验证策略是否检查关键参数,而不只是工具名;
- 对未知工具和缺失身份采用默认拒绝;
- 建立可查询的授权与执行审计记录;
- 准备策略服务不可用时的失败模式,写操作通常应选择关闭放行,即 fail closed。
MCP 扩大了 Agent 的能力边界,也放大了错误决策的影响范围。WriteGuard 指向的核心问题很明确:工具能够被模型发现,不等于模型在任何场景下都应该执行它。把读权限、写权限、高危动作和人工审批拆开,才是让 Agent 从演示环境进入真实业务系统的必要条件。