MCP(Model Context Protocol)让 AI Agent 能够通过统一协议调用外部工具。读取文档、查询数据库通常风险可控,但“创建订单”“修改权限”“删除数据”这类写操作会直接改变现实系统的状态。
Cloudflare 正在私有测试阶段推出 WriteGuard,目标是为 MCP 服务器提供更细粒度的安全控制。它关注的重点不是简单地允许或拒绝一个 Agent,而是控制 Agent 能否调用会修改数据或执行动作的工具,以及这些调用在什么条件下可以被放行。
MCP 安全的分水岭:读操作与写操作
传统的访问控制往往围绕“用户是否能访问某个服务”展开。但在 Agent 场景中,风险还取决于工具的具体行为:
search_documents可能只是读取信息;get_customer可能只返回客户资料;update_customer会改变业务数据;create_refund可能触发真实资金流转;delete_project则可能造成不可逆损失。
如果所有工具共享同一种授权结果,安全策略就会过于粗糙:要么让 Agent 获得过大的权限,要么为了安全完全禁止它执行有价值的操作。
WriteGuard 的方向正是把控制粒度推进到工具调用层,尤其关注那些能够修改数据或执行动作的工具。对于企业来说,这意味着可以把“让 Agent 查信息”和“让 Agent 替用户做决定”拆成两个不同的安全问题。
可以怎样设计一套写操作策略
下面的配置是一个概念性示例,用于展示应用层可以采用的策略结构,并非 Cloudflare WriteGuard 的实际配置语法。接入具体产品时,应以其私测文档和 API 定义为准。
# mcp-write-policy.example.yaml
server: customer-support-mcp
policies:
- name: allow-read-tools
match:
tools:
- search_customers
- get_customer
- list_orders
action: allow
- name: review-sensitive-writes
match:
tools:
- update_customer
- create_refund
action: require_approval
conditions:
require_authenticated_user: true
require_reason: true
max_amount: 500
- name: block-destructive-actions
match:
tools:
- delete_customer
- delete_order
action: deny
这类策略至少表达了三层意图:
- 读工具默认放行:降低 Agent 查询信息时的摩擦。
- 敏感写工具需要额外条件:例如确认用户身份、填写操作原因,或限制退款金额。
- 破坏性工具默认拒绝:删除等不可逆动作不应仅凭普通对话就直接执行。
在实际系统中,还可以将策略与用户身份、租户、请求来源、会话状态和业务上下文结合。例如,同一个 create_refund 工具,对客服主管、普通客服和自动化 Agent 可能需要不同的审批规则。
在 MCP 服务前增加一层可审计的防线
一个实用的调用流程可以长这样:
from dataclasses import dataclass
from typing import Any
@dataclass
class ToolRequest:
user_id: str
tool: str
arguments: dict[str, Any]
READ_TOOLS = {"search_customers", "get_customer", "list_orders"}
REVIEW_TOOLS = {"update_customer", "create_refund"}
BLOCKED_TOOLS = {"delete_customer", "delete_order"}
def authorize(request: ToolRequest) -> str:
if request.tool in BLOCKED_TOOLS:
return "deny"
if request.tool in REVIEW_TOOLS:
if not request.user_id:
return "deny"
if request.tool == "create_refund":
amount = float(request.arguments.get("amount", 0))
if amount > 500:
return "require_approval"
return "require_approval"
if request.tool in READ_TOOLS:
return "allow"
return "deny"
request = ToolRequest(
user_id="user-123",
tool="create_refund",
arguments={"order_id": "ord-456", "amount": 120},
)
print(authorize(request)) # require_approval
运行方式:
python policy_demo.py
示例中的关键点不是 Python 代码本身,而是把授权决策放在工具真正执行之前,并返回明确结果:allow、require_approval 或 deny。正式系统还应记录调用者、工具名、参数摘要、策略版本和最终结果,方便审计和故障排查。
WriteGuard 解决的是“能不能写”,不是全部安全问题
细粒度写控制很重要,但它不能替代完整的 Agent 安全体系。接入类似能力时,还需要注意几个边界:
- 参数校验:即使工具被允许调用,也要验证金额、资源 ID 和字段范围。
- 幂等性:网络重试或 Agent 重复规划可能导致同一写操作执行多次。
- 审批体验:审批必须让人看懂具体动作,而不是只显示“允许工具调用”。
- 最小权限:不要因为 Agent 需要查询订单,就同时授予删除订单的权限。
- 日志与回放:保留足够的调用上下文,但避免把敏感数据完整写入日志。
- 失败处理:策略服务不可用时,应明确选择“默认拒绝”还是受限降级,而不是静默放行。
尤其要警惕“读取工具伪装成写操作”的情况。例如,一个名为 get_status 的工具如果会触发同步、发送通知或刷新支付状态,它实际上也属于有副作用的工具。安全分类应基于行为,而不是工具名称。
给团队的落地清单
如果正在把 MCP 接入客服、数据分析或内部自动化系统,可以按以下顺序推进:
- 为每个工具标记只读、可变更、破坏性三类风险。
- 为写工具定义参数范围、调用者身份和审批条件。
- 先在审计模式运行策略,只记录本应被拦截的请求。
- 对高风险工具启用默认拒绝,并为低风险写操作设置明确上限。
- 在测试环境模拟提示注入、重复调用和异常参数。
- 定期检查策略命中日志,删除不再使用的工具权限。
WriteGuard 所代表的方向,是把 Agent 的安全控制从“是否能连接 MCP”推进到“是否能执行某个具体动作”。对于希望让 Agent 参与真实业务流程的团队,这种细粒度、可审批、可审计的写操作控制,可能比单纯扩大工具数量更值得优先建设。