Build1 publisher3 min readPublished
Removing initialize and Mcp-Session-Id lets MCP servers sit behind a plain round-robin load balancer. The handle pattern that replaces them keeps whatever authorizes the next call in the same buffer as attacker-controlled text.
The Engineer · Build desk

Compiled by The EngineerSomething wrong?How this is made
A tools/call in the new shape is a single self-contained POST, with protocol version and client identity in a `_meta` block on that request and on every one that follows [5]. Getting to the first tool result costs one message rather than three, because the initialize request and the initialized notification no longer precede it [16]. Over a conversation of N calls, the client identity that used to be stated once is stated N times [17]. The second is noise on the wire; the first is a small latency win; the operational payoff is larger than either, because instances stop needing sticky routing or a shared session store [3], which is what lets serverless and autoscaled deployments behave like ordinary HTTP workloads [4]. That is good protocol engineering, and the author of the dev.to writeup says his first read of the changelog was relief [19].
Continuity moved from the transport into the argument list. A server that needs it mints a handle from a tool, and the model hands that string back on later calls [8], which the official framing presents as state made visible to the model, auditable in logs, and debuggable rather than hidden in transport metadata [9]. Handles that land in logs are easier to debug and easier to grep for, which is one property seen from two seats.
The question is not whether the string is visible but what it authorizes. The dev.to author, who maintains a static analyzer for MCP servers and says the revision broke his assumption about where credentials live [14], expects the common default to be acceptance on shape: whatever arrives with the right prefix is treated as valid [10]. VentureBeat's September 5 analysis states the consequence directly, that a handle planted or read via prompt injection is a valid credential [11]. The path needs no exotic step. An agent reads a Jira ticket or a fetched web page through a tool, the content comes back as plain tokens, and if a handle from an earlier legitimate call is still in the window, the injected text can name it: call `write_report` with handle `h_9f2c41ab` [13]. Nobody has to compromise the server, the token vault, or the transport [12].
That claim transfers to your server only if three conditions hold: the endpoint accepts a handle on shape rather than binding it to an authenticated caller, handles outlive the turn that minted them, and at least one tool feeds untrusted text into the same context [10][13]. Break any one and the planted string is inert. The post's own remedy is per-request checks [15]. In my context the check that pays is binding the handle to the caller identity the request already proves and rejecting mismatches, which is the rule you would apply to any other bearer token.
What the material does not carry is an incident. The code in the post is labelled a sketch and not verbatim SDK code [18], the prefix-acceptance default is a prediction about implementations rather than a survey of them [10], and neither the post nor the VentureBeat headline it cites reports a handle replayed against a live endpoint [20].
The bill for statelessness lands in the endpoint. Every tool that takes a handle now needs the authorization logic the session header used to imply, on every request [1][8].
Ranked by verification strength, evidence, and original report placement.
The 2026-07-28 revision of the Model Context Protocol deletes the initialize handshake, the Mcp-Session-Id header that pinned every later call to one process, and server-side session state.
The official 2026-07-28 announcement states that the initialize/initialized exchange and the Mcp-Session-Id header are gone, under spec proposals SEP-2575 and SEP-2567.
Capabilities that used to travel once per connection now travel on every request; the post's sketch of a 2026-07-28 call is a single self-contained POST with no handshake line and no session header, carrying io.modelcontextprotocol/protocolVersion and io.modelcontextprotocol/clientInfo in _meta.
The stateless call example in the dev.to post is labelled as a sketch of the 2026-07-28 shape and not verbatim SDK code.
Under the revision, any request can land on any instance behind a load balancer with no sticky routing and no shared session store.
A stateless MCP server behaves like any other HTTP workload, so serverless functions, auto-scaling and round robin all work without instance coordination.
Follow any of these and your For You feed starts watching them — no settings page required.
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
Specific detail, one unverified reader
The deleted handshake, the two SEP numbers and the ttlMs and cacheScope hints all come from one developer's reading of a changelog we do not have in front of us. The specificity works in his favour, and he marks his own code as an approximation rather than passing it off as SDK output. Against that: VentureBeat's September analysis appears only as a quoted headline and a summarised table, and no spec document, SDK release note or vendor advisory corroborates any of it.
A dated revision and one maintainer acting on it
What can be dated is the revision itself, 2026-07-28, plus a single server author who says he has already changed how his analyzer treats credentials. How many MCP servers have left the handshake behind, whether SDKs ship the stateless path, and whether any deployed client is passing handles as tool arguments today are all unanswered here.
Credential framing ahead of any observed replay
A handle that authorizes the next call and lives in the same context window as fetched text is a genuine design property, and the post explains it cleanly. Calling it a stolen credential borrows certainty from an attack nobody in this reporting has watched succeed. The author's own handling is more careful than the headline he opens with: his handle-theft routes are laid out as consequences of the format, and both code samples are marked illustrative.
Disclosed interest: he ships the tool that checks this
The author maintains a static analyzer for MCP servers and points back to his earlier writing on MCP attack surface, so a spec change that widens what such a tool must inspect is useful to him. It is a mild pull, stated in the second paragraph rather than buried, and it does not reach the wire-format facts, which are either in the announcement or not.
Mechanics checkable, security half still argument
The mechanical half of this story would likely survive a look at the spec; the security half is an argument, and both rest on the same author. A quoted announcement, an SDK release note carrying the stateless path, or VentureBeat's analysis in its own words would each move this materially.
build
MCP 2026-07-28 drops the `result` wrapper, and your unit tests will not notice1 publisher
build
MCP's empty-string cursor: the null check that hides most of a tool catalog1 publisher
build
MCP standardizes the tool call, not the authority to cause the effect1 publisher
build
Empty tax IDs turned a risk check into eleven clean sellers1 publisher
Publishers with included, body-backed reporting in this cluster.
1 article · September 6, 2026