当 MCP Server 从“只读查询”走向“可以修改生产数据、配置和权限”时,风险不再只是模型是否理解了用户意图。真正困难的是:企业不能假设每位员工都能正确配置每个 Agent,也不能要求有人盯住每一次工具调用。Cloudflare 在扩大内部 MCP Server 的写访问权限之前,构建了 WriteGuard,为写操作提供更细粒度的控制,并计划通过私有测试版将这些能力带到 Cloudflare MCP Server 门户。
写权限为什么需要单独治理
只读工具通常最多泄露信息,而写工具会直接改变系统状态。例如,同一个 MCP Server 可能同时暴露查询工单、更新 DNS 记录、修改防火墙规则或删除资源的工具。把它们统一归为“允许访问”或“拒绝访问”,粒度往往不够:
- 用户可能需要读取所有资源,但只能修改自己负责的资源。
- Agent 可以自动执行低风险更新,但高风险操作必须等待人工确认。
- 同一个工具在不同环境中的风险不同,测试环境可以自动写入,生产环境需要额外约束。
- 审计记录需要说明谁发起了请求、Agent 调用了什么工具、参数是什么,以及策略为何放行。
因此,写访问控制的重点不是简单增加一个总开关,而是把“谁、对哪个资源、执行什么动作、在什么环境、满足什么条件”纳入决策。
一个可落地的策略模型
下面的配置是一个可以改造的最小示例,字段名是假设的策略格式,并不代表 WriteGuard 私有测试版的实际 API。它展示了实现细粒度控制时可以采用的思路:
# writeguard-policy.yaml
server: internal-dns
mode: enforce
rules:
- name: engineers-update-dev-records
subject:
groups: [engineering]
tool: dns.update_record
resources:
environment: dev
zones: ["dev.example.com"]
decision: allow
require_approval: false
- name: production-dns-needs-approval
subject:
groups: [engineering]
tool: dns.update_record
resources:
environment: production
zones: ["example.com"]
decision: allow
require_approval: true
approvers: [platform-oncall]
- name: block-destructive-tools
subject:
groups: [engineering, contractors]
tools: [dns.delete_zone, dns.delete_record]
decision: deny
logging:
include: [subject, agent_id, tool, arguments, decision, approval_id]
实际落地时,策略引擎至少需要接收以下上下文:
subject = 当前用户及其组织、团队、角色
agent_id = 发起调用的 Agent 身份
server = MCP Server 名称
team = MCP 工具所属团队或门户空间
tool = 具体工具名称
arguments = 工具参数,例如 zone、record、environment
request_time = 请求时间和请求来源
策略匹配成功后,不应只返回布尔值。更实用的结果是一个带原因的决策对象,让网关或 MCP Server 知道下一步应该放行、拒绝,还是暂停等待审批:
{
"decision": "require_approval",
"reason": "production DNS changes require platform-oncall approval",
"approval_scope": {
"tool": "dns.update_record",
"environment": "production",
"zone": "example.com"
},
"expires_in_seconds": 300
}
把策略放在工具调用路径上
一个简单的服务端流程可以是:
- MCP Server 收到工具调用。
- 网关或服务端提取用户、Agent、工具和参数上下文。
- WriteGuard 根据策略返回
allow、deny或require_approval。 - 只有
allow才直接执行写操作。 require_approval创建一次性审批请求,并在批准后重新校验原始参数。- 将决策、审批结果和实际执行结果写入审计日志。
可以用下面的 Python 伪实现验证策略边界。它不依赖外部库,保存为 policy_check.py 后即可运行;生产系统应将规则解析、身份认证和日志发送替换为正式组件。
from dataclasses import dataclass
from typing import Literal
Decision = Literal["allow", "deny", "require_approval"]
@dataclass
class Request:
group: str
tool: str
environment: str
zone: str
def decide(request: Request) -> tuple[Decision, str]:
destructive_tools = {"dns.delete_zone", "dns.delete_record"}
if request.tool in destructive_tools:
return "deny", "destructive DNS tools are disabled"
if request.tool == "dns.update_record":
if request.environment == "dev" and request.zone.endswith("dev.example.com"):
return "allow", "development record update is allowed"
if request.environment == "production":
return "require_approval", "production DNS changes need approval"
return "deny", "no matching write policy"
requests = [
Request("engineering", "dns.update_record", "dev", "api.dev.example.com"),
Request("engineering", "dns.update_record", "production", "example.com"),
Request("contractors", "dns.delete_record", "dev", "api.dev.example.com"),
]
for item in requests:
decision, reason = decide(item)
print(f"{item.tool} {item.environment} {item.zone}: {decision} ({reason})")
运行命令:
python3 policy_check.py
这个例子中,审批并不等于永久授权。审批应绑定到具体工具、具体参数和较短的有效期。若 Agent 在审批后改变了 zone、记录值或目标环境,系统应视为新的请求重新检查。
设计时要盯住的边界
默认拒绝写操作
MCP Server 新增工具时,不应因为“用户已经有服务器访问权”就自动获得写权限。新工具应进入受控状态,直到有人明确补充策略。这样可以降低工具扩展带来的意外授权。
区分工具风险,而不是只看服务器
同一服务器上的 list_records、update_record 和 delete_zone 风险完全不同。策略应落到工具级别,并进一步检查资源范围和参数,而不是只配置“允许访问某个 MCP Server”。
审批前后重新校验
审批流程中可能发生权限变化、资源删除或参数修改。批准结果需要绑定原始请求,并在真正执行前再次验证身份、策略版本和参数摘要。
审计要能回答“为什么放行”
仅记录“调用成功”不够。排查一次错误写入时,运营人员需要看到主体、Agent、工具、参数摘要、命中的规则、审批人和执行结果。敏感参数可以脱敏,但不能让审计失去因果链。
先在内部场景收敛规则
Cloudflare 的做法先是在扩大内部 MCP Server 写访问之前建设控制能力,再通过私有测试版逐步带到 MCP Server 门户。对其他团队而言,这提示了一条稳妥路径:先选择少数写工具,收集误拒绝、审批耗时和审计缺口,再扩大覆盖面。
采用清单
上线写访问前,可以逐项确认:
- 是否为每个写工具定义了明确的资源范围?
- 是否区分开发、测试和生产环境?
- 高风险或破坏性操作是否默认拒绝?
- Agent 身份是否与最终用户身份分开记录?
- 审批是否绑定具体参数并设置过期时间?
- 策略拒绝和审批请求是否能被用户清楚理解?
- 是否能从日志还原一次完整的工具调用决策?
- 新增 MCP 工具时,是否不会自动继承写权限?
WriteGuard 的核心价值可以概括为:让 MCP 的写能力从“相信每个 Agent 都配置正确”转向“在每次高影响工具调用前执行可解释的策略决策”。这不会消除自动化风险,但能把权限、审批和审计放到同一条执行路径上,为逐步扩大写访问范围提供更可控的基础。