The migration brief
Imagine an internal Ops Copilot whose MCP server queries deployment status and sometimes needs an engineer to choose a target AWS account before it can continue. Its current ECS service uses Mcp-Session-Id, sticky load-balancer routing, and a shared session store so a follow-up reaches the instance that remembers the conversation. The migration question is not “how do we make the application forget everything?” It is: “which information must be explicit and verified on every portable request?”
By the end, you will be able to redraw this server for the stateless MCP core, safely continue a multi-step call, and retire infrastructure whose only job was to preserve a protocol session. We will build the new architecture in layers: remove invisible affinity, make follow-up work resumable, protect explicit state, then delete the old compensating machinery.

Remove the invisible session
In the legacy design, a client started with an initialize handshake and subsequent requests carried Mcp-Session-Id. The deployment then had to keep the session coherent: route a client consistently to one instance, or externalize enough state that any instance could reconstruct it. That is why a seemingly simple tool server often acquired sticky routing, Amazon ElastiCache or DynamoDB session records, and session-aware diagnostics.
The 2026-07-28 specification changes the protocol core to stateless request/response. The handshake and Mcp-Session-Id header are removed. A client’s very first message can be a tool call, and each request carries the protocol version and context it needs. “Stateless” here means no invisible transport relationship is required between messages. In the Ops Copilot spine, the load balancer no longer needs to remember which container received the previous request just to satisfy MCP.
The important subtlety: a request can still name a workspace, a job, or an account. The difference is that the identifier is explicit in the request and each receiving server must validate it; it is not recovered from a hidden session tied to one worker.
affinity?
—
Which dependency is no longer required for MCP protocol continuity?
Let any healthy worker answer
Once requests are self-contained, an Application Load Balancer can send two consecutive MCP requests to different healthy instances without breaking protocol continuity. Horizontal scaling becomes ordinary request scaling rather than session-preserving scaling. The team can remove session affinity rules and, if the session store served only MCP transport state, decommission it.
That also makes AWS Lambda a first-class MCP hosting pattern: its natural shape is request in, response out, and an invocation need not inherit memory from a previous invocation. Lambda is not automatically right for every tool—long-running work, connection behavior, package size, latency requirements, and downstream limits still matter—but no longer conflicts with the MCP core because a server-side protocol session is not required.
For Ops Copilot, the refactored path is client → authenticated endpoint/load balancer → any healthy Lambda invocation or container → tool/API. Keep a database only for durable business data, not as a disguised replacement for the removed Mcp-Session-Id session.

After migration, which change follows from self-contained MCP requests?
Resume work with MRTR
The old mental model says that when the server needs more information, it can pause a call and push a question to the client. The stateless core replaces that with Multi Round-Trip Requests (MRTR). The server returns an input_required result together with an opaque requestState continuation token and the information the client needs to obtain.
For example, Ops Copilot receives “prepare the deployment report.” The tool determines that the target account was not specified. It returns input_required, asking for an account selection, and emits requestState. After the user chooses, the client sends the tool call again with the newly supplied account and echoes requestState. Whichever instance receives that second request verifies the continuation and resumes the work. No sticky route is necessary.
The token is a continuation handle, not a magic memory channel. The call has more round trips, but each round trip is independently routable. This is the key trade: explicit resumability replaces implicit server affinity.
A tool needs an account selection before it can prepare a report. What should its first response do?
Make portable state safe and observable
Stateless MCP does not ban application state. Ops Copilot may pass a workspace ID so the server can read durable workspace data. But any identifier or requestState that transits the client may be visible to, copied by, or altered through an LLM-facing workflow. A dangerous design treats an opaque-looking string as a bearer capability: “if you present it, you own the workflow.” Prompt injection can then turn a copied token into access to someone else’s continuation.
Treat the echoed requestState as untrusted input on every request. Bind it to the authenticated caller and relevant context, verify authorization and expiry, and protect integrity cryptographically—for example with HMAC or authenticated encryption (AEAD). Opaque means the client need not interpret it; it does not mean the server can skip verification. Never put secrets or authorization grants in a token merely because it is opaque.
Two adjacent protocol capabilities also become deployment tools. ttlMs tells consumers how long a response remains fresh; cacheScope states whether only the client or shared intermediaries may cache it. Use a shared cache only when the result is safe to share across the intended security boundary. For observability, forward W3C Trace Context such as traceparent and tracestate in request _meta so traces can link the agent/client, gateway, MCP handler, and downstream AWS service in OpenTelemetry-compatible tooling. This replaces ad hoc session-based correlation with portable request correlation.
requestState: opaque-value
workspaceId: ops-prod
What is the best correction to “requestState is opaque, so any request that echoes it can resume the workflow”?
Retire the session-era machinery
An SDK upgrade alone does not necessarily make a server stateless. The team must explicitly use the 2026-07-28 revision and audit code for initialize, Mcp-Session-Id, HTTP+SSE, and other legacy assumptions. Legacy features including Roots, Sampling, Logging, and HTTP+SSE have a twelve-month deprecation floor ending in July 2027; plan the migration before that deadline rather than treating it as optional cleanup.
For Ops Copilot, inventory each session artifact and ask what it actually protects. Preserve durable business records where required; replace protocol-continuation state with verified requestState design; update clients and test MRTR over non-sticky routing; propagate W3C trace context; validate caching boundaries; then remove session affinity, unused ElastiCache/DynamoDB session capacity, and warm instances retained only for pinned sessions. Measure errors, cost, concurrency, and traces during rollout. The finished architecture is well-architected not simply because it says “stateless,” but because every request can be routed, secured, observed, and resumed by design.
Keep / replace / retire
Which statement correctly describes the first client message under the MCP 2026-07-28 stateless core?
Which deployment change best matches a stateless MCP server with bursty traffic?
In an MRTR flow, what does the client do after receiving input_required and requestState?
Which design safely uses a requestState token?
Which migration sequence is most well-architected?
Your portable-request review
✓ Stateless transport ✓ Portable routing ✓ MRTR continuation ✓ Token verification ✓ Deliberate teardown
Portable Requests
This certifies that
has demonstrated a well-architected migration from pinned sessions to portable, verified MCP requests.