#42238·appsmith

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

Author: mbasaranCreated Sep 16, 2026Updated Sep 16, 2026

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

typescript
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