Zenaique

What does a stateful MCP session enable and what is the key scaling tradeoff?

Short answer·Hard·4.0 · 0·~3 min·Asked atCursorElasticVernacular Ai·Relevant atAnthropic
Attempt it

Explain what a stateful MCP session enables that a stateless per call model cannot. Describe at least one concrete multi-step scenario and the scaling tradeoff this model introduces.

Free · 2 AI evals / day
TL;DR

A stateful MCP session remembers context across calls (enabling transactions and server-pushed notifications) but the cost is sticky routing that breaks easy horizontal scaling.

Memory aid
Sign in to see the mnemonic that makes this stick.
Easy to grasp

Think of a stateless call like a fast-food counter where a new cashier serves you each time. You must repeat your whole order every visit, and nobody can start cooking now to finish later. A stateful MCP session is a sit-down restaurant with one waiter who remembers your table all night. They open a tab, take several courses, and close it at the end. That memory is powerful: the waiter can also walk over and tell you news without being asked. The catch is you are tied to that one waiter. If they go on break, nobody else knows your tab. The restaurant cannot just throw any free waiter at your table the way the fast-food counter could.

Concept explanation~2 min read

Everything you need to truly understand this topic: intuition, mechanics, step by step explanation, code, formulas, and worked example. Click to expand.

This is a hard senior question because it rewards balance. Plenty of candidates can recite that MCP supports stateful sessions and that this enables transactions. Far fewer connect that benefit to its production cost, which is exactly the dimension a staff interviewer is probing. The question explicitly asks for both a concrete multi-step scenario and the scaling tradeoff, so an answer that names only one half is incomplete by construction.

The core idea: a stateful session lets an MCP server keep memory across many calls within one connection. The client and server negotiate capabilities once during the lifecycle handshake, the server assigns a session id, and every later request reuses it. That memory is the foundation for multi-step operations and for server-initiated traffic. Without it, MCP would collapse to a glorified per-call function dispatcher with no way to group calls or push events.

The flip side is operability. State that lives in one instance's memory pins the client to that instance, which forces sticky routing and complicates horizontal scaling, deploys, and failure recovery. This deep dive walks both halves, shows the lifecycle that creates a session, then shows where the current Streamable HTTP transport lets you opt back into stateless operation and why that choice is per-server, not global.

What a stateful session actually remembers

A stateful MCP session begins with the lifecycle handshake. The client sends initialize, the two sides negotiate protocol version and capabilities, the client confirms with initialized, and the server may assign a session id the client echoes on every subsequent request. From that point the server can attach in-memory state to the session and trust that capabilities were agreed once, not renegotiated per call.

The contrast with a stateless per-call model is sharp. In a stateless design each request is fully self-contained: the server holds nothing between calls, so it cannot know that two requests belong to the same logical workflow. Capability negotiation, if it happens at all, repeats per request, and the server cannot assume the client supports any optional feature without re-checking. Each call is an island.

With a session, the server gets a stable identity to hang state on. That is the enabling primitive. Everything else in this answer, transactions, notifications, subscriptions, sampling, depends on the server being able to say 'this request belongs to the same session as that earlier one.' Negotiating once also amortizes the handshake cost: a long-lived stdio session to a local server pays it at startup and never again, which is why editor integrations favor it.

The benefit: multi-step operations
The benefit: server-initiated communication
The cost: sticky routing and horizontal scale
Staying stateless with Streamable HTTP
Sign in to unlock the full deep dive.

Situations where this technique stops working.

Sign in to see when this approach fails.

2–4 min · Everything important, quickly.

Sign in to see the quick scan of the deep dive.
typescript
// Stateful session: the server holds a DB transaction across calls.
const sessions = new Map<string, { tx: Transaction; lastSeen: number }>();

server.setRequestHandler("tools/call", async (req, sessionId) => {
  const { name, arguments: args } = req.params;

  if (name === "begin_transaction") {
    const tx = await db.beginTransaction();
    sessions.set(sessionId, { tx, lastSeen: Date.now() });
    return ok("transaction opened");
  }

  const session = sessions.get(sessionId);
  if (!session) throw new Error("no active session"); // sticky routing failed
  session.lastSeen = Date.now();

  if (name === "execute_query") return ok(await session.tx.query(args.sql));
  if (name === "commit") {
    await session.tx.commit();
    sessions.delete(sessionId); // cleanup on graceful close
    return ok("committed");
  }
});

// Idle sweeper prevents leaks from ungraceful disconnects.
setInterval(() => {
  const cutoff = Date.now() - 30 * 60 * 1000;
  for (const [id, s] of sessions) {
    if (s.lastSeen < cutoff) { s.tx.rollback(); sessions.delete(id); }
  }
}, 60 * 1000);
ConcernStateful sessionStateless per-call
Multi-step transactionsYes, handle persists across callsNo, each call is isolated
Server-initiated pushNotifications, subscriptions, samplingNot supported
Capability negotiationOnce at initializePer request, if at all
Load balancingNeeds sticky routingPlain round-robin works
Replica failureLive sessions lostAny replica can serve

Real products, models, and research that use this idea.

  • A Postgres MCP server opens a transaction, runs queries across several tool calls, then commits; the handle lives in session memory the whole time.
  • Claude Code and Cursor keep long-lived stdio sessions to local servers, negotiating capabilities once at startup rather than per request.
Sign in to see more production examples.

What an interviewer would ask next. Try answering before peeking at the approach.

QHow would you externalize MCP session state so any replica can serve a follow-up request?
A

Move the session map to a shared store like Redis; keep handles serializable; accept that live resources like an open transaction handle cannot leave one process, so only some state externalizes cleanly.

3 more follow-ups an interviewer would ask next. Sign in to reveal them.

Red flags & common mistakes

The phrases that signal junior thinking. Click to expand.

Most common mistake

Naming only the benefit and forgetting the cost. Senior answers must connect in-memory session state to sticky routing and the loss of stateless load balancing.

Sign in to see all red flags and common mistakes.

60 second bullets to scan on the way to the call.

  • What a stateful session enables that a per-call model cannot

  • A concrete transaction example with state living across calls

Sign in to unlock the revision sheet.

Primary sources. Browse if you want the original framing.

Similar questions

Same topic, related formats. Practice these next.

4 curated
Next question
What is the Model Context Protocol (MCP) and what problem does it solve?
MCQ·Easy