Skip to content

refactor: create McpServer per session for reliable HTTP reconnection#299

Merged
GLips merged 3 commits intomainfrom
refactor/per-session-mcp-server
Mar 19, 2026
Merged

refactor: create McpServer per session for reliable HTTP reconnection#299
GLips merged 3 commits intomainfrom
refactor/per-session-mcp-server

Conversation

@GLips
Copy link
Copy Markdown
Owner

@GLips GLips commented Mar 19, 2026

Summary

  • Creates a new McpServer instance per StreamableHTTP/SSE session instead of sharing one across all connections
  • Matches the pattern from the MCP SDK documentation, which creates a new server inside each init handler
  • Fixes "Already connected to a transport" errors when clients reconnect without a clean session termination
  • Unifies transport tracking into a single sessions map that stores both the transport and its associated server
  • Promotes the multi-client concurrent test from it.fails to it (now works with per-session servers)

Test plan

  • New reconnection test: connect → terminate → reconnect → list tools
  • New dirty-close test: connect → close without terminate → reconnect → list tools
  • Smoke tested: reverted to shared server, dirty-close test timed out (caught the bug)
  • Multi-client test (StreamableHTTP + SSE concurrent) now passes
  • All 41 tests pass

GLips added 3 commits March 19, 2026 13:01
The MCP SDK expects one McpServer per transport connection. The previous
code shared a single instance across all HTTP sessions, which meant
reconnecting clients hit "Already connected to a transport" errors
because the old session's binding was never released.

Now each StreamableHTTP and SSE session gets its own McpServer instance,
matching the pattern from the SDK documentation. Sessions are tracked
in a unified map with their transport and server for cleanup.
The MCP SDK expects one McpServer per transport connection. The previous
code shared a single instance across all HTTP sessions, which meant
reconnecting clients hit "Already connected to a transport" errors
because the old session's binding was never released.

Now each StreamableHTTP and SSE session gets its own McpServer instance,
matching the pattern from the SDK documentation. Sessions are tracked
in a unified map with their transport and server for cleanup.

Also adds reconnection tests including a dirty-close scenario that
reproduces the original bug, and promotes the multi-client test from
it.fails to it (now works with per-session servers).
@GLips GLips merged commit 03bdb37 into main Mar 19, 2026
1 check passed
@GLips GLips deleted the refactor/per-session-mcp-server branch March 19, 2026 20:48
medyas pushed a commit to YassineValue/Figma-Context-MCP that referenced this pull request Mar 22, 2026
… errors

- Adopt upstream GLips#299 per-session McpServer architecture: each HTTP session
  gets its own McpServer instance, fixing "Already connected" errors on
  client reconnection. Preserved fork additions (health endpoint, metrics,
  caching support).
- fetchWithRetry: throw combined error with both fetch and curl failure
  reasons instead of silently discarding curl context.
- writeLogs: switch from sync fs to async fs/promises to avoid blocking
  the event loop when writing large debug files in development mode.
- style.ts: fix let→const for never-reassigned backgroundRepeat.
compassalessandrolorenz pushed a commit to compassalessandrolorenz/Figma-Context-MCP-AIR that referenced this pull request Mar 25, 2026
…GLips#299)

* refactor: create McpServer per session instead of sharing one instance

The MCP SDK expects one McpServer per transport connection. The previous
code shared a single instance across all HTTP sessions, which meant
reconnecting clients hit "Already connected to a transport" errors
because the old session's binding was never released.

Now each StreamableHTTP and SSE session gets its own McpServer instance,
matching the pattern from the SDK documentation. Sessions are tracked
in a unified map with their transport and server for cleanup.

* refactor: create McpServer per session instead of sharing one instance

The MCP SDK expects one McpServer per transport connection. The previous
code shared a single instance across all HTTP sessions, which meant
reconnecting clients hit "Already connected to a transport" errors
because the old session's binding was never released.

Now each StreamableHTTP and SSE session gets its own McpServer instance,
matching the pattern from the SDK documentation. Sessions are tracked
in a unified map with their transport and server for cleanup.

Also adds reconnection tests including a dirty-close scenario that
reproduces the original bug, and promotes the multi-client test from
it.fails to it (now works with per-session servers).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant