MCP protocol contract
Understand the requirements for implementing the Model Context Protocol (MCP) in Amazon Bedrock AgentCore Runtime so that agents can call tools and agent servers. These requirements apply to MCP servers on both compute types, microVMs and Instances.
For example code, see Deploy MCP servers in AgentCore Runtime.
Topics
Protocol implementation requirements
Your MCP server must implement these specific protocol requirements:
-
Transport : Use the Streamable HTTP transport. For version
2025-11-25and earlier, use stateless mode (stateless_http=True) by default for compatibility with Amazon's session management and load balancing. Version2026-07-28and later is stateless by the MCP specification. -
Session Management : The platform forwards session headers, including
Mcp-Session-IdandX-Amzn-Bedrock-AgentCore-Runtime-Session-Id, to your MCP server. Your MCP server must accept these headers and not reject requests that include them.
Tip
AgentCore Runtime also supports stateful MCP servers ( stateless_http=False ). With a stateful MCP server, you can use capabilities such as elicitation (multi-turn user interactions) and sampling (LLM-generated content). For MCP protocol version 2025-11-25 and earlier, stateful mode is required for elicitation and sampling, because the server delivers these requests over an open session. For version 2026-07-28 and later, elicitation and sampling use the multi round-trip requests (MRTR) pattern, which does not require stateful mode. For more information about MRTR, see Multi round-trip requests
Stateful mode carries state within an MCP session across multiple requests. A stateless MCP server keeps state in a backing store that your application manages, such as a database. It uses explicit state handles to reference that state. The server returns a state identifier in a tool result, and the client passes it back on later tool calls to key into the store. For more information about explicit state handles, see explicit state handles
MCP session management and microVM stickiness
AgentCore Runtime routes each request to a microVM based on a session ID. It takes the session ID from a client request header, or generates one if the request doesn’t include it. Requests with the same session ID go to the same microVM while the session is active. On Instances, requests with the same session ID go to the same instance session. For more information, see Use isolated sessions for agents and, for Instances, Session. Sending the same session ID on related requests helps you:
-
Avoid the latency of starting a new session for each request.
-
Reduce cost, because related requests share one session instead of each starting a new one.
-
Stay within the quota for active sessions, because each new session counts toward it. For more information, see Resource allocation limits.
-
Keep state that your server holds in memory across requests, such as the status of a long-running task that the client polls.
The header that AgentCore Runtime uses for the session ID depends on the MCP protocol version, because version 2026-07-28 removes the Mcp-Session-Id header. For more information, see Key changes
Version 2026-07-28 and later
AgentCore Runtime uses X-Amzn-Bedrock-AgentCore-Runtime-Session-Id as the session ID. For backward compatibility, it still accepts Mcp-Session-Id. If the client sends both headers, AgentCore Runtime uses Mcp-Session-Id. Each response header returns the value that the client sent in the same request header, even if the two values differ. If the client sends only one of the headers, both response headers use its value. If the client sends neither, both use a session ID that the service generates.
Tip
To keep requests on the same microVM, send the same X-Amzn-Bedrock-AgentCore-Runtime-Session-Id value on each request.
Version 2025-11-25 and earlier
AgentCore Runtime uses Mcp-Session-Id as the session ID (for the MCP specification, see MCP Streamable HTTP TransportMcp-Session-Id returned in the response and include it in all subsequent requests. The service doesn’t use X-Amzn-Bedrock-AgentCore-Runtime-Session-Id to route requests in this version.
Stateless MCP ( stateless_http=True ):
-
The client can send its own
Mcp-Session-Id, or omit it on the first request so that AgentCore Runtime returns one in the response. -
The client must include the same
Mcp-Session-Idin all subsequent requests for microVM affinity.
Stateful MCP ( stateless_http=False ):
-
Client sends the initialize request without an
Mcp-Session-Idheader. -
Platform returns
Mcp-Session-Idin the response. -
Client must include this
Mcp-Session-Idin all subsequent requests for both session state and microVM affinity.
For more information about stateful MCP session management, see the MCP session management specification
Server requirements
Whether you use direct code deployment or a container image, your MCP server must meet these requirements:
-
Host:
0.0.0.0 -
Serving port:
8000by default, or the serving port inprotocolConfiguration.port -
Architecture: ARM64. If you deploy a container image, build it for ARM64. If you use direct code deployment, build any native binaries in your package for ARM64.
You can change the serving port and the InvokeAgentRuntime POST path with protocolConfiguration. See Path requirements for the default paths. For configuration examples, see Configure your agent’s serving port and invocation path.
Path requirements
/mcp - POST
Purpose
Receives MCP RPC messages and processes them through your agent’s tool capabilities, complete pass-through of InvokeAgentRuntime API payload with standard MCP RPC messages
Response format
JSON-RPC based request/response format, supporting both application/json and text/event-stream as response content-types
Use cases
The /mcp endpoint serves several key purposes:
-
Tool invocation and management
-
Agent capability discovery
-
Resource access and manipulation
-
Multi-step agent workflows
/ping - GET (Recommended)
Purpose
Reports whether your MCP server is healthy, independent of the MCP protocol version that your server implements. AgentCore Runtime doesn’t require /ping, but we recommend that every MCP server implement it. With GET /ping, your server can also report HealthyBusy while it runs background work, so that AgentCore Runtime doesn’t end the session for being idle. For more information, see Runtime session lifecycle management.
Response format
To be detected, /ping must:
-
Be served at the root path (
/ping) on your server’s serving port (8000by default), regardless of your MCP path. -
Return a
2xxstatus with a JSON body in the format described in /ping - GET in the HTTP protocol contract. Other responses, such as an HTML page or a catch-all200with a different body, are not treated as/pingsupport.
Health probes
AgentCore Runtime probes your server to decide when it is ready to serve traffic and whether it is still healthy. To implement the recommended health endpoint, see /ping - GET (Recommended).
Readiness check when a session starts
When a new session starts, AgentCore Runtime sends GET /ping to your server’s serving port. Any response other than 502 or 429 shows that your server accepted the connection. This includes 404 and 405. AgentCore Runtime then treats your server as ready. If your server doesn’t implement /ping, a 404 Not Found for GET /ping in your access log is expected and harmless.
Health checks during the session
After your server is serving, AgentCore Runtime continues to check health. It first checks whether your server implements GET /ping. If it does, AgentCore Runtime uses GET /ping for the rest of the session. Otherwise, it sends an MCP ping request: a POST to your MCP path with a JSON-RPC ping method and the Accept: application/json, text/event-stream header. This fallback supports servers on MCP protocol version 2025-11-25 and earlier, in both stateful and stateless mode, and servers on version 2026-07-28.
A server on version 2026-07-28 might reject the ping request, because that version removed the ping method and the initialize handshake. If your server returns HTTP 400 to ping, AgentCore Runtime sends an initialize request. If that request also returns 400, AgentCore Runtime treats your server as healthy unless it stops responding or returns server errors. It also writes a one-time message to your agent’s logs that recommends implementing /ping. Other error responses to ping or initialize can fail the health check.
Note
Your MCP SDK, its version, and its configuration determine whether your server answers ping. Some SDKs that support both the current and earlier versions still answer ping from clients that don’t specify a protocol version. SDKs that support only 2026-07-28 or later reject it. Without GET /ping, AgentCore Runtime can detect only that such a server has stopped responding or is returning errors other than the ping rejection, such as server errors. To give AgentCore Runtime a reliable health signal, implement GET /ping.
Error handling
AgentCore Runtime returns errors as JSON-RPC 2.0 error responses. Error codes and HTTP status codes depend on the MCP-Protocol-Version request header:
-
Version
2026-07-28and later : The HTTP status code reflects the error, to align with the MCP 2026-07-28 specification. -
Version
2025-11-25and earlier, or header missing or invalid : Most errors return HTTP 200. Only authentication, authorization, and Accept header errors use other status codes.
The following table lists the error for each runtime exception.
| Runtime Exception | HTTP Error Code (2026-07-28 and later) | JSON-RPC Error Code (2026-07-28 and later) | HTTP Error Code (2025-11-25 and earlier) | JSON-RPC Error Code (2025-11-25 and earlier) | Error Message |
|---|---|---|---|---|---|
|
UnauthorizedException |
401 |
-32001 |
401 |
-32001 |
Authentication error - Invalid credentials |
|
AccessDeniedException |
403 |
-20001 |
403 |
-32002 |
Authorization error - Insufficient permissions |
|
ThrottlingException |
429 |
-32003 |
200 |
-32003 |
Rate limit exceeded - Too many requests |
|
ServiceQuotaExceededException |
429 |
-32003 |
200 |
-32003 |
Rate limit exceeded - Too many requests |
|
ResourceNotFoundException |
404 |
-32602 |
200 |
-32004 |
Resource not found - Requested resource does not exist |
|
ConflictException |
409 |
-32005 |
200 |
-32005 |
Resource conflict - Resource already exists |
|
RetryableConflictException |
409 |
-32005 |
200 |
-32005 |
Session operation in progress, please retry |
|
ValidationException |
400 |
-32006 |
200 |
-32006 |
Validation error - Invalid request data |
|
RuntimeClientError |
424 |
-32010 |
200 |
-32010 |
Tool execution error - Please check your CloudWatch logs for more information |
|
McpRequestUnacceptableException |
406 |
-32011 |
406 |
-32011 |
Accept Header Error - MCP protocol requires Accept header: application/json, text/event-stream |
|
Any other exception |
500 |
-32603 |
200 |
-32603 |
Internal error - Server error |
Note
-
For version
2026-07-28and later,AccessDeniedExceptionreturns JSON-RPC error code-20001instead of-32002. The MCP 2026-07-28 specification doesn’t allow servers to send-32002, and it recommends that new error codes use values outside the JSON-RPC reserved range (-32768to-32000). The HTTP status code (403) stays the same. -
For version
2026-07-28and later,ResourceNotFoundExceptionreturns JSON-RPC error code-32602(Invalid params) instead of-32004. This matches the code that the MCP 2026-07-28 specification uses for a resource that doesn’t exist.
Example error response:
{ "jsonrpc": "2.0", "id": "req-001", "error": { "code": -32005, "message": "Session operation in progress, please retry" } }
Responses from your MCP server
When your MCP server returns one of the following status codes, the service returns that status code and the response body to the client. For any other status code, the service returns RuntimeClientError.
-
Version
2026-07-28and later : 200, 202, 400, 401, 403, and 404. Other status codes return HTTP 424. -
Version
2025-11-25and earlier : 200 and 202. Other status codes return HTTP 200.
Retrying RetryableConflictException
ConflictException and RetryableConflictException share error code -32005 and differ by message. The service returns RetryableConflictException when an operation targets a session that is being provisioned or torn down. Retry with short exponential backoff — MCP clients do not auto-retry it. For version 2025-11-25 and earlier, the response is HTTP 200, so inspect the response body to detect it.
OAuth authentication responses
OAuth-configured agents follow RFC 6749 (OAuth 2.0)
401 Unauthorized
Returned when the Authorization header is missing or empty.
Response includes WWW-Authenticate header:
WWW-Authenticate: Bearer resource_metadata="https://bedrock-agentcore.{region}.amazonaws.com/runtimes/{ESCAPED_ARN}/invocations/.well-known/oauth-protected-resource?qualifier={QUALIFIER}"
Note
SigV4-configured agents return HTTP 403 and do not include WWW-Authenticate headers.