Skip to content

Connect: Amazon Bedrock AgentCore Gateway

Recipe · through our public MCP server · their docs checked 2026-10-30

AgentCore Gateway puts our server behind one MCP endpoint for your agents. The gateway authenticates callers on its side (inbound auth) and calls us with its own credential (outbound auth). It speaks MCP 2026-07-28, 2025-11-25, 2025-06-18 and 2025-03-26.

flowchart LR
  AG["Agent"] -->|"inbound auth"| GW["AgentCore Gateway"]
  GW -->|"API key: Authorization: Bearer …"| S["public_app /mcp"]
  ID[("AgentCore Identity<br/>API key provider")] -.-> GW

Our side

def public_app(tools: Registry, host: str, agent_token: str, reviewer_token: str) -> Any:
    """REST at /, MCP at /mcp, one bearer check for both: for a host on the internet."""
    from mcp.server.transport_security import TransportSecuritySettings

    from agent_adapter.server import create_app

    tokens = {
        agent_token: Principal("hosted-agent"),  # the token the remote framework sends
        reviewer_token: Principal("reviewer@example.com", scopes=frozenset({APPROVER_SCOPE})),
    }
    security = TransportSecuritySettings(allowed_hosts=[host], allowed_origins=[f"https://{host}"])
    return create_app(
        tools,
        authenticate=bearer_auth(tokens),
        host="0.0.0.0",  # a public bind: the public-host checks apply
        allowed_hosts=[host],  # REST: any other Host header gets 421
        mcp_options={"transport_security": security},  # MCP: the same rule
    )


hosted = registry.subset(tags=["hosted"])  # no confirm tools: hosted runtimes cannot resume them

Serve public_app(hosted, host, agent_token, reviewer_token).

Their side

  1. In AgentCore Identity, create an API key credential provider that holds our agent token (same account and Region as the gateway).
  2. Add an MCP server target (boto3 bedrock-agentcore-control):
control.create_gateway_target(
    gatewayIdentifier=gateway_id,
    name="shop-tools",
    targetConfiguration={
        "mcp": {"mcpServer": {"endpoint": "https://tools.example.com/mcp", "listingMode": "DEFAULT"}}
    },
    credentialProviderConfigurations=[
        {
            "credentialProviderType": "API_KEY",
            "credentialProvider": {
                "apiKeyCredentialProvider": {
                    "providerArn": api_key_provider_arn,
                    "credentialParameterName": "Authorization",
                    "credentialPrefix": "Bearer ",
                    "credentialLocation": "HEADER",
                }
            },
        }
    ],
)
Key Meaning
targetConfiguration.mcp.mcpServer.endpoint our /mcp URL (URL-encoded)
listingMode DEFAULT: the gateway caches our tools/list; DYNAMIC: it asks us each time
credentialProviderType: "API_KEY" outbound auth from an AgentCore Identity API key provider
credentialParameterName, credentialPrefix, credentialLocation how the key is sent: header Authorization, value Bearer <token>
SynchronizeGatewayTargets refresh the cached tool list after you change tools (DEFAULT mode)

OAuth outbound (client credentials, authorization code, token exchange) also works when bearer_auth is given an async verifier for your issuer's tokens.

Their side, OpenAPI target (alternative)

The gateway also imports an OpenAPI document, but refuses oneOf, anyOf and allOf and spec-level security schemes. /openapi.json (3.1) has unions, so give it the dialect="3.0-gateway" file instead (how): 3.0.3, no unions, only the invoke_<tool> operations, our server_url, no security.

control.create_gateway_target(
    gatewayIdentifier=gateway_id,
    name="shop-tools-rest",
    targetConfiguration={"mcp": {"openApiSchema": {"inlinePayload": inline_payload}}},
    credentialProviderConfigurations=[...],  # the same API_KEY entry as step 2
)
Key Meaning
openApiSchema.inlinePayload the document as JSON text (or s3 with a bucket URI)
tool names the gateway uses each operationId: invoke_<tool>
a 202 pending_approval a confirm tool runs only when a reviewer decides over REST, and the agent never sees that result: serve hosted here too

Checklist

Check Why
serve hosted the gateway does not send our resume keys back; a confirm tool would never run
every gateway caller shares the target's one token so one principal: per-user runs need token exchange and a verifier
call SynchronizeGatewayTargets after each tool change DEFAULT mode serves a cached list
keep client_approval off the gateway passes 2026-07-28 requestState through unchecked, and no person sees a form
everything on the public-host checklist

Sources