View a markdown version of this page

AgentCore 게이트웨이에서 유도 사용 - Amazon Bedrock AgentCore

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

AgentCore 게이트웨이에서 유도 사용

유도는 MCP 서버가 도구 호출 중에 클라이언트에 추가 정보를 요청할 수 있도록 하는 MCP 기능입니다. 도구를 진행하기 위해 사용자 확인, 인증 또는 추가 입력이 필요한 경우 서버는 유도 요청을 클라이언트로 다시 보냅니다. AgentCore Gateway는 MCP 서버 대상의 유도 요청을 클라이언트로 전달하여 요청을 게이트웨이 생성 식별자id로 바꿉니다.

사전 조건

게이트웨이에서 유도를 사용하려면 다음이 필요합니다.

  • 활성화된 세션(버전 2025-11-25 이하) - 유도에는 세션 지원이 필요합니다. 게이트웨이에서 MCP 세션 사용을 참조하세요. 버전 2026-07-28 이상의 경우 게이트웨이sessionConfiguration에를 추가할 필요가 없습니다. 이러한 버전은 상태 비저장 버전이기 때문입니다.

  • 응답 스트리밍 활성화됨(버전 2025-11-25 이하) - 유도 요청은 열린 연결 중에 Server-Sent Events(SSE) 청크로 전송됩니다. 게이트웨이의 true에서를 streamingConfiguration.enableResponseStreaming로 설정합니다protocolConfiguration.mcp. 버전 2026-07-28 이상의 경우 응답 스트리밍을 활성화할 필요가 없습니다. 이러한 버전은 응답 스트림에서 서버 시작 요청 대신 다중 왕복 요청(MRTR) 패턴을 통해 유도를 제공합니다. 자세한 내용은 모델 컨텍스트 프로토콜 설명서의 다중 왕복 요청을 참조하세요.

  • MCP 서버 대상 유형 - 유도는 MCP 서버 대상에 대해서만 지원됩니다. 유도는 MCP 서버에서 시작되며 게이트웨이를 통해 클라이언트로 전달됩니다.

  • 클라이언트가 유도 기능 선언 - 클라이언트는 게이트웨이가 유도 요청을 전달할 수 있도록 유도 지원을 선언해야 합니다. 버전 2025-11-25 이하의 경우 클라이언트는 initialize 요청에서이 지원을 선언합니다. 버전 2026-07-28 이상의 경우 클라이언트는 _meta 필드()의 각 요청에 대한 기능을 선언합니다io.modelcontextprotocol/clientCapabilities.

지원되는 유도 모드

AgentCore Gateway는 MCP 사양에 정의된 세 가지 유도 모드를 지원합니다.

Mode 설명

양식 모드

서버는 클라이언트가 작성할 필드가 포함된 구조화된 양식을 전송합니다. 사용자 확인, 기본 설정 또는 입력 데이터를 수집하는 데 사용됩니다. 요청은 응답을 기다리는 동안 열린 상태로 유지됩니다.

URL 모드(요청 기반)

서버는 사용자가 작업(일반적으로 인증)을 완료하기 위해 방문해야 하는 URL을 보냅니다. 작업이 완료될 때까지 기다리는 동안 요청은 열린 상태로 유지됩니다.

URL 모드(예외 기반)

서버는 URL이 URLElicitationRequiredError 포함된를 발생시킵니다. 요청이 종료되고, 사용자가 URL에서 작업을 완료하고, 클라이언트가 원래 도구 호출을 재시도합니다.

역량 협상

게이트웨이는 다음과 같은 경우에만 MCP 서버 대상에 대한 유도 지원을 선언합니다.

  1. 클라이언트는 유도 지원을 선언했습니다. 버전 2025-11-25 이하의 경우 클라이언트는 중에 이를 선언합니다initialize. 버전 2026-07-28 이상의 경우 클라이언트는의 각 요청에 대해 이를 선언합니다_meta.

  2. MCP 프로토콜 버전은 유도 모드를 지원합니다. form 모드에는 버전 2025-03-26 이상이 필요합니다. url 모드에는 버전 2025-11-25 이상이 필요합니다.

  3. 게이트웨이는 클라이언트가 선언한 특정 유도 기능(형식, URL 또는 둘 다)과 일치합니다.

양식 모드 유도 흐름

참고

여기에 설명된 흐름은 서버가 열린 SSE 스트림에서 서버 시작 요청elicitation/create으로 전송하는 버전 2025-11-25 이하에 적용됩니다. 버전 2026-07-28 이상의 경우 유도는 대신 다중 왕복 요청(MRTR) 패턴을 사용합니다. 서버는 중간 결과를 반환하고 클라이언트는 수집된 입력으로 원래 요청을 재시도합니다. 자세한 내용은 모델 컨텍스트 프로토콜 설명서의 다중 왕복 요청을 참조하세요.

  1. 클라이언트는 Mcp-Session-Id 헤더와 함께 tools/call 요청을 보냅니다.

  2. Gateway는 도구 호출을 MCP 서버 대상으로 전달합니다.

  3. 대상이 SSE 스트림을 열고 첫 번째 이벤트로 elicitation/create 요청을 보냅니다.

  4. Gateway는 SSE 스트림의 클라이언트에 elicitation/create 요청을 전달하여 요청을 교체합니다id.

  5. 클라이언트는 사용자에게 양식을 제공하고 응답을 수집합니다.

  6. 클라이언트는 동일한를 사용하여 유도 응답(작업: accept 또는 decline)과 함께 새 요청을 보냅니다Mcp-Session-Id.

  7. Gateway는 응답을 MCP 서버 대상에 전달합니다.

  8. 대상이 HTTP 202 Accepted로 승인합니다.

  9. 대상이 도구 호출을 완료하고 원래 SSE 스트림에서 최종 결과를 전송합니다.

  10. Gateway는 최종 결과를 클라이언트에 전달하고 스트림을 닫습니다.

URL 모드(예외 기반) 유도 흐름

  1. 클라이언트는 Mcp-Session-Id 헤더와 함께 tools/call 요청을 보냅니다.

  2. Gateway는 도구 호출을 MCP 서버 대상으로 전달합니다.

  3. 대상은 URL과 유도 ID가 포함된를 JSON-RPC 오류URLElicitationRequiredError로 발생시킵니다.

  4. Gateway는를 클라이언트에 전달URLElicitationRequiredError하여 요청을 바꿉니다id.

  5. 클라이언트는 사용자를 제공된 URL로 리디렉션하여 작업을 완료합니다(일반적으로 OAuth 인증).

  6. 사용자가 작업을 완료하면 클라이언트는 원래 tools/call 요청을 재시도합니다.

  7. Gateway는 재시도를 대상으로 전달합니다. URL 유도가 이행된 이후 대상이 도구 호출을 완료합니다.

  8. Gateway는 최종 도구 결과를 클라이언트에 전달합니다.

유도를 사용한 병렬 도구 호출

클라이언트는 유도가 보류 중인 동안에도 동일한 세션 내에서 여러 tools/call 요청을 시작할 수 있습니다. 각 유도는에 의해 독립적으로 추적됩니다id. 유도 응답을 보낼 때 클라이언트는 게이트웨이에서 보낸 id 것과 동일한를 elicitation/create 요청에 포함해야 합니다.

MCP 서버 대상 개발자를 위한 지침

중요

유도 요청을 보내는 MCP 서버 대상은 유도 호출을 try-catch 블록으로 래핑하고 클라이언트가 유도를 지원하지 않는 경우를 처리해야 합니다. 게이트웨이의 클라이언트가 유도 기능을 선언하지 않은 경우 게이트웨이는 이를 대상으로 선언하지 않습니다. 대상이 어쨌든 유도를 보내면 게이트웨이는 대상에 -32601 (메서드를 찾을 수 없음) 오류를 반환합니다.

서버는 유도를 사용할 수 없는 경우 대체 경로(예: 기본값 사용 또는 작업 건너뛰기)를 구현해야 합니다.

요청 상태 보안(버전 2026-07-28 이상)

버전 2026-07-28 이상에서는 유도가 클라이언트와 MCP 서버 대상 requestState 간에 불투명한 다중 왕복 요청(MRTR) 패턴을 사용합니다. 이 값을 보호하는 것은 공동 책임입니다. 게이트웨이는 값을 저장하지 않고 권한을 부여하고 전달하는 반면, MCP 서버 대상은 값을 검증하고 한 사용자가 다른 사용자의 요청 상태를 재생하지 못하도록 해야 합니다. MCP 서버가 따라야 하는 전체 공동 책임 모델 및 보호 지침은 MCP 서버 대상 고려 사항의 유도 및 샘플링을 위한 요청 상태 보호를 참조하세요.

오류 처리

시나리오 오류 설명

대기 중인 유도가 없을 때 클라이언트가 유도 응답을 보냅니다.

JSON-RPC-32600(잘못된 요청)

이 세션에 대해 일치하는 유도를 찾을 수 없습니다.

클라이언트는 보류 중인 유도와 일치하지 id 않는를 사용하여 유도 응답을 보냅니다.

JSON-RPC-32600(잘못된 요청)

는 elicitation/create 요청에서 게이트웨이가 보낸 것과 일치해야 id 합니다.

게이트웨이와 MCP 서버 대상 간의 연결 중단

DependencyFailedException을 사용한 JSON-RPC 오류

클라이언트는 원래 도구 호출 요청을 다시 시도해야 합니다.

클라이언트와 게이트웨이 간의 연결 중단

해당 사항 없음

보류 중인 유도가 정리됩니다. 클라이언트는 도구 호출을 다시 시도해야 합니다.

MCP 서버가 유도를 전송하지만 게이트웨이가 지원을 선언하지 않음

JSON-RPC-32601(메서드를 찾을 수 없음)

MCP 서버 대상으로 반환됩니다. 문제 해결을 참조하세요.

게이트웨이 작성 유도에는 클라이언트가 선언하지 않은 기능(버전 2026-07-28 이상)이 필요합니다.

JSON-RPC-32021(필수 클라이언트 기능 누락), HTTP 400

버전 2026-07-28 이상에서는 게이트웨이가 대신이 코드를 반환합니다-32601. 이는 클라이언트가 요청에 필요한 기능을 선언하지 않은 경우에 발생합니다_meta.

문제 해결

오류: "오류 호출 도구 'sample_tool': 메서드를 찾을 수 없음: 유도/생성"

이 오류는 MCP 서버 대상이 유도 요청을 보내지만 게이트웨이의 클라이언트가 유도 기능을 선언하지 않은 경우에 발생합니다. 버전 2025-11-25 이하의 경우 클라이언트는 중에이 기능을 선언합니다initialize. 버전 2026-07-28 이상의 경우 클라이언트는 _meta 필드의 각 요청에 대해 이를 선언합니다. 게이트웨이는 대상에 -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()
  • 게이트웨이 클라이언트 개발자인 경우: 버전 2025-11-25 이하의 경우 클라이언트가에서 유도 기능을 선언하는지 확인합니다initialize.

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

오류: "필수 클라이언트 기능 누락"(-32021)

버전 2026-07-28 이상에서 게이트웨이는 게이트웨이 작성 유도에 선언되지 않은 기능이 필요한 경우 -32021 오류(HTTP 400)를 반환합니다. 이러한 버전은 상태 비저장이고 initialize 핸드셰이크가 없으므로 클라이언트는 각 요청에서 기능을 선언합니다. 이 오류를 해결하려면 유도를 트리거할 수 있는 모든 요청의 요청 _meta 필드(io.modelcontextprotocol/clientCapabilities)에 유도 기능을 포함합니다.

코드 샘플

양식 모드 예제

양식 모드에서 서버는 클라이언트가 작성할 구조화된 스키마를 전송합니다. 요청은 응답을 기다리는 동안 열린 상태로 유지됩니다.

예
Python requests package (2025-11-25 and earlier)

이러한 버전에서 클라이언트는 중 유도 기능을 선언initialize하며, 유도는 열린 SSE 스트림에 elicitation/create 요청으로 도착합니다. MCP-Protocol-Version 헤더를 게이트웨이가 지원하는 버전으로 설정합니다.

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 headers["MCP-Protocol-Version"] = "2025-06-18" # 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
Python requests package (2026-07-28)

버전에서 2026-07-28유도는 SSE 스트림에서 서버 시작 요청 대신 다중 왕복 요청 패턴을 사용합니다. 클라이언트는 각 요청에 대해 _meta의 유도 기능을 선언합니다. 도구에 입력이 필요한 경우 응답은 inputRequests 및 불투명가 포함된 input_required 결과입니다requestState. 클라이언트는 입력을 수집하고 새 id, inputResponses및 수정되지 않은를 사용하여 원래 요청을 재시도합니다requestState. 세션과 initialize 핸드셰이크는 사용되지 않습니다. 게이트웨이의 에는가 포함되어야 supportedVersions 합니다2026-07-28.

import requests gateway_url = "https://mygateway-abcdefghij.gateway.bedrock-agentcore.us-west-2.amazonaws.com/mcp" META = { "io.modelcontextprotocol/protocolVersion": "2026-07-28", "io.modelcontextprotocol/clientInfo": {"name": "my-agent", "version": "1.0.0"}, "io.modelcontextprotocol/clientCapabilities": {"elicitation": {"form": {}, "url": {}}} } headers = { "Content-Type": "application/json", "Accept": "application/json, text/event-stream", "Authorization": "Bearer YOUR_ACCESS_TOKEN", "MCP-Protocol-Version": "2026-07-28", "Mcp-Method": "tools/call", "Mcp-Name": "use_aws" } arguments = {"command": "aws s3 rm s3://my-bucket/important-file"} # Step 1: Call the tool, declaring the elicitation capability in _meta response = requests.post(gateway_url, headers=headers, json={ "jsonrpc": "2.0", "id": "tool-call-1", "method": "tools/call", "params": {"name": "use_aws", "arguments": arguments, "_meta": META} }).json() result = response["result"] if result.get("resultType") == "input_required": # Step 2: Fulfill each input request (form elicitation) input_responses = {} for key, input_request in result.get("inputRequests", {}).items(): print(f"Form elicitation received: {input_request['params']['message']}") input_responses[key] = {"action": "accept", "content": {"confirm": True}} # Step 3: Retry the tool call with a new id, the input responses, # and the requestState echoed back unmodified retry_params = {"name": "use_aws", "arguments": arguments, "_meta": META, "inputResponses": input_responses} if "requestState" in result: retry_params["requestState"] = result["requestState"] response = requests.post(gateway_url, headers=headers, json={ "jsonrpc": "2.0", "id": "tool-call-2", "method": "tools/call", "params": retry_params }).json() result = response["result"] print(f"Tool result: {result}")
MCP Client
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
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
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 모드 예제

URL 모드에서 서버는 사용자가 작업을 완료하기 위해 방문해야 하는 URL(일반적으로 OAuth 인증)을 보냅니다. 사용자가 URL에서 작업을 완료할 때까지 기다리는 동안 요청은 열린 상태로 유지됩니다.

예
Python requests package (2025-11-25 and earlier)

이러한 버전에서는 URL 유도가 MCP 세션 내에서 열린 SSE 스트림에 elicitation/create 요청으로 도착합니다. MCP-Protocol-Version 헤더를 게이트웨이가 지원하는 버전으로 설정합니다.

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-Protocol-Version": "2025-11-25", "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
Python requests package (2026-07-28)

버전 에서는 SSE 스트림 대신 다중 왕복 요청 패턴을 통해 2026-07-28URL 유도가 input_required 결과로 도착합니다. 사용자는 URL에서 작업을 완료한 다음 클라이언트는 새 , inputResponses및 수정되지 않은 id로 원래 요청을 재시도합니다requestState. 세션은 사용되지 않습니다. 게이트웨이의 에는가 포함되어야 supportedVersions 합니다2026-07-28.

import requests import webbrowser gateway_url = "https://mygateway-abcdefghij.gateway.bedrock-agentcore.us-west-2.amazonaws.com/mcp" META = { "io.modelcontextprotocol/protocolVersion": "2026-07-28", "io.modelcontextprotocol/clientInfo": {"name": "my-agent", "version": "1.0.0"}, "io.modelcontextprotocol/clientCapabilities": {"elicitation": {"form": {}, "url": {}}} } headers = { "Content-Type": "application/json", "Accept": "application/json, text/event-stream", "Authorization": "Bearer YOUR_ACCESS_TOKEN", "MCP-Protocol-Version": "2026-07-28", "Mcp-Method": "tools/call", "Mcp-Name": "access_github_repo" } arguments = {"repo": "my-org/my-repo"} # Step 1: Call the tool, declaring the elicitation capability in _meta response = requests.post(gateway_url, headers=headers, json={ "jsonrpc": "2.0", "id": "tool-call-1", "method": "tools/call", "params": {"name": "access_github_repo", "arguments": arguments, "_meta": META} }).json() result = response["result"] if result.get("resultType") == "input_required": # Step 2: Open the browser for the user to complete each URL elicitation input_responses = {} for key, input_request in result.get("inputRequests", {}).items(): params = input_request["params"] print(f"URL elicitation: {params['message']}") webbrowser.open(params["url"]) input("Press Enter after completing authentication...") input_responses[key] = {"action": "accept"} # Step 3: Retry the tool call with a new id, the input responses, # and the requestState echoed back unmodified retry_params = {"name": "access_github_repo", "arguments": arguments, "_meta": META, "inputResponses": input_responses} if "requestState" in result: retry_params["requestState"] = result["requestState"] response = requests.post(gateway_url, headers=headers, json={ "jsonrpc": "2.0", "id": "tool-call-2", "method": "tools/call", "params": retry_params }).json() result = response["result"] print(f"Tool result: {result}")
MCP Client
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
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
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"}]} )