View a markdown version of this page

Usa l'elicitazione con il tuo gateway AgentCore - Amazon Bedrock AgentCore

Usa l'elicitazione con il tuo gateway AgentCore

L'elicitazione è una funzionalità MCP che consente a un server MCP di richiedere informazioni aggiuntive al client durante una chiamata allo strumento. Quando uno strumento richiede la conferma dell'utente, l'autenticazione o un input aggiuntivo per procedere, il server invia una richiesta di elicitazione al client. AgentCore Gateway inoltra le richieste di elicitazione dalle destinazioni del server MCP ai client, sostituendo la richiesta id con un identificatore generato dal gateway.

Prerequisiti

Per utilizzare l'elicitazione con il gateway, è necessario disporre di:

  • Sessioni abilitate: Elicitation richiede il supporto della sessione. Vedi Utilizzare le sessioni MCP con il gateway.

  • Streaming di risposta abilitato: le richieste di elicitazione vengono inviate come blocchi di Server-Sent eventi (SSE) durante una connessione aperta. Imposta su true nel streamingConfiguration.enableResponseStreaming tuo gateway. protocolConfiguration.mcp

  • Tipo di destinazione del server MCP: l'elicitazione è supportata solo per le destinazioni del server MCP. L'elicitazione proviene dal server MCP e viene inoltrata al client tramite il gateway.

  • Il client dichiara la capacità di elicitazione: il client deve dichiarare il supporto per l'elicitazione durante la richiesta al gateway di inoltrare le initialize richieste di elicitazione.

Modalità di elicitazione supportate

AgentCore Gateway supporta tre modalità di elicitazione definite dalla specifica MCP:

Modalità Description

modalità Form

Il server invia un modulo strutturato con campi da compilare per il client. Utilizzato per raccogliere conferme utente, preferenze o dati di input. La richiesta rimane aperta in attesa della risposta.

Modalità URL (basata su richiesta)

Il server invia un URL che l'utente deve visitare per completare un'azione (in genere l'autenticazione). La richiesta rimane aperta in attesa del completamento dell'azione.

Modalità URL (basata su eccezioni)

Il server genera un URL URLElicitationRequiredError contenente. La richiesta viene chiusa, l'utente completa l'azione sull'URL e il client riprova la chiamata allo strumento originale.

Negoziazione delle capacità

Il gateway dichiara il supporto per l'elicitazione su una destinazione del server MCP solo se:

  1. Il client ha dichiarato il supporto per l'elicitazione durante. initialize

  2. La versione del protocollo MCP supporta la modalità elicitazione: la form modalità richiede una versione 2025-03-26 o successiva, le url modalità richiedono una versione 2025-11-25 o successiva.

  3. Il gateway corrisponde alle funzionalità di elicitazione specifiche dichiarate dal client (modulo, url o entrambi).

Flusso di elicitazione in modalità Form

  1. Il client invia una tools/call richiesta con l'Mcp-Session-Idintestazione.

  2. Gateway inoltra la chiamata allo strumento alla destinazione del server MCP.

  3. Il target apre un flusso SSE e invia una elicitation/create richiesta come primo evento.

  4. Gateway inoltra la elicitation/create richiesta al client nel flusso SSE, sostituendo la richiesta. id

  5. Il client presenta il modulo all'utente e raccoglie la risposta.

  6. Il client invia una nuova richiesta con la risposta di elicitazione (action: accept ordecline) utilizzando la stessa. Mcp-Session-Id

  7. Gateway inoltra la risposta alla destinazione del server MCP.

  8. La destinazione riconosce con HTTP 202 Accepted.

  9. Il target completa la chiamata allo strumento e invia il risultato finale sul flusso SSE originale.

  10. Gateway inoltra il risultato finale al client e chiude lo stream.

Flusso di elicitazione in modalità URL (basato su eccezioni)

  1. Il client invia una tools/call richiesta con l'intestazione. Mcp-Session-Id

  2. Gateway inoltra la chiamata allo strumento alla destinazione del server MCP.

  3. La destinazione genera un URLElicitationRequiredError messaggio di JSON-RPC errore, contenente l'URL e un ID di elicitazione.

  4. Gateway inoltra il file URLElicitationRequiredError al client, sostituendo la richiesta. id

  5. Il client reindirizza l'utente all'URL fornito per completare l'azione (in genere l'autenticazione OAuth).

  6. Dopo che l'utente ha completato l'azione, il client ritenta la richiesta originale. tools/call

  7. Gateway inoltra il nuovo tentativo alla destinazione. Il target completa la chiamata allo strumento non appena è stata completata la richiesta dell'URL.

  8. Gateway inoltra il risultato finale dello strumento al client.

Lo strumento parallelo chiama con elicitazioni

Un client può avviare più tools/call richieste all'interno della stessa sessione, anche se un'elicitazione è in sospeso. Ogni elicitazione viene tracciata indipendentemente dalla sua. id Quando invia una risposta di elicitazione, il client deve includere nella richiesta la stessa id che è stata inviata dal gateway. elicitation/create

Linee guida per gli sviluppatori di server MCP destinati agli sviluppatori

Importante

I target del server MCP che inviano richieste di elicitazione devono racchiudere le chiamate di elicitazione in blocchi try-catch e gestire il caso in cui il client non supporti l'elicitazione. Se il client del gateway non ha dichiarato la capacità di elicitazione, il gateway non la dichiara alla destinazione. Se il target invia comunque un'elicitazione, il gateway restituisce un errore -32601 (Metodo non trovato) al bersaglio.

I server devono implementare un percorso di fallback (ad esempio utilizzando valori predefiniti o saltando l'operazione) quando l'elicitazione non è disponibile.

Gestione degli errori

Scenario Errore Description

Il client invia una risposta di elicitazione quando nessuna elicitazione è in sospeso

JSON-RPC -32600(Richiesta non valida)

Nessuna elicitazione corrispondente trovata per questa sessione.

Il client invia una risposta di elicitazione con una id che non corrisponde a una elicitazione in sospeso

JSON-RPC -32600(Richiesta non valida)

idDeve corrispondere a quello inviato dal gateway nella elicitation/create richiesta.

Interruzioni di connessione tra il gateway e la destinazione del server MCP

JSON-RPC errore con DependencyFailedException

Il client deve riprovare la richiesta originale di chiamata allo strumento.

Interruzioni di connessione tra client e gateway

N/A

L'elicitazione in sospeso viene ripulita. Il client deve ripetere la chiamata allo strumento.

Il server MCP invia l'elicitazione ma il gateway non ha dichiarato il supporto

JSON-RPC -32601(Metodo non trovato)

Restituito alla destinazione del server MCP. Vedere Risoluzione dei problemi.

Risoluzione dei problemi

Errore: «Errore durante la chiamata dello strumento 'sample_tool': Metodo non trovato:" elicitation/create

Questo errore si verifica quando una destinazione del server MCP invia una richiesta di elicitazione ma il client del gateway non ha dichiarato la capacità di elicitazione durante l'operazione. initialize Il gateway restituisce un errore -32601 (Method not found) alla destinazione e la destinazione può restituirlo al client come errore di esecuzione dello strumento.

Per risolvere:

  • Se sei lo sviluppatore del server MCP: aggiungi la gestione degli errori nelle chiamate di elicitazione. Implementa un percorso di fallback quando l'elicitazione non è supportata:

    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()
  • Se sei lo sviluppatore del client gateway: assicurati che il cliente dichiari la capacità di elicitazione durante: initialize

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

Esempi di codice

Esempio di modalità Form

In modalità modulo, il server invia al client uno schema strutturato da compilare. La richiesta rimane aperta in attesa della risposta.

Esempio
Python requests package
  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
MCP Client
  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" ))
Strands MCP Client
  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)
LangGraph MCP Client
  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"}]} )

Esempio di modalità URL

In modalità URL, il server invia un URL che l'utente deve visitare per completare un'azione (in genere l'autenticazione OAuth). La richiesta rimane aperta in attesa che l'utente completi l'azione sull'URL.

Esempio
Python requests package
  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
MCP Client
  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" ))
Strands MCP Client
  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)
LangGraph MCP Client
  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"}]} )