Claude Media
MCPのElicitation、フォームとURLで何が違うか

MCPのElicitation、フォームとURLで何が違うか

MCP ElicitationのFormモードとURLモードの違いと、パスワードなど機密情報でURLモードが必須になる理由をClaude Codeの実装で確認します。

MCPのElicitationは、サーバーがタスクの途中でユーザーに追加入力を求める仕組みです。仕様は入力の集め方をフォームモードとURLモードの2つに分けており、両者は用途が明確に線引きされています。パスワード・APIキー・アクセストークンなどの機密情報は、フォームモードでの要求が仕様上禁止され、URLモードの使用が必須です。Claude CodeはMCPクライアントとして両モードを実装しており、Elicitationフックで応答を自動化することもできます。

Elicitationとは何をする仕組みか

Elicitationは、MCPサーバーがツール呼び出しの処理中に「情報が足りない」と判断したとき、クライアント経由でユーザーに追加入力を求めるプロトコル機能です。ツール呼び出し1回で完結させず、サーバーが「入力が必要」という結果を返し、クライアントがユーザーとやり取りしたうえで元のリクエストを再送する、という往復構造になっています。

Claude Codeでは設定不要で、サーバーがElicitationを要求すると対話ダイアログが自動的に表示されます。フォーム型ならダイアログにフィールドが並び、URL型ならブラウザでURLが開きます。

フォームモードとURLモードの違い

フォームモードURLモード
データの流れフォームモードクライアント経由(帯域内)URLモードクライアントを経由しない(帯域外)
入力形式フォームモードJSON Schemaで定義した構造化データURLモード外部URLへのナビゲーション
想定用途フォームモード名前・メール・選択肢などの一般情報URLモード認証フロー・決済処理・機密情報の入力
クライアントが見る内容フォームモード送信されたデータそのものURLモードURLのみ(入力内容は見えない)
機密情報(パスワード等)フォームモード仕様上禁止URLモード仕様上必須

仕様の警告はこの一点に集約されます。

Servers MUST NOT use form mode elicitation to request sensitive information such as passwords, API keys, access tokens, or payment credentials. Servers MUST use URL mode for interactions involving such sensitive information.

「サーバーはパスワード・APIキー・アクセストークン・決済情報などの機密情報をフォームモードで要求してはならず、これらを扱う場合はURLモードを使わなければならない」という、仕様の中でも数少ない断定的な必須要件です。「機密情報」の定義も明確です。取引を承認したりアクセス権を与えたりする秘密・資格情報が対象で、氏名・メールアドレス・ユーザー名のような一般的な連絡先情報は対象外です。一般情報をフォームモードで求めるかどうかはサーバーの裁量に委ねられており、禁止されているわけではありません。

フォームモードのスキーマは意図的に制限されている

フォームモードのrequestedSchemaは、JSON Schemaの全機能を使えるわけではありません。フラットなオブジェクトで、プロパティはプリミティブ型のみという制約があります。対応する型は次の4つです。

  • String: minLength / maxLength / format(email / uri / date / date-time)
  • Number(integer含む): minimum / maximum
  • Boolean
  • Enum: 単一選択・複数選択、タイトル付き選択肢にも対応

ネストしたオブジェクトや、enum以外の配列は仕様上サポート対象外です。理由は「クライアント側のフォーム生成・入力体験をシンプルに保つため」と明記されています。実際のリクエスト例です。

{
  "method": "elicitation/create",
  "params": {
    "mode": "form",
    "message": "Please provide your GitHub username",
    "requestedSchema": {
      "type": "object",
      "properties": { "name": { "type": "string" } },
      "required": ["name"]
    }
  }
}

URLモードは「MCPクライアントの認証」とは別物

URLモードは、MCPクライアントとサーバー間の認証(MCP authorization)とは目的が異なります。MCPサーバーが第三者サービスの認可を取り付ける仕組みです。

典型はサーバーが外部SaaSのOAuthクライアントとして動く場面です。サーバーはURLモードのElicitationでユーザーをブラウザへ誘導し、ユーザーは第三者の認可画面で同意し、サーバーはコールバックで受け取ったトークンをユーザーIDに紐づけて保存します。この一連の流れでMCPクライアント自身の認証トークンは一切変わりません。仕様が明記する必須要件は3つです。

  1. 第三者の認証情報がMCPクライアントを経由してはならない
  2. サーバーはMCPクライアントの認証情報を第三者サービスへ横流ししてはならない(token passthrough禁止)
  3. Elicitationを開始したユーザー本人が、認可フローも完了させなければならない(なりすまし対策)

3点目はフィッシング対策として重要です。悪意あるユーザーがElicitationのURLを生成させ、それを別の被害者に開かせると、被害者が完了した第三者認可が悪意あるユーザーのセッションに紐づいてしまう恐れがあります。仕様はサーバー側に、Elicitationを開始した本人と認可フローを完了する本人が同一であることをセッションCookie等で確認するよう求めています。

Claude CodeはURLモードのURLを渡す長さに上限がある

Claude CodeはURLモードのURLをコマンドライン引数としてOSのURLハンドラーへ渡す設計上、渡せるURLの長さに上限があります。エスケープが必要な文字(%&など)は、その文字自身とエスケープ用の3文字を合わせて4倍分をカウントします。

自作のMCPサーバーがURLモードElicitationを使う場合、認可URLに長大なクエリパラメータを積み込む設計は避けたほうが安全です。

クライアントはURLモードのURLをどう扱うべきか

URLモードは「ユーザーがクリックする前に何が起きるURLか分かること」が安全性の前提です。仕様はクライアント側に次のような扱いを求めています。

  • URLやそのメタデータを事前に自動フェッチしない
  • ユーザーの明示的な同意なしにURLを開かない
  • URL全体をユーザーに見せてから同意を取る
  • ドメイン部分を強調表示し、サブドメインを使ったなりすましに気づきやすくする
  • Punycode(見た目が紛らわしい国際化ドメイン)を含む疑わしいURLには警告を出す
  • ブラウザを開く際は、クライアントやLLM自身がページの中身・入力内容を覗き見できない方式にする(iOSでいえばSFSafariViewControllerのような専用ビューが該当し、WKWebViewのような埋め込み方式は不適切とされています)

最後の点は地味に重要です。URLモードの目的は「LLMやMCPクライアントに機密情報を触れさせない」ことなので、開いたページの中身をクライアント側から覗ける実装ではその前提が崩れます

応答は3種類 — Accept / Decline / Cancel

フォーム・URLどちらのモードでも、ユーザーの応答は3つのアクションに分かれます。

  • Accept: 明示的に承認して送信(フォームならcontentにデータを含む)
  • Decline: 明示的に拒否(「いいえ」を選択した状態)
  • Cancel: ダイアログを閉じる・Escapeを押す等、明確な選択をせずに離脱した状態

DeclineとCancelを同一視するとユーザー体験を損ないます。仕様はサーバー側に「Declineには代替案の提示」「Cancelには後で再度促す」といった別処理を推奨しています。

Claude Codeで応答を自動化する — Elicitationフック

Elicitationダイアログを毎回手動で処理したくない場合、Elicitationフックで自動応答を組めます。フックはツール呼び出し中にMCPサーバーがユーザー入力を求めたタイミングで発火し、mcp_server_namemessagemode・(URLモードなら)urlを受け取ります。

{
  "hook_event_name": "Elicitation",
  "mcp_server_name": "example-server",
  "message": "Please provide your GitHub username",
  "mode": "form"
}

出力側でhookSpecificOutputaction(accept / decline / cancel)と、フォームモードならcontentを返すことで、ダイアログを表示せずに応答を確定できます。exit code 2を返すとElicitationそのものを拒否扱いにできます。応答が送信された直後にもう一段フックを挟みたい場合は、ElicitationResultフックで応答内容を観察・上書き・ブロックできます。

CIやheadlessモードでMCPサーバーからの入力待ちに毎回人手が要る運用を避けたいときは、この2つのフックが実質的な唯一の自動化経路です。フックイベント全体の設定方法はClaude Code Hooks完全ガイドにまとめています。

MCPサーバー側の実装で気をつけること

自分でMCPサーバーを書いてElicitationを実装する場合、仕様が課す制約は次の3点です。

  • フォームモードで機密情報を要求しない(パスワード・APIキー・アクセストークン・決済情報)
  • URLモードのURLには、事前認証済みでアクセスできるURL(いわゆるマジックリンク)を含めない — クライアントによるなりすましのリスクがあるため
  • URLモードで送るURLには、エンドユーザーの個人情報や認証情報そのものを含めない

サーバーごとにどこまでの操作を許可するかという権限設計は、MCPセキュリティガイドでも扱っています。リモートMCPサーバーでOAuth認可を実装する場合は、Elicitationとは別レイヤーの話になるためリモートMCPのOAuth認証を合わせて確認してください。

まとめ

MCP ElicitationはフォームモードとURLモードの2つに分かれ、機密情報の扱いだけは仕様上の明文規定があります。パスワード・APIキー・アクセストークン・決済情報はフォームモードで要求してはならず、URLモードで別ドメインの安全な画面に逃がす設計が必須です。Claude Codeは両モードを自動でダイアログ表示しつつ、Elicitation/ElicitationResultフックで応答を自動化する経路も持っています。自作のMCPサーバーを書く場合は、機密情報を扱うすべての入力要求をURLモードに寄せることと、認可フローの開始者と完了者が同一であることの確認を、実装の出発点にしてください。

この記事を共有:XはてブLinkedIn