View a markdown version of this page

Utilisez l'élicitation avec votre passerelle AgentCore - Amazon Bedrock AgentCore

Utilisez l'élicitation avec votre passerelle AgentCore

L'élicitation est une fonctionnalité MCP qui permet à un serveur MCP de demander des informations supplémentaires au client lors d'un appel d'outil. Lorsqu'un outil a besoin d'une confirmation de l'utilisateur, d'une authentification ou d'une saisie supplémentaire pour continuer, le serveur renvoie une demande d'élicitation au client. AgentCore Gateway transmet les demandes de sollicitation des cibles du serveur MCP à vos clients, en remplaçant la demande id par un identifiant généré par la passerelle.

Conditions préalables

Pour utiliser l'élicitation avec votre passerelle, vous devez disposer des éléments suivants :

  • Sessions activées — L'élicitation nécessite un support de session. Consultez la section Utiliser des sessions MCP avec votre passerelle.

  • Streaming de réponses activé — Les demandes d'élicitation sont envoyées sous forme de segments d' Server-Sent événements (SSE) lors d'une connexion ouverte. streamingConfiguration.enableResponseStreamingRéglez sur true celui de votre passerelleprotocolConfiguration.mcp.

  • Type de cible de serveur MCP — L'élicitation n'est prise en charge que pour les cibles de serveur MCP. L'élicitation provient du serveur MCP et est transmise au client par le biais de la passerelle.

  • Le client déclare sa capacité d'élicitation — Le client doit déclarer son soutien à l'élicitation lors de la initialize demande à la passerelle de transférer les demandes d'élicitation.

Modes de sollicitation pris en charge

AgentCore Gateway prend en charge trois modes d'élicitation définis par la spécification MCP :

Mode Description

Mode formulaire

Le serveur envoie un formulaire structuré avec des champs que le client doit remplir. Utilisé pour collecter les confirmations, les préférences ou les données d'entrée des utilisateurs. La demande reste ouverte en attendant la réponse.

Mode URL (basé sur les demandes)

Le serveur envoie une URL que l'utilisateur doit consulter pour effectuer une action (généralement une authentification). La demande reste ouverte en attendant que l'action soit terminée.

Mode URL (basé sur les exceptions)

Le serveur renvoie une URL URLElicitationRequiredError contenant une URL. La demande se ferme, l'utilisateur exécute l'action sur l'URL et le client tente à nouveau l'appel d'outil d'origine.

Négociation des capacités

La passerelle déclare la prise en charge de l'élicitation à une cible de serveur MCP uniquement si :

  1. Le client a déclaré un soutien à l'élicitation au cours de. initialize

  2. La version du protocole MCP prend en charge le mode d'élicitation : le form mode nécessite une version 2025-03-26 ou une version ultérieure, les url modes nécessitent une version ou une version 2025-11-25 ultérieure.

  3. La passerelle correspond aux capacités d'élicitation spécifiques déclarées par le client (formulaire, URL ou les deux).

Flux d'élicitation en mode formulaire

  1. Le client envoie une tools/call demande avec l'Mcp-Session-Iden-tête.

  2. Gateway transmet l'appel d'outil à la cible du serveur MCP.

  3. La cible ouvre un flux SSE et envoie une elicitation/create demande en tant que premier événement.

  4. Gateway transmet la elicitation/create demande au client sur le flux SSE, en remplaçant la demandeid.

  5. Le client présente le formulaire à l'utilisateur et recueille la réponse.

  6. Le client envoie une nouvelle demande avec la réponse à l'élicitation (action : accept oudecline) en utilisant celle-ci. Mcp-Session-Id

  7. Gateway transmet la réponse à la cible du serveur MCP.

  8. La cible accuse réception avec HTTP 202 Accepted.

  9. La cible termine l'appel à l'outil et envoie le résultat final sur le flux SSE d'origine.

  10. Gateway transmet le résultat final au client et ferme le flux.

Flux d'élicitation en mode URL (basé sur les exceptions)

  1. Le client envoie une tools/call demande avec l'Mcp-Session-Iden-tête.

  2. Gateway transmet l'appel d'outil à la cible du serveur MCP.

  3. La cible renvoie un JSON-RPC message URLElicitationRequiredError d'erreur contenant l'URL et un identifiant d'élicitation.

  4. Gateway le transmet URLElicitationRequiredError au client en remplaçant la demandeid.

  5. Le client redirige l'utilisateur vers l'URL fournie pour terminer l'action (généralement l'authentification OAuth).

  6. Une fois que l'utilisateur a terminé l'action, le client réessaie la tools/call demande d'origine.

  7. Gateway transmet la nouvelle tentative à la cible. La cible termine l'appel à l'outil puisque l'obtention de l'URL a été effectuée.

  8. Gateway transmet le résultat final de l'outil au client.

Appels d'outils parallèles avec sollicitations

Un client peut lancer plusieurs tools/call demandes au cours d'une même session, même si une demande est en attente. Chaque sollicitation est suivie indépendamment par son. id Lors de l'envoi d'une réponse à une sollicitation, le client doit inclure la même réponse id que celle envoyée par la passerelle dans la elicitation/create demande.

Conseils pour les développeurs cibles de serveurs MCP

Important

Les cibles du serveur MCP qui envoient des demandes d'élicitation doivent encapsuler les appels dans des blocs trycatch et gérer les cas où le client ne prend pas en charge l'élicitation. Si le client de la passerelle n'a pas déclaré de capacité d'élicitation, la passerelle ne la déclare pas à la cible. Si la cible envoie quand même une élicitation, la passerelle renvoie une erreur -32601 (Method not found) à la cible.

Les serveurs doivent implémenter un chemin de secours (par exemple en utilisant des valeurs par défaut ou en sautant l'opération) lorsque l'élicitation n'est pas disponible.

Gestion des erreurs

Scénario Erreur Description

Le client envoie une réponse à une sollicitation lorsqu'aucune sollicitation n'est en attente

JSON-RPC -32600(Demande non valide)

Aucune élicitation correspondante n'a été trouvée pour cette session.

Le client envoie une réponse à une sollicitation avec un message id qui ne correspond pas à une demande en attente

JSON-RPC -32600(Demande non valide)

Le id doit correspondre à celui envoyé par la passerelle dans la elicitation/create demande.

Interruptions de connexion entre la passerelle et la cible du serveur MCP

JSON-RPC erreur avec DependencyFailedException

Le client doit réessayer la demande d'appel d'outil d'origine.

Interruptions de connexion entre le client et la passerelle

N/A

L'élicitation en attente est nettoyée. Le client doit réessayer d'appeler l'outil.

Le serveur MCP envoie une demande mais la passerelle n'a pas déclaré de support

JSON-RPC -32601(Méthode introuvable)

Retourné à la cible du serveur MCP. Consultez la section Résolution des problèmes.

Résolution des problèmes

Erreur : « Erreur lors de l'appel de l'outil 'sample_tool' : méthode introuvable : » elicitation/create

Cette erreur se produit lorsqu'une cible du serveur MCP envoie une demande d'élicitation mais que le client de la passerelle n'a pas déclaré de capacité d'élicitation au cours de cette opération. initialize La passerelle renvoie une erreur -32601 (Method not found) à la cible, et la cible peut la renvoyer sous forme d'erreur d'exécution de l'outil au client.

Pour résoudre le problème :

  • Si vous êtes le développeur du serveur MCP : ajoutez la gestion des erreurs à vos appels de sollicitation. Implémentez un chemin de secours lorsque l'élicitation n'est pas prise en charge :

    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()
  • Si vous êtes le développeur du client Gateway : assurez-vous que votre client déclare sa capacité d'élicitation pendant : initialize

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

Exemples de code

Exemple de mode formulaire

En mode formulaire, le serveur envoie un schéma structuré que le client doit remplir. La demande reste ouverte en attendant la réponse.

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

Exemple de mode URL

En mode URL, le serveur envoie une URL que l'utilisateur doit consulter pour effectuer une action (généralement une authentification OAuth). La demande reste ouverte en attendant que l'utilisateur termine l'action sur l'URL.

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