---
slug: cloudflare-writeguard-mcp-write-governance
title: WriteGuard：MCP 寫入控管與使用場景
status: published
excerpt: 將 agent 的寫入操作接上權限、歸因與人工審核。
category: AI
tags: [mcp, security, cloudflare]
author: Seer
author_role: Author
read_time: 8 min
cover: "/static/cloudflare-writeguard-mcp-write-governance-cover.png"
closing_note: "先把邊界講清楚，工具才能變成可靠流程。"
published_at: "2026-08-20T00:00:00Z"
updated_at: "2026-08-20T00:00:00Z"
---

這篇指南可以協助你為團隊的 AI Agent 建立一道安全防線：在保留 Agent 自動化效率的同時，防止它們誤刪資料、亂發信件或在 GitLab 任意合併程式碼。你可以利用 Cloudflare 研發的 [WriteGuard](https://blog.cloudflare.com/mcp-portal-writeguard-private-beta/) 機制，在免修改既有 MCP server 程式碼的前提下，對 Agent 的寫入行為進行風險分級控管、加上身分標籤並同步記錄稽核追蹤軌跡。[1][2]

## 問題

當 AI Agent 開始具備調用工具（Tool Call）的能力，能存取 Jira、GitLab 或 Wiki 時，其產生的外部副作用（Side Effects）便帶來了顯著風險。[1]

主要問題在於：
1. **難以識別的 Agent 行為**：當工程師授權 Agent 操作系統時，下游系統通常只看得到該使用者的帳號（例如 Joe）。如果 Agent 寫了不良 Prompt 導致背景大量關閉 Ticket，事後稽核日誌只會顯示是 Joe 關閉的，團隊無法區分哪些是人手操作、哪些是 Agent 的失控行為。[1]
2. **缺乏細粒度的寫入管控**：AI 應用端內建的確認提示（Confirm Prompt）容易被使用者關閉或繞過。[1] 如果直接開放寫入權限，Agent 可能會執行高風險動作，例如將程式碼合併至正式環境或向客戶大量發送郵件。[1]
3. **安全邊界的劃分與管理需求**：
   - **哪些 MCP 寫入需要管**：所有會對下游系統狀態造成不可逆改變的動作（例如：GitLab 中的 `merge_mr`、部署觸發；Jira 中的大量關閉與刪除 Ticket；郵件/Slack 中的外部寄信與大量發訊；資料庫中的 `drop_table` 或 DML 異動）都必須受控。單純的唯讀動作（如 `get_merge_request`）風險較低，可以直接放行。[1]
   - **哪些邊界由 Access/OAuth 處理**：Cloudflare Access 與 OAuth 負責身分驗證與粗粒度的端點授權。Access 驗證「是誰在調用（例如 Joe）」，OAuth 則將該請求對應到下游系統（如 GitLab）的權限。如果 Joe 本身沒有 GitLab 合併權限，OAuth 自然會阻擋。然而，如果 Joe 擁有該權限，Access/OAuth 無法阻止 Agent 代替 Joe 執行不當的合併。這正是 WriteGuard 需要介入的微觀工具層級控制。[1][3]

## 原理

WriteGuard 作為政策、歸因與稽核層，接在 [MCP server portal](https://developers.cloudflare.com/cloudflare-one/access-controls/ai-controls/mcp-portals/) 上，包覆既有的 MCP server，無須重構或修改工具原始碼。[2][3]

當 Agent 發送工具呼叫（Tool Call）時，WriteGuard 會依據管理員設定的工具風險層級（Risk Level），引導請求走入三種處理路徑之一：[1]
1. **放行 (Allow)**：通常適用於 Read Only 工具。呼叫直接送達 MCP server handler。[1]
2. **放行並標註 (Allow with labeling)**：適用於受控寫入（Contained Write）。在寫入下游系統時，於指定欄位附加 Agent 歸因標籤（如標示特定 Client 與 Session），並非同步寫入已去敏感化的稽核日誌。[1][2]
3. **擋下 (Block)**：針對高風險（Critical）或停用的工具，在 handler 執行前即刻阻擋，並將嘗試紀錄寫入稽核日誌。[1]

```mermaid
flowchart TB
  A["Agent / MCP Client"] --> I["Access + OAuth identity"]
  I --> W["MCP Portal + WriteGuard"]
  W --> D{"Tool risk level"}
  D -->|Read Only| M["MCP server handler"]
  D -->|Contained Write| L["加入 Agent 標籤"]
  L --> M
  D -->|Critical / disabled| B["執行前阻擋"]
  M --> S["下游系統"]
  L --> U["Central audit log"]
  B --> U
```

WriteGuard 的核心功能包含四項主要能力：[2]
- **Agentic identity**：將每次工具呼叫連結至特定的 Agent、Client 與 Session，並疊加於 Access 驗證的身分之上。
- **Deny-by-default gating**：寫入工具預設為關閉狀態，必須明確授權方可開啟。
- **Visible labels**：在目標系統的變更內容中，顯示明確的 Agent 標籤。
- **Central audit**：所有連接至 portal 的 MCP server，均共享一份中央稽核日誌。

Cloudflare 內部 portal 在 2026-04 接 13 台 MCP server，查核時寫的是 27 台，而且一開始全是唯讀。[1]

每個工具都有風險層級、開關、標籤設定。層級決定能不能執行，也決定稽核時的查核標準：[1]

| 風險層級 | 官方例子 | 工具例子 |
|---|---|---|
| Read Only | 搜尋 issue、讀 MR、看 pipeline | `get_merge_request` |
| Minimal Impact | 加 reaction、標已讀、訂閱 issue | — |
| Contained Write | 留言、開 MR、改 issue 欄位 | `create_mr_note` |
| Critical | 合併 MR、觸發正式部署、大量刪除 | `merge_mr` |

## 操作

團隊若要導入此機制，可以分為兩個主要階段：設定 MCP Portal 與配置 Client 連線。[3]

### 1. 團隊如何建立與連接 MCP Portal
前置條件為帳號內需有作用中的 Domain，且 Zero Trust 已與身分提供商（IdP）對接。[3]

新增 MCP Server 的步驟如下：[3]
1. 登入 Cloudflare dashboard，導航至 **Zero Trust** → **Access controls** → **AI controls**。
2. 啟用 **MCP servers**，並點選 **Add an MCP server**。
3. 輸入名稱與可選的 Server ID。
4. 在 **HTTP URL** 欄位輸入 MCP server 的完整位址（例如 `https://docs.mcp.cloudflare.com/mcp`）。
5. 設定 Access 政策以限制可存取該 server 的人員。
6. 點選 **Save and connect server**。若 server 支援 OAuth，需使用管理員帳號完成授權。

建立 Portal 的步驟如下：[3]
1. 在同一頁面點選 **Add MCP server portal**。
2. 輸入 Portal 名稱。
3. 在 **Custom domain** 選擇帳號內的 Zone，亦可指定 Subdomain。
4. 將前述設定的 MCP server 加進 Portal。
5. 視需求關閉不希望暴露的 Tools 或 Prompts。
6. 設定 **Require user auth**（預設為開啟，要求使用者以個人身分登入；關閉則使用 Admin 憑證）。
7. 設定 Access 政策以限制可連線至 Portal URL 的人員。
8. 點選 **Add an MCP server portal**。

使用者連線的終端點位址為：
```text
https://<subdomain>.<domain>/mcp
```
請透過瀏覽器開啟首頁 `https://<subdomain>.<domain>/` 進行登入。若直接以瀏覽器存取 `/mcp` 路徑，會因缺乏 MCP Client Token 而收到 `invalid token` 錯誤。[3]

### 2. 透過 Allowlist 預先關閉不當工具
Portal 預設會啟用 Server 上的所有 tools/prompts。管理員可透過配置 allowlist，在 server-to-portal mapping 中設定 `default_disabled: true`，並在 `updated_tools` 中明確啟用特定工具：[3]
```json
{
  "servers": [
    {
      "id": "example-server",
      "default_disabled": true,
      "updated_tools": [
        { "name": "search_documents", "enabled": true },
        { "name": "list_projects", "enabled": true }
      ]
    }
  ]
}
```

### 3. 設定 Client 連線
- **本機 Client 設定**：官方建議使用 `mcp-remote@latest` 封裝連線，以確保 Session 順利建立。例如在 Claude Desktop 或 OpenCode 的 `config.json` 中配置：[3]
  ```json
  {
    "mcpServers": {
      "company-portal": {
        "command": "npx",
        "args": [
          "-y",
          "mcp-remote@latest",
          "https://<subdomain>.<domain>/mcp"
        ]
      }
    }
  }
  ```
- **Playground 測試**：
  1. 開啟 [Workers AI Playground](https://playground.ai.cloudflare.com/)。[3]
  2. 於 **MCP Servers** 輸入 `https://<subdomain>.<domain>/mcp` 並點選 **Connect**。[3]
  3. 透過彈出視窗完成 Access 登入，並對需 OAuth 的上游 server 完成授權。[3]
- **機器對機器連線**：使用 Access service token，並在標頭加入 `CF-Access-Client-Id` 與 `CF-Access-Client-Secret`。此時 Portal 與上游 Server 皆須配置 Service Auth 政策，且該 Server 的 **Require user auth** 必須關閉。[3]

### 4. 申請 WriteGuard beta
公開文件（2026-08-12 更新的 MCP Portal 頁）尚未包含 WriteGuard 設定欄位。[3] 團隊可至 [WriteGuard closed beta](https://www.cloudflare.com/resource/writeguard-beta-landing-page/) 進行申請，未來幾個月將逐步對更多客戶開放。[2]

## 驗證

我們以 GitLab MCP server 的整合應用為例，驗證同一個使用者身分在執行三種不同動作時的行為差異：[1]

```js
const sendEmailTool = {
  tool: EmailMCP.sendEmailTool,
  writeGuard: {
    riskLevel: RiskLevel.CONTAINED_WRITE,
    enabled: true,
    labeling: {
      field: "body",
      supportedFormats: [
        LabelFormat.PLAIN_TEXT,
        LabelFormat.HTML,
      ],
    },
  },
};
```
上述程式碼展示了郵件工具的 WriteGuard 政策配置，其中 `labeling.field` 指定標籤寫入的欄位，`supportedFormats` 則用以相容下游應用的格式要求。[1]

依據上述原則，GitLab 工具的執行結果如下：
1. **讀取 MR**：Agent 呼叫 `get_merge_request`。WriteGuard 判定為 `READ_ONLY`，直接放行。[1]
2. **在 MR 留言**：Agent 呼叫 `create_mr_note`。此為 `CONTAINED_WRITE`，WriteGuard 會在留言欄位中插入 Agent 歸因標籤，隨後將呼叫送至 handler，並非同步記錄一筆已清除敏感資訊的審計日誌。[1]
3. **合併程式碼**：Agent 嘗試呼叫 `merge_mr`。由於該操作被歸類為 `CRITICAL` 且未被啟用，WriteGuard 會在 handler 執行前直接阻擋該請求，並將此嘗試記錄至審計日誌中。[1]

## 限制

1. **服務狀態**：截至 2026-08-15 查核，WriteGuard 仍處於 Private Beta 階段，尚未正式 GA。[1][2]
2. **文件與介面限制**：目前公開的 MCP Portal 文件中尚未包含 WriteGuard 的設定欄位，且 Beta 版本的設定畫面未在本次評估中進行帳號核對。[3]
3. **權限與邊界限制**：WriteGuard 的控制點建立在使用者已擁有的權限之上。如果使用者本身不具備某項操作的權限（例如無法關閉 Ticket），Agent 也無法執行該操作。WriteGuard 無法逾越 Access 與 OAuth 的底層身分防線，它僅能在使用者權限之內，針對 Agent 代替人執行的行為進行限縮與追蹤。[1]
4. **旁路風險**：若使用者繞過 Portal 直接連接上游 MCP server，將無法套用 WriteGuard 政策。官方建議將 Access 設為該 server 的唯一 OAuth 提供商以強制要求經由 Portal 轉發。[3]
5. **稽核欄位限制**：為保護敏感資訊，非同步稽核日誌會過濾掉 sensitive payload，因此可能無法提供完整的參數值。[1]

## Sources

[1] https://blog.cloudflare.com/mcp-portal-writeguard-private-beta — WriteGuard: Fine-grained controls for MCP Servers
[2] https://www.cloudflare.com/resource/writeguard-beta-landing-page — WriteGuard closed beta
[3] https://developers.cloudflare.com/cloudflare-one/access-controls/ai-controls/mcp-portals — MCP server portals
[4] https://developers.cloudflare.com/agents/model-context-protocol — Cloudflare Agents MCP docs
