refactor!: switch to stateless HTTP transport#304
Merged
Conversation
Each request creates its own McpServer and transport with sessionIdGenerator: undefined. Removes the session registry, SSE transport, /messages endpoint, and progress notification interval. StreamableHTTP is served at both /mcp and /sse for backward compatibility. GET and DELETE return 405.
Express 4 does not catch rejected promises from async handlers. Without a try/catch, a failure in connect() or handleRequest() causes an unhandled rejection that crashes the process.
Aligns with the MCP SDK which already depends on Express 5. Express 5 natively catches async route handler rejections, so the manual try/catch added in the previous commit is no longer needed.
Close transport and McpServer when the response ends, matching the SDK's recommended pattern for stateless servers. Add Express error-handling middleware that returns a JSON-RPC error response instead of Express's default HTML 500.
Replace raw express() with the SDK's createMcpExpressApp(), which applies localhost DNS rebinding protection middleware automatically. This also handles express.json() globally, removing the need for per-route body parsing.
GLips
added a commit
that referenced
this pull request
Mar 24, 2026
Keep active connection tracking and graceful shutdown from the progress notifications branch. The squash merge of #304 into main didn't include these additions.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
McpServer+StreamableHTTPServerTransportwithsessionIdGenerator: undefined. Removes the entire session registry, SSE transport,/messagesendpoint, and progress notification interval./mcpand/sse— existing client configs that point at/ssekeep working since modern MCP clients probe with POST first.createMcpExpressApp()instead of rawexpress(), which applies localhost Host header validation automatically.transport.close()/mcpServer.close()cleanup on response end./mcpand/sse.Net: -514 lines across server + tests.
Breaking changes
SSEClientTransportmust upgrade toStreamableHTTPClientTransport. The/sseURL still works.mcp-session-idheader in responses. Clients relying on session persistence across requests will see each request as independent.Test plan
pnpm test— 46 pass, 1 skipped (integration, needs API key)pnpm type-check— cleanpnpm lint— clean/mcp/sse(backward compat)mcp-session-idheader/mcpand/ssereturn 405