ChanlChanl
Tools & MCP

What the July 28 MCP spec means for your stateful agents

The July 28 MCP spec is the largest protocol revision since launch. Sessions are removed. Stateless request handling replaces the initialization handshake. Here's what breaks and how to fix it before the deadline.

DGDean GroverCo-founderFollow
June 22, 2026
13 min read
Diagram showing the MCP session lifecycle being replaced with stateless request handling, with session state moving to an external Redis store

The MCP spec ships its largest revision on July 28. Sessions go away. The initialization handshake goes away. If your agents maintain conversation state through MCP's session layer, you're building on something that won't exist in six weeks.

This isn't a change that crashes your server overnight. Client libraries will update gradually, and backward compatibility will hold for a while. But the direction is clear: MCP is going stateless, and teams storing conversation context inside the MCP session layer need a migration plan before they get caught flat-footed.

Here's what's actually changing, what breaks, and how to adapt.

What sessions gave you

MCP sessions exist because the protocol originally needed a way to establish shared state between a client and server before tool calls could begin. The session lifecycle works like this: the client connects and sends an initialize request with its capabilities, the server responds with its own capabilities, the session opens, tool calls flow within that session context, and the session closes when the client disconnects.

This model has a familiar problem: it's inherently stateful. The server has to track active sessions, maintain session-specific context, and ensure that tool calls from the same session see consistent state. In a single-server deployment, that's manageable. In a horizontally scaled production environment, it's a coordination problem. Which server holds which session? What happens when the session server goes down? How do you deploy without interrupting active sessions?

The simplest way to understand why this is changing: a stateless API can run behind any load balancer with no sticky sessions, scale to zero in a serverless function, and restart without losing state. Stateful APIs can't do any of those things cleanly.

What the July 28 spec removes

Three things are being removed or rewritten in the 2026-07-28 spec.

Sessions are removed. The initialize/initialized handshake lifecycle is gone. There's no session to open or close. Each request is self-contained.

The initialization handshake is replaced by metadata discovery. Instead of a runtime negotiation of capabilities, servers publish their capabilities through metadata endpoints. Clients read the server's capabilities once, cache them, and use them to decide what to send on each request.

MCP servers become formal OAuth 2.1 resource servers. This was a recommendation in the existing spec. After July 28, it's required for any server accessible over the network. Servers must implement Protected Resource Metadata (RFC 9728) so clients can discover which auth server to use automatically.

Here's what the session-based flow looks like today compared to what replaces it:

initialize (capabilities) initialized (capabilities) tool call (within session context) tool result GET /.well-known/oauth-protected-resource Auth server + scopes (cached by client) tool call + Bearer token (self-contained) tool result July 28 protocol (stateless) Agent client MCP server
Current MCP session lifecycle vs. the July 28 stateless model

What breaks if you're using sessions for state

Not every MCP implementation uses sessions for meaningful state. If you're listing tools, calling them, and returning results with no session-level context, you're largely unaffected. The initialization handshake was mostly invisible to most tool implementations.

The problem comes if you're using any of these patterns.

Session-scoped auth context. Some servers authenticate the session once and then trust all subsequent tool calls within that session. In the stateless model, every tool call carries its own token. You can't authenticate once and rely on the session to remember it.

Session-scoped configuration. If you're setting user preferences or configuration options in the session and using them across tool calls, those need to move somewhere else. The canonical place is the tool call arguments themselves, or a context object that the orchestrator passes explicitly.

Session-scoped cursor state. Pagination that relies on cursors stored in session state breaks. You need to return the cursor to the client and have the client pass it back on the next call.

In-memory state between tool calls. Any state you're storing in server-side memory tied to a session ID needs to move to an external store, keyed to something the client can pass on each request.

anti-pattern-session-state.ts·typescript
// Anti-pattern: relying on session to remember context (breaks July 28)
class MyMcpServer {
  private sessions = new Map<string, { userId: string; prefs: UserPrefs }>();
 
  handleInitialize(sessionId: string, params: InitializeParams) {
    const user = validateToken(params.token);
    // Storing state in the session -- no longer supported
    this.sessions.set(sessionId, { userId: user.id, prefs: user.prefs });
  }
 
  async handleToolCall(sessionId: string, tool: string, args: unknown) {
    const session = this.sessions.get(sessionId); // This won't work
    return executeTool(tool, args, session!.userId, session!.prefs);
  }
}
stateless-pattern.ts·typescript
// Stateless pattern: each call is self-contained (compatible with July 28)
async function handleToolCall(request: McpToolRequest): Promise<McpToolResult> {
  // Validate the token on every call -- no session to trust
  const user = await validateBearerToken(request.headers.authorization);
 
  // Context comes from the token claims or explicit args, never from a session
  return executeTool(request.tool, request.args, user.id);
}

Moving state out of MCP

The right home for conversation state depends on how long it lives and how frequently it changes.

Short-lived state within a conversation (which tool was just called, what the user answered, where you are in a multi-step flow) belongs in your orchestrator's in-memory session object. The orchestrator tracks conversation progress and passes the relevant pieces as context when it calls MCP tools.

Medium-lived state (current session's customer data, the cart contents, the active support ticket) belongs in a fast cache like Redis, keyed to a session ID that the orchestrator maintains.

Long-lived state (customer history, preferences, past interactions) belongs in a proper data store, loaded at session start by the orchestrator and refreshed as needed.

The key insight: MCP is for tool execution, not state management. The session layer just made state storage tempting. The stateless spec pushes that state to where it belongs.

session-store.ts·typescript
import { createClient } from 'redis';
 
const redis = createClient({ url: process.env.REDIS_URL });
 
export class SessionStore {
  async get<T>(sessionId: string, key: string): Promise<T | null> {
    const raw = await redis.get(`session:${sessionId}:${key}`);
    return raw ? (JSON.parse(raw) as T) : null;
  }
 
  async set<T>(sessionId: string, key: string, value: T, ttlSeconds = 3600): Promise<void> {
    await redis.setEx(
      `session:${sessionId}:${key}`,
      ttlSeconds,
      JSON.stringify(value)
    );
  }
}
 
// Orchestrator loads state and passes it explicitly to each tool call
const store = new SessionStore();
const customerData = await store.get(sessionId, 'customer');
 
// The tool call carries its own context -- no MCP session needed
const result = await mcpClient.callTool('get_order_status', {
  orderId: args.orderId,
  customerId: customerData!.id, // Passed explicitly, not inferred from session
});

The auth work you actually have to do

Moving state is architectural refactoring you can do at your own pace. The auth change requires active work before July 28: your MCP server needs to expose a /.well-known/oauth-protected-resource endpoint.

This is how compliant clients discover your auth configuration automatically. Without it, clients following the new spec won't know which auth server to use or what scopes to request.

oauth-metadata-route.ts·typescript
// Add this endpoint to your MCP server before July 28
app.get('/.well-known/oauth-protected-resource', (req, res) => {
  res.json({
    resource: 'https://your-mcp-server.example.com',
    authorization_servers: [
      'https://auth.your-company.com'
    ],
    scopes_supported: [
      'mcp:tools:read',
      'mcp:tools:write',
    ],
    bearer_methods_supported: ['header'],
  });
});

If you're already running OAuth from the existing spec, this is a small addition. If you're not running auth at all, the stateless spec makes it harder to avoid: without a session to trust, every tool call needs some way to identify who's calling.

The MCP auth in production post covers OAuth scopes and per-tenant tool sets in depth. And the MCP feature page covers how Chanl implements Protected Resource Metadata for servers in your stack.

Testing your migration before the spec ships

You have five weeks. Here's what to test.

Stateless tool calls: Remove the initialize/initialized handshake from your test client and call tools directly with a Bearer token. Your server should handle these without any setup phase.

Cross-request state isolation: Run a two-step tool call sequence where the second call depends on information from the first. Verify the orchestrator correctly passes the first call's output to the second, without relying on any server-side session state.

Per-request auth validation: Call the same tool 10 times in sequence. Verify the server validates the token on each call. An expired token on request 7 should fail even if requests 1 through 6 succeeded with a valid token.

Metadata endpoint: Hit /.well-known/oauth-protected-resource and verify it returns the correct auth server URL, scopes list, and resource identifier.

Chanl's scenario testing lets you run multi-step tool call sequences against your real MCP server and assert state boundaries between steps. You can run the same scenarios before and after your migration to catch regressions before they reach production.

What you don't have to change

Not everything breaks. Tool definitions, tool implementations, and result formatting are all unchanged in the July 28 spec. If your tool takes an orderId and returns order status, it still works exactly the same way.

The ListTools response format is unchanged. The CallTool request and response format is unchanged. The spec adds things (metadata endpoints, formal resource server requirements) and removes things (session lifecycle) but doesn't restructure the core tool protocol.

If you're using an MCP client library like the official TypeScript SDK, watch for a spec-aligned update before July 28. The library should handle the client-side changes automatically. The server-side changes, removing session handling and adding the metadata endpoint, are yours to implement.

For context on why the protocol is heading this way, the tool calling fragmentation post explains why MCP is winning and what the governance changes at the Agentic AI Foundation mean for long-term protocol direction.

The July 28 spec is a maturation step, not a rewrite. Sessions were training wheels for a protocol that's now ready to run stateless at scale. The teams that adapt early will have more resilient, more portable MCP servers. The teams that wait will find that compliant client libraries simply stop maintaining sessions for them, with no warning in the logs.

Ship tools that work with the new MCP spec

Chanl's MCP runtime is being updated for the July 28 spec. Your agents keep calling tools the same way. The migration happens at the infrastructure layer.

Start Building
DG

Co-founder

Building the platform for AI agents at Chanl — tools, testing, and observability for customer experience.

Learn Agentic AI

Weekly. Patterns for shipping agents that work. MCP, scorecards, regression tests, prompts, model comparisons.

500+ builders subscribed

Frequently Asked Questions