

# AgentCore ゲートウェイで誘発を使用する
<a name="gateway-mcp-elicitation"></a>

誘発は、MCP サーバーがツール呼び出し中にクライアントに追加情報をリクエストできるようにする MCP 機能です。ツールがユーザーの確認、認証、または追加の入力を必要とする場合、サーバーは誘発リクエストをクライアントに送り返します。AgentCore Gateway は、MCP サーバーターゲットからの誘発リクエストをクライアントに転送し、リクエストをゲートウェイが生成`id`した識別子に置き換えます。

## 前提条件
<a name="gateway-mcp-elicitation-prereqs"></a>

ゲートウェイで誘発を使用するには、以下が必要です。
+  **セッションが有効** — 誘発にはセッションサポートが必要です。[「ゲートウェイで MCP セッションを使用する](gateway-sessions.md)」を参照してください。
+  **レスポンスストリーミングが有効** — 起動リクエストは、オープン接続中にサーバー送信イベント (SSE) チャンクとして送信されます。ゲートウェイの `true`で `streamingConfiguration.enableResponseStreaming`を に設定します`protocolConfiguration.mcp`。
+  **MCP サーバーターゲットタイプ** — 誘発は MCP サーバーターゲットでのみサポートされています。誘発は MCP サーバーから発信され、ゲートウェイを介してクライアントに転送されます。
+  **クライアントが誘発機能を宣言**する — クライアントは、ゲートウェイが誘発`initialize`リクエストを転送するリクエスト中に誘発のサポートを宣言する必要があります。

## サポートされている誘発モード
<a name="gateway-mcp-elicitation-modes"></a>

AgentCore Gateway は、MCP 仕様で定義された 3 つの誘発モードをサポートしています。


| モード | 説明 | 
| --- | --- | 
|  **フォームモード**  | サーバーは、クライアントが入力するフィールドを含む構造化フォームを送信します。ユーザーの確認、設定、または入力データの収集に使用されます。レスポンスを待っている間、リクエストは開いたままになります。 | 
|  **URL モード (リクエストベース)**  | サーバーは、アクション (通常は認証) を完了するためにユーザーがアクセスする必要がある URL を送信します。アクションの完了を待っている間、リクエストは開いたままになります。 | 
|  **URL モード (例外ベース)**  | サーバーは URL `URLElicitationRequiredError`を含む をスローします。リクエストは終了し、ユーザーは URL でアクションを完了し、クライアントは元のツール呼び出しを再試行します。 | 

## 機能ネゴシエーション
<a name="gateway-mcp-elicitation-capability"></a>

ゲートウェイは、次の場合にのみ MCP サーバーターゲットへの誘発サポートを宣言します。

1. **クライアント**は、 中に誘発サポートを宣言しました`initialize`。

1. **MCP プロトコルバージョン**は誘発モードをサポートしています。`form`モードにはバージョン `2025-03-26` 以降が必要で、`url`モードにはバージョン `2025-11-25`以降が必要です。

1. ゲートウェイは、クライアントによって宣言された特定の誘発機能 (フォーム、URL、またはその両方) と一致します。

## フォームモード誘発フロー
<a name="gateway-mcp-elicitation-form-flow"></a>

1. クライアントは `Mcp-Session-Id`ヘッダーを使用して`tools/call`リクエストを送信します。

1. Gateway は、ツール呼び出しを MCP サーバーターゲットに転送します。

1. ターゲットは SSE ストリームを開き、最初のイベントとして`elicitation/create`リクエストを送信します。

1. Gateway は`elicitation/create`リクエストを SSE ストリームのクライアントに転送し、リクエスト を置き換えます`id`。

1. クライアントはフォームをユーザーに提示し、レスポンスを収集します。

1. クライアントは、同じ を使用して、誘発レスポンス (アクション: `accept`または `decline`) を含む新しいリクエストを送信します`Mcp-Session-Id`。

1. Gateway はレスポンスを MCP サーバーターゲットに転送します。

1. ターゲットは HTTP 202 Accepted で承認します。

1. ターゲットはツール呼び出しを完了し、元の SSE ストリームで最終結果を送信します。

1. Gateway は最終結果をクライアントに転送し、ストリームを閉じます。

## URL モード (例外ベース) 誘発フロー
<a name="gateway-mcp-elicitation-url-exception-flow"></a>

1. クライアントは `Mcp-Session-Id`ヘッダーを使用して`tools/call`リクエストを送信します。

1. Gateway は、ツール呼び出しを MCP サーバーターゲットに転送します。

1. ターゲットは、URL と誘発 ID を含む JSON-RPC エラー`URLElicitationRequiredError`として をスローします。

1. Gateway は をクライアントに転送`URLElicitationRequiredError`し、リクエスト を置き換えます`id`。

1. クライアントは、指定された URL にユーザーをリダイレクトしてアクション (通常は OAuth 認証) を完了します。

1. ユーザーがアクションを完了すると、クライアントは元の`tools/call`リクエストを再試行します。

1. ゲートウェイは再試行をターゲットに転送します。ターゲットは、URL 誘発が満たされたため、ツール呼び出しを完了します。

1. Gateway は、最終的なツール結果をクライアントに転送します。

## 誘発を伴う並列ツール呼び出し
<a name="gateway-mcp-elicitation-parallel"></a>

クライアントは、誘発が保留中であっても、同じセッション内で複数の`tools/call`リクエストを開始できます。各誘発は、その によって個別に追跡されます`id`。誘発レスポンスを送信する場合、クライアントはゲートウェイによって送信された`id`のと同じ を`elicitation/create`リクエストに含める必要があります。

## MCP サーバーターゲット開発者向けガイダンス
<a name="gateway-mcp-elicitation-server-guidance"></a>

**重要**  
誘発リクエストを送信する MCP サーバーターゲットは、誘発呼び出しを try-catch ブロックにラップし、クライアントが誘発をサポートしていない場合を処理する**必要があります**。ゲートウェイのクライアントが誘発機能を宣言しなかった場合、ゲートウェイはそれをターゲットに宣言しません。ターゲットが誘発を送信した場合、ゲートウェイはターゲットに `-32601` (メソッドが見つかりません) エラーを返します。  
誘発が利用できない場合、サーバーはフォールバックパスを実装する必要があります (デフォルト値の使用やオペレーションのスキップなど）。

## エラー処理
<a name="gateway-mcp-elicitation-errors"></a>


| シナリオ | エラー | 説明 | 
| --- | --- | --- | 
| 誘発が保留中でない場合、クライアントは誘発レスポンスを送信します | JSON-RPC `-32600` (無効なリクエスト) | このセッションに一致する誘発が見つかりませんでした。 | 
| クライアントが、保留中の誘発と`id`一致しない で誘発レスポンスを送信する | JSON-RPC `-32600` (無効なリクエスト) | は、`elicitation/create`リクエストでゲートウェイによって送信されたものと一致する`id`必要があります。 | 
| ゲートウェイと MCP サーバーターゲット間の接続中断 | DependencyFailedException による JSON-RPC エラー | クライアントは元のツール呼び出しリクエストを再試行する必要があります。 | 
| クライアントとゲートウェイ間の接続中断 | 該当なし | 保留中の誘発はクリーンアップされます。クライアントはツール呼び出しを再試行する必要があります。 | 
| MCP サーバーが誘発を送信したが、ゲートウェイがサポートを宣言しなかった | JSON-RPC `-32601` (メソッドが見つかりません) | MCP サーバーターゲットに戻ります。[トラブルシューティング](#gateway-mcp-elicitation-troubleshooting)を参照してください。 | 

## トラブルシューティング
<a name="gateway-mcp-elicitation-troubleshooting"></a>

 **エラー: "エラー呼び出しツール 'sample\_tool': メソッドが見つかりません: 誘発/作成"**

このエラーは、MCP サーバーターゲットが誘発リクエストを送信したが、ゲートウェイのクライアントが 中に誘発機能を宣言しなかった場合に発生します`initialize`。ゲートウェイは `-32601` (メソッドが見つからない) エラーをターゲットに返し、ターゲットはこれをツール実行エラーとしてクライアントに返す場合があります。

解決するには:
+  **MCP サーバー開発者の場合**: 誘発呼び出しに関するエラー処理を追加します。誘発がサポートされていない場合は、フォールバックパスを実装します。

  ```
  try:
      result = await context.session.create_elicitation(
          message="Confirm this action?",
          requested_schema={"type": "object", "properties": {"confirm": {"type": "boolean"}}}
      )
  except Exception as e:
      # Fallback when client doesn't support elicitation
      logger.warning(f"Elicitation not supported: {e}")
      result = default_action()
  ```
+  **ゲートウェイクライアント開発者の場合: クライアントが** 中に誘発機能を宣言していることを確認します`initialize`。

  ```
  {
    "capabilities": {
      "elicitation": {
        "form": {},
        "url": {}
      }
    }
  }
  ```

## コードサンプル
<a name="gateway-mcp-elicitation-examples"></a>

### フォームモードの例
<a name="gateway-mcp-elicitation-examples-form"></a>

フォームモードでは、サーバーはクライアントが入力する構造化スキーマを送信します。レスポンスを待っている間、リクエストは開いたままになります。

**Example**  

1. 

   ```
   import requests
   import json
   import sseclient
   
   gateway_url = "https://mygateway-abcdefghij.gateway.bedrock-agentcore.us-west-2.amazonaws.com/mcp"
   headers = {
       "Content-Type": "application/json",
       "Accept": "text/event-stream",
       "Authorization": "Bearer YOUR_ACCESS_TOKEN"
   }
   
   # Step 1: Initialize with elicitation capability
   init_response = requests.post(gateway_url, headers=headers, json={
       "jsonrpc": "2.0",
       "id": "init-request",
       "method": "initialize",
       "params": {
           "protocolVersion": "2025-06-18",
           "capabilities": {"elicitation": {"form": {}, "url": {}}},
           "clientInfo": {"name": "my-agent", "version": "1.0.0"}
       }
   })
   session_id = init_response.headers["Mcp-Session-Id"]
   headers["Mcp-Session-Id"] = session_id
   
   # Step 2: Call tool (streaming response)
   response = requests.post(gateway_url, headers=headers, json={
       "jsonrpc": "2.0",
       "id": "tool-call-1",
       "method": "tools/call",
       "params": {
           "name": "use_aws",
           "arguments": {"command": "aws s3 rm s3://my-bucket/important-file"}
       }
   }, stream=True)
   
   # Step 3: Process SSE events
   client = sseclient.SSEClient(response)
   for event in client.events():
       data = json.loads(event.data)
       if data.get("method") == "elicitation/create":
           elicitation_id = data["id"]
           print(f"Form elicitation received: {data['params']['message']}")
   
           # Step 4: Send elicitation response
           requests.post(gateway_url, headers=headers, json={
               "jsonrpc": "2.0",
               "id": elicitation_id,
               "result": {"action": "accept", "content": {"confirm": True}}
           })
       elif "result" in data:
           print(f"Tool result: {data['result']}")
           break
   ```

1. 

   ```
   from mcp import ClientSession
   from mcp.client.streamable_http import streamablehttp_client
   import asyncio
   
   async def elicitation_handler(request):
       """Handle form elicitation requests from the server."""
       print(f"Elicitation: {request.params.message}")
       return {"action": "accept", "content": {"confirm": True}}
   
   async def use_elicitation(url, token):
       headers = {"Authorization": f"Bearer {token}"}
   
       async with streamablehttp_client(url=url, headers=headers) as (
           read_stream, write_stream, _
       ):
           async with ClientSession(
               read_stream, write_stream,
               elicitation_handler=elicitation_handler
           ) as session:
               await session.initialize()
               result = await session.call_tool(
                   name="use_aws",
                   arguments={"command": "aws s3 rm s3://my-bucket/important-file"}
               )
               print(f"Tool result: {result}")
               return result
   
   asyncio.run(use_elicitation(
       url="https://mygateway-abcdefghij.gateway.bedrock-agentcore.us-west-2.amazonaws.com/mcp",
       token="YOUR_ACCESS_TOKEN"
   ))
   ```

1. 

   ```
   from mcp.client.streamable_http import streamablehttp_client
   from mcp.types import ElicitResult
   from strands import Agent
   from strands.tools.mcp import MCPClient
   
   mcp_url = "https://mygateway-abcdefghij.gateway.bedrock-agentcore.us-west-2.amazonaws.com/mcp"
   access_token = "YOUR_ACCESS_TOKEN"
   
   async def elicitation_callback(context, params):
       """Handle form elicitation requests from the MCP server target."""
       print(f"Elicitation: {params.message}")
       user_response = get_user_input(params)  # Your UI logic
       return ElicitResult(action="accept", content=user_response)
   
   mcp_client = MCPClient(
       lambda: streamablehttp_client(
           mcp_url, headers={"Authorization": f"Bearer {access_token}"}
       ),
       elicitation_callback=elicitation_callback,
   )
   
   with mcp_client:
       agent = Agent(tools=mcp_client.list_tools_sync())
       response = agent("Delete the file s3://my-bucket/important-file using AWS CLI")
       print(response)
   ```

1. 

   ```
   from langchain_mcp_adapters.client import MultiServerMCPClient
   from langchain_mcp_adapters.callbacks import Callbacks, CallbackContext
   from langchain.agents import create_agent
   from mcp.shared.context import RequestContext
   from mcp.types import ElicitRequestParams, ElicitResult
   
   async def on_elicitation(
       mcp_context: RequestContext,
       params: ElicitRequestParams,
       context: CallbackContext,
   ) -> ElicitResult:
       """Handle elicitation requests from MCP servers."""
       print(f"[{context.server_name}] Elicitation: {params.message}")
       # Prompt user for input based on params.requestedSchema
       return ElicitResult(
           action="accept",
           content={"confirm": True},
       )
   
   client = MultiServerMCPClient(
       {
           "gateway": {
               "url": "https://mygateway-abcdefghij.gateway.bedrock-agentcore.us-west-2.amazonaws.com/mcp",
               "transport": "http",
               "headers": {"Authorization": "Bearer YOUR_ACCESS_TOKEN"},
           }
       },
       callbacks=Callbacks(on_elicitation=on_elicitation),
   )
   
   tools = await client.get_tools()
   agent = create_agent("claude-sonnet-4-20250514", tools)
   
   result = await agent.ainvoke(
       {"messages": [{"role": "user", "content": "Delete s3://my-bucket/important-file"}]}
   )
   ```

### URL モードの例
<a name="gateway-mcp-elicitation-examples-url"></a>

URL モードでは、サーバーはユーザーが アクション (通常は OAuth 認証) を完了するためにアクセスする必要がある URL を送信します。ユーザーが URL でアクションを完了するのを待っている間、リクエストは開いたままになります。

**Example**  

1. 

   ```
   import requests
   import json
   import sseclient
   import webbrowser
   
   gateway_url = "https://mygateway-abcdefghij.gateway.bedrock-agentcore.us-west-2.amazonaws.com/mcp"
   headers = {
       "Content-Type": "application/json",
       "Accept": "text/event-stream",
       "Authorization": "Bearer YOUR_ACCESS_TOKEN",
       "Mcp-Session-Id": "session-abc123def456"
   }
   
   # Call tool that triggers URL elicitation
   response = requests.post(gateway_url, headers=headers, json={
       "jsonrpc": "2.0",
       "id": "tool-call-2",
       "method": "tools/call",
       "params": {
           "name": "access_github_repo",
           "arguments": {"repo": "my-org/my-repo"}
       }
   }, stream=True)
   
   # Process SSE events
   client = sseclient.SSEClient(response)
   for event in client.events():
       data = json.loads(event.data)
       if data.get("method") == "elicitation/create":
           elicitation_id = data["id"]
           url = data["params"]["url"]
           print(f"URL elicitation: {data['params']['message']}")
   
           # Open browser for user to complete authentication
           webbrowser.open(url)
           input("Press Enter after completing authentication...")
   
           # Send elicitation response
           requests.post(gateway_url, headers=headers, json={
               "jsonrpc": "2.0",
               "id": elicitation_id,
               "result": {"action": "accept"}
           })
       elif "result" in data:
           print(f"Tool result: {data['result']}")
           break
   ```

1. 

   ```
   from mcp import ClientSession
   from mcp.client.streamable_http import streamablehttp_client
   import asyncio
   import webbrowser
   
   async def elicitation_handler(request):
       """Handle URL elicitation by opening the browser."""
       if hasattr(request.params, 'url') and request.params.url:
           print(f"Opening URL for authentication: {request.params.url}")
           webbrowser.open(request.params.url)
           input("Press Enter after completing authentication...")
           return {"action": "accept"}
       # Form mode fallback
       return {"action": "accept", "content": {}}
   
   async def use_url_elicitation(url, token):
       headers = {"Authorization": f"Bearer {token}"}
   
       async with streamablehttp_client(url=url, headers=headers) as (
           read_stream, write_stream, _
       ):
           async with ClientSession(
               read_stream, write_stream,
               elicitation_handler=elicitation_handler
           ) as session:
               await session.initialize()
               result = await session.call_tool(
                   name="access_github_repo",
                   arguments={"repo": "my-org/my-repo"}
               )
               print(f"Tool result: {result}")
               return result
   
   asyncio.run(use_url_elicitation(
       url="https://mygateway-abcdefghij.gateway.bedrock-agentcore.us-west-2.amazonaws.com/mcp",
       token="YOUR_ACCESS_TOKEN"
   ))
   ```

1. 

   ```
   from mcp.client.streamable_http import streamablehttp_client
   from mcp.types import ElicitResult
   from strands import Agent
   from strands.tools.mcp import MCPClient
   import webbrowser
   
   mcp_url = "https://mygateway-abcdefghij.gateway.bedrock-agentcore.us-west-2.amazonaws.com/mcp"
   access_token = "YOUR_ACCESS_TOKEN"
   
   async def elicitation_callback(context, params):
       """Handle URL elicitation by opening the browser."""
       if hasattr(params, 'url') and params.url:
           print(f"Opening URL: {params.url}")
           webbrowser.open(params.url)
           input("Press Enter after completing authentication...")
           return ElicitResult(action="accept")
       return ElicitResult(action="accept", content={})
   
   mcp_client = MCPClient(
       lambda: streamablehttp_client(
           mcp_url, headers={"Authorization": f"Bearer {access_token}"}
       ),
       elicitation_callback=elicitation_callback,
   )
   
   with mcp_client:
       agent = Agent(tools=mcp_client.list_tools_sync())
       response = agent("Access the my-org/my-repo GitHub repository")
       print(response)
   ```

1. 

   ```
   from langchain_mcp_adapters.client import MultiServerMCPClient
   from langchain_mcp_adapters.callbacks import Callbacks, CallbackContext
   from langchain.agents import create_agent
   from mcp.shared.context import RequestContext
   from mcp.types import ElicitRequestParams, ElicitResult
   import webbrowser
   
   async def on_elicitation(
       mcp_context: RequestContext,
       params: ElicitRequestParams,
       context: CallbackContext,
   ) -> ElicitResult:
       """Handle URL elicitation by opening the browser."""
       if params.url:
           print(f"[{context.server_name}] Opening URL: {params.url}")
           webbrowser.open(params.url)
           input("Press Enter after completing authentication...")
           return ElicitResult(action="accept")
       return ElicitResult(action="accept", content={})
   
   client = MultiServerMCPClient(
       {
           "gateway": {
               "url": "https://mygateway-abcdefghij.gateway.bedrock-agentcore.us-west-2.amazonaws.com/mcp",
               "transport": "http",
               "headers": {"Authorization": "Bearer YOUR_ACCESS_TOKEN"},
           }
       },
       callbacks=Callbacks(on_elicitation=on_elicitation),
   )
   
   tools = await client.get_tools()
   agent = create_agent("claude-sonnet-4-20250514", tools)
   
   result = await agent.ainvoke(
       {"messages": [{"role": "user", "content": "Access the my-org/my-repo GitHub repository"}]}
   )
   ```