跳转到内容

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 在架构中的位置