Skip to content

Support stateless mode for clients that don't preserve session IDs #173

Description

@iknox

Problem

Some MCP clients (e.g., OpenCode with type: "remote") do not preserve the mcp-session-id header across requests. The client correctly sends initialize, receives a session ID, but subsequent tools/list and tool call requests omit the header.

The current server rejects these with:

400 Bad Request: No valid session ID provided

Root Cause

@modelcontextprotocol/sdk v1.x requires sessionIdGenerator to be a function. Setting it to undefined throws a type error — stateless mode isn't available in v1.

Solution

The v2 SDK (@modelcontextprotocol/server@2.0.0-beta.4 + @modelcontextprotocol/node@2.0.0-beta.4) supports native stateless mode:

// v2: stateless — sessionIdGenerator: undefined disables session validation
const transport = new NodeStreamableHTTPServerTransport({
  sessionIdGenerator: undefined,
});

This would accept any POST without an mcp-session-id header, solving the issue cleanly.

Migration Scope

The v2 SDK replaces the monolithic @modelcontextprotocol/sdk with three packages:

  • @modelcontextprotocol/serverMcpServer, types
  • @modelcontextprotocol/nodeNodeStreamableHTTPServerTransport
  • @modelcontextprotocol/expresscreateMcpExpressApp

This touches ~16 files across src/ and __tests__/. The import paths change:

  • @modelcontextprotocol/sdk/server/mcp.js@modelcontextprotocol/server
  • @modelcontextprotocol/sdk/server/streamableHttp.js@modelcontextprotocol/node
  • @modelcontextprotocol/sdk/server/stdio.js@modelcontextprotocol/node
  • @modelcontextprotocol/sdk/types.js@modelcontextprotocol/server

Also requires zod as a peer dependency.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions