MCP 2026-07-28 removed sessions — what does a consent decision attach to now?
answer
- There is no session left to attach to
- The grant belongs to the host, not the wire
- Keyed to user plus server identity
- A live process proves nothing
- Reconnection is transport, not policy
basics
~20 sTo host-side state keyed to the user and the server's identity, checked as each request is assembled. Revision 2026-07-28 removed the initialize handshake and protocol sessions, so there is no connection or session object a grant could hang on.
solid answer
~50 sConsent now lives entirely in the **host's own state**, keyed to the user and the identity of the server being called, and it is evaluated as the host constructs each request. Before revision 2026-07-28 many implementations effectively bound approval to the `initialize` handshake or to an `Mcp-Session-Id` — "the user approved this session" — and that framing is gone: the handshake, `notifications/initialized`, protocol sessions and the session header were all removed, every request is self-contained, servers MUST NOT rely on prior requests over the same connection, and an open stdio process is explicitly **not** a conversation or a session. Nothing on the wire can carry a grant either: `clientInfo` and `serverInfo` are self-reported and untrusted, and any handle a server minted is server state, not evidence a human agreed to anything. Practically, a long-lived connection no longer implies a long-lived approval — the two were never the same thing, and 2026-07-28 removes the object that let people confuse them.
go deeper
Know that 2026-07-28 removed the initialize handshake and sessions, so there is no session for an approval to belong to; the host remembers the decision itself.
Explain that every request is self-contained and servers must not rely on prior requests, and state what a host-side grant is keyed on — the user and the configured server identity, not a connection.
Show why nothing on the wire can substitute: connections, server-minted handles, opaque requestState and access tokens each prove something else. Keep reconnection out of the consent path.
Own the re-prompt policy — when a grant should be re-confirmed because the surface or the data class changed — and defend it as host policy rather than pretending the specification mandates it.
## The framing that broke In the handshake era — revisions up to and including 2025-11-25 — an MCP connection opened with `initialize`, the client answered with `notifications/initialized`, and over Streamable HTTP the server could mint an `Mcp-Session-Id` that subsequent requests carried. That made a tempting mental model available: the connection is a relationship, the user blesses the relationship once at the start, and everything afterwards inherits the blessing. Plenty of hosts were built exactly that way, and plenty of interview answers still describe it. Revision **2026-07-28** removed the whole substrate. The `initialize` handshake and `notifications/initialized` are gone, replaced by per-request metadata (`io.modelcontextprotocol/protocolVersion` and `io.modelcontextprotocol/clientCapabilities` on every request) plus `server/discover`. Protocol-level sessions and the `Mcp-Session-Id` header are gone, along with `DELETE` termination and expired-session errors — there is no session to expire. The spec's own words: MCP is a stateless protocol, every request is self-contained, servers MUST NOT rely on prior requests over the same connection, and "an open connection, such as a STDIO process, is not a conversation or a session". ## Where consent actually lived all along The honest reading is that consent was never a protocol object even in the handshake era. There has never been a `consented: true` field, and there could not usefully be one, because the client is the party that would set it and nothing verifies it. What the handshake provided was a convenient *hook* for host bookkeeping. Removing it forces the question that was always the real one: what is the grant about? A workable answer keys the grant on facts the host controls: - **Which user**, in a multi-user or multi-profile host. - **Which server identity** — and identity here means the host's own record of what it configured (a command line and binary for a locally launched stdio server, an origin plus the resource identity used for authorization for a remote one). Explicitly *not* `serverInfo.name`, which is self-reported and untrusted; the spec even notes it is unreliable for disambiguating servers. - **Which surface** — a specific tool, a class of resources, or a category of data the host is willing to place in arguments. - **Which scope of effect**, for hosts that distinguish read-only from mutating operations. The host then evaluates that record every time it assembles a request. That is not a workaround for statelessness; it is the same design a careful host needed anyway, because approval that expires with a socket is approval nobody can reason about. ## Things that are not consent records Statelessness invites a substitution error, so it is worth naming what cannot stand in for host state: - **A live connection.** An open stdio subprocess proves a process is running, nothing more. - **A server-minted handle.** Now that cross-call state is carried as explicit identifiers passed as ordinary tool arguments, it is tempting to read possession of one as continuity of approval. It is not: it is server-side bookkeeping, and possession alone must never be treated as authentication. - **An opaque `requestState`** echoed back on a multi-round-trip retry. It is server state the client copies verbatim without inspecting; it says nothing about the user. - **A valid access token.** For remote servers this is genuine and enforceable — audience-bound, PKCE-protected, no passthrough — but it establishes which principal is calling, not that a human approved a particular action. Authorization and consent are different questions with different lifetimes. ## What this changes operationally For a remote server behind a load balancer, statelessness means any node can serve any request, which is a scaling win precisely because no node holds a session. Consent policy is unaffected by that — it never lived on a node. For stdio, the client re-sends `subscriptions/listen` after a reconnect and a broken response stream means re-issuing the request with a **new** JSON-RPC id, since resumability was removed; again, none of that should re-prompt the user, because reconnection is a transport event and consent is a policy fact. The interesting host-design question that remains is re-prompting: when the *surface* a grant was given for changes. The spec supplies one relevant guarantee — a server's tool, prompt and resource set MUST NOT vary per connection, though it MAY vary with the authorization presented — so a set that changes under the same authorization is a real change, not connection noise, and a defensible policy treats it as a reason to re-confirm. That is host policy, not a protocol MUST. ## The interview signal An answer that says "the user approves the session at connect time" identifies someone whose knowledge stops at 2025-11-25. The strong answer names the removal, states that consent is host-side state keyed to user and server identity, and points out that a connection was never a sound place to hang it in the first place.
- Should a host re-prompt the user when a stdio server's process restarts?No. A restart is a transport event; the grant is host state keyed to the user and the configured server identity, and it survives the process. The client re-sends `subscriptions/listen` after reconnecting because notification streams do not survive, but consent is not a stream. Re-prompting on every reconnect trains users to click through prompts, which is worse than not asking.
- Does an audience-bound OAuth token for a remote server double as a consent record?No. It is enforceable proof of which principal is calling and what scopes it holds, which is exactly what authorization should be. Consent is the separate fact that a human understood and agreed to a specific action or exposure. A token can be valid for hours across many actions the user never contemplated, so the host still evaluates its own grant per request.
- What would you re-prompt on, if not on connection?On change of surface or of scope. A defensible policy re-confirms when the server's tool, prompt or resource set changes under the same authorization — the spec guarantees that set MUST NOT vary per connection, so a change is real — when the class of data the host is about to place in arguments exceeds what was approved, or when the operation escalates from read-only to mutating. None of that is a spec MUST; it is host policy.
saying these in an interview costs you the question
- Says the user approves the session during initialize
- Treats an open stdio process as a standing approval
- Reads possession of a state handle as continuing consent
- Keys the grant on the server's self-reported serverInfo.name
- Re-prompts the user on every reconnect or load-balancer hop