Skip to content

[Bug]: MCP server on Cloud rejects its own session ids — sessions are per-process, break behind multiple replicas #42238

Description

@mbasaran

Is there an existing issue for this?

  • I have searched the existing issues

Description

On Appsmith Cloud, the embedded MCP server (appsmith-mcp 0.0.1) accepts initialize and returns an Mcp-Session-Id, but then rejects that same session id on nearly every follow-up request:

HTTP 404
{"error":"session not found; initialize a new MCP session"}

Result: every standard MCP client (Claude Code, etc.) connects, initializes successfully, fails on its first real call (tools/list), and drops the server. The MCP feature is effectively unusable on Cloud.

Cause (in source): sessions are stored in a per-process Map —

app/client/packages/mcp/src/app.ts:7011

const sessions = new Map<string, McpSession>();

registered in onsessioninitialized (app.ts:7282, sessionIdGenerator: randomUUID) and removed in transport.onclose. With more than one replica behind a load balancer that has no session affinity, initialize lands on replica A and registers the session there, while subsequent POSTs are balanced across the other replicas, none of which know the id.

Note that #42210 ("Now Mcp also accepts redis cluster", merged 2026-09-08) moved governance state into Redis (governance/store.ts) but did not touch the transport session map, so that path is still per-process.

Stateless mode is not available as a workaround: tools/list without a session id returns 400 {"error":"initialize the MCP session first"}.

What I expect: a session issued at initialize is honored by all subsequent requests carrying its Mcp-Session-Id, regardless of which replica serves them.

Steps To Reproduce

Against a Cloud tenant, with a valid MCP key as bearer token (from the "Connect an MCP client" page):

  1. POST /mcp with an initialize request → 200 OK, Mcp-Session-Id header present, correct handshake body (serverInfo: appsmith-mcp 0.0.1, protocol 2025-06-18).
  2. POST /mcp with that Mcp-Session-Id header and {"jsonrpc":"2.0","id":2,"method":"tools/list"}.
  3. Repeat step 2 against the same session id.

Twelve consecutive attempts on one session id:

Oxxxxxxxxxxx      → 1 success, 11 × "session not found"

Roughly 1 in 12 requests succeeds, consistent with a dozen or so replicas behind a non-sticky balancer. No Set-Cookie is issued on initialize, so a client has nothing to echo back for affinity.

Initialize response headers:

HTTP/1.1 200 OK
Mcp-Session-Id: 805e04fd-964f-47ea-a0d7-c12c314fb2a2
Via: 1.1 Caddy, 1.1 <redacted>.cloudfront.net (CloudFront)
X-Appsmith-Request-Id: 74a64b33-167c-4ceb-ac8e-2e6711108b51

Auth is not the problem: without a token the endpoint returns a clean 401 + WWW-Authenticate: Bearer, and with the token initialize succeeds every time.

Suggested fixes

  • Short term (ops): session affinity at the Caddy/CDN layer keyed on the Mcp-Session-Id header.
  • Medium term: back the session map with the shared Redis already used by the governance store, so any replica can serve any session.
  • Alternative: run the transport stateless (sessionIdGenerator: undefined) where per-session server state isn't required.

Public Sample App

No response — not app-specific; reproduces at the transport layer with any tenant and any MCP key.

Environment

Production

Severity

High (Blocker to building or releasing)

Issue video log

No response

Version

Cloud — appsmith-mcp 0.0.1 (per initialize handshake), tested 2026-09-16

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions