

# Gunakan elicitation dengan gateway Anda AgentCore
<a name="gateway-mcp-elicitation"></a>

Elicitation adalah fitur MCP yang memungkinkan server MCP untuk meminta informasi tambahan dari klien selama panggilan alat. Ketika alat membutuhkan konfirmasi pengguna, otentikasi, atau input tambahan untuk melanjutkan, server mengirimkan permintaan elisitasi kembali ke klien. AgentCore Gateway meneruskan permintaan dari target server MCP ke klien Anda, menggantikan permintaan `id` dengan pengenal yang dihasilkan gateway.

## Prasyarat
<a name="gateway-mcp-elicitation-prereqs"></a>

Untuk menggunakan elicitation dengan gateway Anda, Anda harus memiliki:
+  **Sesi diaktifkan** - Elicitation membutuhkan dukungan sesi. Lihat [Menggunakan sesi MCP dengan gateway Anda](gateway-sessions.md).
+  **Streaming respons diaktifkan** - Permintaan elicitation dikirim sebagai potongan Server-Sent Acara (SSE) selama koneksi terbuka. Setel `streamingConfiguration.enableResponseStreaming` ke `true` dalam gateway Anda`protocolConfiguration.mcp`.
+  **Jenis target server MCP** - Elicitation hanya didukung untuk target server MCP. Elisitasi berasal dari server MCP dan diteruskan melalui gateway ke klien.
+  **Klien mendeklarasikan kemampuan elisitasi** — Klien harus menyatakan dukungan untuk elisitasi selama permintaan gateway untuk meneruskan `initialize` permintaan elisitasi.

## Mode elisitasi yang didukung
<a name="gateway-mcp-elicitation-modes"></a>

AgentCore Gateway mendukung tiga mode elisitasi yang ditentukan oleh spesifikasi MCP:


| Modus | Deskripsi | 
| --- | --- | 
|  **Mode formulir**  | Server mengirimkan formulir terstruktur dengan bidang untuk diisi klien. Digunakan untuk mengumpulkan konfirmasi pengguna, preferensi, atau data input. Permintaan tetap terbuka sambil menunggu tanggapan. | 
|  **Mode URL (berbasis permintaan)**  | Server mengirimkan URL yang harus dikunjungi pengguna untuk menyelesaikan suatu tindakan (biasanya otentikasi). Permintaan tetap terbuka sambil menunggu tindakan selesai. | 
|  **Mode URL (berbasis pengecualian)**  | Server melempar `URLElicitationRequiredError` berisi URL. Permintaan ditutup, pengguna menyelesaikan tindakan di URL, dan klien mencoba ulang panggilan alat asli. | 

## Negosiasi kemampuan
<a name="gateway-mcp-elicitation-capability"></a>

Gateway hanya mendeklarasikan dukungan elisitasi ke target server MCP jika:

1. **Klien** menyatakan dukungan elisitasi selama. `initialize`

1. **Versi protokol MCP** mendukung mode elicitation — mode memerlukan versi atau yang lebih baru, `form` `url` mode memerlukan versi `2025-03-26` `2025-11-25` atau yang lebih baru.

1. Gateway cocok dengan kemampuan elisitasi spesifik yang dideklarasikan oleh klien (formulir, url, atau keduanya).

## Aliran elisitasi mode bentuk
<a name="gateway-mcp-elicitation-form-flow"></a>

1. Klien mengirimkan `tools/call` permintaan dengan `Mcp-Session-Id` header.

1. Gateway meneruskan panggilan alat ke target server MCP.

1. Target membuka aliran SSE dan mengirimkan `elicitation/create` permintaan sebagai acara pertama.

1. Gateway meneruskan `elicitation/create` permintaan ke klien pada aliran SSE, menggantikan permintaan. `id`

1. Klien menyajikan formulir kepada pengguna dan mengumpulkan respons.

1. Klien mengirimkan permintaan baru dengan respons elisitasi (tindakan: `accept` atau`decline`) menggunakan yang sama. `Mcp-Session-Id`

1. Gateway meneruskan respons ke target server MCP.

1. Target mengakui dengan HTTP 202 Diterima.

1. Target menyelesaikan panggilan alat dan mengirimkan hasil akhir pada aliran SSE asli.

1. Gateway meneruskan hasil akhir ke klien dan menutup aliran.

## Aliran elisitasi mode URL (berbasis pengecualian)
<a name="gateway-mcp-elicitation-url-exception-flow"></a>

1. Klien mengirimkan `tools/call` permintaan dengan `Mcp-Session-Id` header.

1. Gateway meneruskan panggilan alat ke target server MCP.

1. Target melempar `URLElicitationRequiredError` sebagai JSON-RPC kesalahan, berisi URL dan ID elisitasi.

1. Gateway meneruskan `URLElicitationRequiredError` ke klien, menggantikan permintaan`id`.

1. Klien mengarahkan pengguna ke URL yang disediakan untuk menyelesaikan tindakan (biasanya otentikasi OAuth).

1. Setelah pengguna menyelesaikan tindakan, klien mencoba ulang permintaan asli`tools/call`.

1. Gateway meneruskan percobaan lagi ke target. Target menyelesaikan panggilan alat sejak elisitasi URL terpenuhi.

1. Gateway meneruskan hasil alat akhir ke klien.

## Panggilan alat paralel dengan elisitasi
<a name="gateway-mcp-elicitation-parallel"></a>

Klien dapat memulai beberapa `tools/call` permintaan dalam sesi yang sama, bahkan saat elisitasi tertunda. Setiap elisitasi dilacak secara independen olehnya. `id` Saat mengirim respons elisitasi, klien harus menyertakan hal yang sama `id` yang dikirim oleh gateway dalam permintaan. `elicitation/create`

## Panduan untuk pengembang target server MCP
<a name="gateway-mcp-elicitation-server-guidance"></a>

**penting**  
Target server MCP yang mengirim permintaan elisitasi **harus** membungkus panggilan elicitation dalam blok try-catch dan menangani kasus di mana klien tidak mendukung elisitasi. Jika klien gateway tidak mendeklarasikan kemampuan elisitasi, gateway tidak mendeklarasikannya ke target. Jika target tetap mengirimkan elisitasi, gateway mengembalikan kesalahan `-32601` (Metode tidak ditemukan) ke target.  
Server harus mengimplementasikan jalur fallback (seperti menggunakan nilai default atau melewatkan operasi) saat elicitation tidak tersedia.

## Penanganan kesalahan
<a name="gateway-mcp-elicitation-errors"></a>


| Skenario | Kesalahan | Deskripsi | 
| --- | --- | --- | 
| Klien mengirimkan respons elisitasi ketika tidak ada elisitasi yang tertunda | JSON-RPC `-32600`(Permintaan Tidak Valid) | Tidak ada elisitasi yang cocok ditemukan untuk sesi ini. | 
| Klien mengirimkan respons elisitasi dengan yang tidak cocok dengan elisitasi `id` yang tertunda | JSON-RPC `-32600`(Permintaan Tidak Valid) | `id`Harus cocok dengan yang dikirim oleh gateway dalam `elicitation/create` permintaan. | 
| Koneksi terputus antara gateway dan target server MCP | JSON-RPC kesalahan dengan DependencyFailedException | Klien harus mencoba lagi permintaan panggilan alat asli. | 
| Koneksi terputus antara klien dan gateway | N/A | Elisitasi yang tertunda dibersihkan. Klien harus mencoba lagi panggilan alat. | 
| Server MCP mengirimkan elisitasi tetapi gateway tidak menyatakan dukungan | JSON-RPC `-32601`(Metode tidak ditemukan) | Kembali ke target server MCP. Lihat [Pemecahan Masalah](#gateway-mcp-elicitation-troubleshooting). | 

## Pemecahan masalah
<a name="gateway-mcp-elicitation-troubleshooting"></a>

 **Kesalahan: “Kesalahan memanggil alat 'sample\_tool': Metode tidak ditemukan:" elicitation/create** 

Kesalahan ini terjadi ketika target server MCP mengirimkan permintaan elisitasi tetapi klien gateway tidak mendeklarasikan kemampuan elisitasi selama. `initialize` Gateway mengembalikan kesalahan `-32601` (Metode tidak ditemukan) ke target, dan target dapat mengembalikan ini sebagai kesalahan eksekusi alat ke klien.

Untuk menyelesaikan:
+  **Jika Anda adalah pengembang server MCP**: Tambahkan penanganan kesalahan di sekitar panggilan elisitasi Anda. Menerapkan jalur fallback saat elicitation tidak didukung:

  ```
  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()
  ```
+  **Jika Anda adalah pengembang klien gateway: Pastikan klien** Anda mendeklarasikan kemampuan elisitasi selama: `initialize`

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

## Sampel Kode
<a name="gateway-mcp-elicitation-examples"></a>

### Contoh mode formulir
<a name="gateway-mcp-elicitation-examples-form"></a>

Dalam mode formulir, server mengirimkan skema terstruktur untuk diisi klien. Permintaan tetap terbuka sambil menunggu tanggapan.

**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"}]}
   )
   ```

### Contoh mode URL
<a name="gateway-mcp-elicitation-examples-url"></a>

Dalam mode URL, server mengirimkan URL yang harus dikunjungi pengguna untuk menyelesaikan tindakan (biasanya otentikasi OAuth). Permintaan tetap terbuka sambil menunggu pengguna menyelesaikan tindakan di 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"}]}
   )
   ```