跳到內容

NextPDF Connect HITL 風險層級

每個工具都會宣告四個風險等級之一。最高等級「需核准」(approval-required)在第一次呼叫時不會直接執行;ConfirmationGate 會改為回傳一次性挑戰權杖,AI Agent(代理)必須將這個權杖轉交給人類,由人類授權後再重新呼叫。

Terminal window
composer require nextpdf/server

這個風險模型只有四個依序排列的等級:

等級意義效果
safe(安全)0唯讀,沒有副作用自動執行
caution(注意)1建立或修改記憶體內的狀態自動執行,並寫入稽核紀錄
review(審查)2產生可能被濫用的輸出自動執行,並寫入稽核紀錄
approval_required(需核准)3具破壞性、涉及法律或攸關隱私需要人類確認

一個工具的風險等級只會來自兩個地方:工具本身的宣告,以及選用的維運者組態覆寫。沒有第三個來源。這個模型帶有版本號,而 MCP 的 initialize 回應會公開這個版本號,讓用戶端能偵測不相容的變更。稽核紀錄會套用在 caution 以上等級。

將自動化動作擱置到人類授權後才繼續,正好把控制點放在自動化引入風險的位置。這正是 IEC 31010 為控制由人類行為所引入的風險而指出的位置:就在風險引入點或其附近(IEC 31010:2019)。

當一個 approval_required 工具在沒有有效權杖的情況下被呼叫時,這道 gate 會發出一個挑戰。這項檢查會回傳下列兩種結構之一。

{ "allowed": true }

或是

{ "allowed": false, "challenge": "<human-readable text>", "token": "confirm_<nonce>" }

挑戰文字會點出該操作及其說明,並在目標檔案會被覆寫時提出警告。它會指示呼叫端將 _confirmation_token 參數設為所發出的權杖,並重新呼叫同一個工具。這個權杖會在 300 秒後過期。

權杖的綁定方式是刻意設計的:權杖會綁定工具名稱、一個隨機 nonce,以及 TTL ——而非綁定引數。重試時,MCP 用戶端可能以不同的鍵排序或正規化方式重新序列化引數;因此,若對引數做雜湊,反而會破壞合法的確認流程。這個權杖是一次性的;在重新呼叫時消耗它,正好只允許該呼叫執行一次。

凡是會驅動工具的傳輸層,都會強制執行這道 gate:

  • **MCP:**挑戰會以成功的 JSON-RPC 回應在頻道內回傳,內容就是挑戰文字。呼叫端會重新呼叫 tools/call,並帶上 arguments._confirmation_token
  • **REST 與 gRPC:**同一道 gate 會在共用的工具執行器中,於 approval_required 操作之前執行。挑戰會出現在操作回應中;呼叫端再帶著權杖重複該操作。

組態覆寫可以提高工具的風險等級,但永遠不能調降原本就設計為 approval_required 的工具。組態載入器會強制套用一組固定的鍵集合;如果覆寫試圖降級,就會在載入時拋出例外。伺服器寧可拒絕啟動,也不會在 gate 被削弱的狀態下執行。

output_pdf 寫入檔案以觸發一次挑戰:

Terminal window
./vendor/bin/nextpdf-mcp <<'EOF'
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"c","version":"1.0.0"}}}
{"jsonrpc":"2.0","method":"notifications/initialized"}
{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"output_pdf","arguments":{"document_id":"<id>","file_path":"/var/lib/nextpdf/tmp/out.pdf"}}}
EOF

回應會是該挑戰,而不是檔案。請帶著所發出的權杖重新呼叫:

{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"output_pdf","arguments":{"document_id":"<id>","file_path":"/var/lib/nextpdf/tmp/out.pdf","_confirmation_token":"confirm_<nonce>"}}}

若要強化部署,請將一個原本是 caution 的工具提高為 approval-required:

/etc/nextpdf/nextpdf-mcp.yaml
nextpdf_mcp:
risk_level_overrides:
add_image: 3 # require human confirmation for image insertion

降級會在載入時遭到拒絕,伺服器也不會啟動。舉例來說,把 output_pdf 設成低於 3 就是一種降級。

  • **output_pdf 在 base64 模式下不會觸發 gate。**寫入磁碟屬於 approval-required;將 PDF 以 base64 回傳(不帶 file_path)會被視為較低風險,不需要確認即可執行。

  • **這個權杖不是憑證。**它不會驗證呼叫端的身分,也不會在連網的傳輸層上取代 API 金鑰。它只會在 300 秒內放行一次受 gate 管控的特定呼叫。

  • **每次都是新的挑戰。**如果沒有轉交權杖,或讓權杖過期,並不會永久封鎖該工具;下一次呼叫會發出一個全新的挑戰。權杖會存放在一次性權杖儲存區中,並會定期進行垃圾回收。

  • **不論結果如何都會稽核。**發出挑戰、成功執行,以及 caution 以上等級的失敗執行,都會連同工具名稱與風險等級一起寫入稽核紀錄。

這道 gate 會增加一次權杖儲存區查詢,並在發出挑戰時額外產生一次隨機權杖。相較於受 gate 管控操作本身的成本,這項開銷微不足道,而且只會對 approval_required 工具執行。

這道 gate 是一種圍堵控制,而不是身分驗證控制。即使工具由自主代理(agent)驅動,它也能確保具破壞性、涉及法律或攸關隱私的動作必須由人類授權。對這些操作,伺服器並未宣稱可在沒有人類監督的情況下運作,而且組態也無法削弱這道 gate。在連網的傳輸層上,請將它與 API 金鑰模型結合,並透過 enabled_tools 控制最小權限範圍。請參閱 /connect/security-and-operations/。

聲明來源reference_id
在(人類)引入風險的那一點控制風險IEC 31010:2019

風險模型版本會帶在 MCP 的 initialize 回應中,讓用戶端能偵測不相容的變更。其線路格式記載於 /transports/mcp/。

Premium 工具會使用同一套四級模型宣告自己的風險等級。具破壞性的 Premium 操作(例如塗黑遮蔽)會由完全相同的機制把關。這道 gate 是伺服器的一部分,而不是 Premium 套件的一部分。

  • /connect/tool-catalog/ —— 每個已驗證核心工具的風險等級
  • /connect/configuration/ —— 只能提高的風險覆寫
  • /connect/security-and-operations/ —— 這道 gate 如何契合威脅模型
  • /transports/mcp/ —— 頻道內挑戰的線路格式
  • /connect/overview/ —— 這道 gate 在架構中的位置