コンテンツにスキップ

NextPDF Connect の HITL リスク階層

すべてのツールは、4 つのリスクレベルのいずれかを宣言します。最上位レベルの approval-required は、最初の呼び出しでは実行されません。代わりに、ConfirmationGate が単回使用のチャレンジトークンを返し、エージェントはそのトークンを人間に中継する必要があります。人間は再呼び出しを承認します。

Terminal window
composer require nextpdf/server

リスクモデルには、順序付けられた 4 つのレベルだけが存在します。

レベル意味効果
safe(安全レベル)0読み取り専用、副作用なし自動実行
caution(注意レベル)1メモリ内状態の作成または変更自動実行、監査ログ記録
review(確認レベル)2悪用される可能性のある出力の生成自動実行、監査ログ記録
approval_required(承認必須レベル)3破壊的、法的、またはプライバシー上重要人間による確認が必要

ツールのリスクは、ツール自身の宣言と、任意のオペレーター構成オーバーライドという 2 つの情報源だけから決まります。第 3 の情報源は存在しません。モデルはバージョン番号を保持しており、MCP の initialize レスポンスでその番号を公開するため、クライアントは互換性のない変更を検出できます。監査ログ記録は caution 以上に適用されます。

人間が承認するまで自動化されたアクションを保留することで、自動化がリスクを持ち込むまさにその地点に制御を置けます。これは、人間の行為を通じて持ち込まれるリスクを、その持ち込み地点またはその付近で制御する位置として IEC 31010 が特定しているものです(IEC 31010:2019)。

有効なトークンなしで approval_required ツールが呼び出されると、ゲートはチャレンジを発行します。このチェックは、次の 2 つの形式のいずれかを返します。

{ "allowed": true }

または

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

チャレンジテキストには操作名と説明が含まれ、ターゲットファイルが上書きされる場合は警告も含まれます。これは呼び出し元に対し、発行されたトークンを _confirmation_token パラメーターに設定して、同じツールを再呼び出しするよう指示するものです。トークンは 300 秒で期限切れになります。

トークンのバインドは意図的な設計です。トークンはツール名、ランダムなノンス、TTL にバインドされますが、引数には バインドされません。再試行時、MCP クライアントがキーの順序や正規化を変えて引数を再シリアライズする場合があるため、引数をハッシュ化すると正当な確認が壊れてしまいます。トークンは単回使用です。再呼び出し時に消費され、その呼び出しがちょうど 1 回だけ許可されます。

ゲートは、ツールを駆動するすべてのトランスポートで強制されます。

  • MCP: チャレンジは、成功した JSON-RPC レスポンスとしてインバンドで返され、その内容がチャレンジテキストになります。呼び出し元は、arguments._confirmation_token を付けて tools/call を再呼び出しします。
  • REST と gRPC: 同じゲートが、approval_required 操作の前に共有ツールエグゼキューター内で実行されます。チャレンジは操作レスポンスで提示されます。呼び出し元はトークンを付けてその操作を繰り返します。

構成オーバーライドはツールのリスクレベルを 引き上げる ことはできますが、設計上 approval_required であるツールを引き下げることは決してできません。構成ローダーは固定された重要ツールセットを強制し、オーバーライドがダウングレードを試みた場合はロード時に例外をスローします。サーバーは、弱められたゲートで稼働するのではなく、起動を拒否します。

ファイルを 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_pdf3 より低く設定することはダウングレードです。

  • base64 モードの output_pdf はゲートされません。 ディスクへの書き込みは approval-required ですが、PDF を base64 として返す場合(file_path なし)は、より低いリスクとして扱われ、確認なしで実行されます。

  • トークンはクレデンシャルではありません。 トークンは呼び出し元を認証せず、ネットワークトランスポート上で API キーを置き換えるものでもありません。300 秒以内に、特定のゲートされた呼び出しを 1 回だけ解放するだけです。

  • 毎回新しいチャレンジ。 トークンの中継に失敗したり期限切れになったりしても、ツールが恒久的にブロックされることはありません。次の呼び出しで新しいチャレンジが発行されます。トークンは、定期的なガベージコレクションを伴う単回使用のトークンストアに保存されます。

  • 監査は結果にかかわらず行われます。 チャレンジの発行、実行の成功、caution 以上での実行の失敗は、いずれもツール名とリスクレベルとともに監査ログに記録されます。

ゲートは、トークンストアのルックアップを追加し、チャレンジ時にはランダムトークンの生成も追加します。これはゲートされる操作のコストに対して無視できる程度であり、approval_required ツールに対してのみ実行されます。

ゲートは封じ込め制御であり、認証制御ではありません。これは、自律エージェントがツールを駆動する場合でも、破壊的、法的、またはプライバシー上重要なアクションを人間が承認することを保証します。これらの操作について、サーバーは人間の監督なしで動作するとは主張せず、構成によってゲートを弱めることもできません。ネットワークトランスポート上では API キーモデルと組み合わせ、さらに enabled_tools による最小権限のスコープ設定と組み合わせてください。詳しくは /connect/security-and-operations/ を参照してください。

主張出典reference_id
(人間による)持ち込み地点でリスクを制御するIEC 31010:2019

リスクモデルのバージョンは MCP の initialize レスポンスで伝達されるため、クライアントは互換性のない変更を検出できます。ワイヤーフォーマットは /transports/mcp/ に記載されています。

Premium ツールは、同じ 4 段階モデルを使って独自のリスクレベルを宣言します。破壊的な Premium 操作(たとえば墨消し)は、同じメカニズムでゲートされます。ゲートは Premium パッケージではなく、サーバーの一部です。

  • /connect/tool-catalog/ — 検証済みの各コアツールのリスクレベル
  • /connect/configuration/ — 引き上げ専用のリスクオーバーライド
  • /connect/security-and-operations/ — ゲートが脅威モデルにどのように適合するか
  • /transports/mcp/ — インバンドチャレンジのワイヤーフォーマット
  • /connect/overview/ — ゲートがアーキテクチャ内のどこに位置するか