* fix: add transport isolation guards to prevent cross-client data leaks
When a single McpServer or stateless transport is reused across multiple
client connections, responses can be routed to the wrong client due to
message ID collisions. This is a data leak vulnerability (CWE-362).
Two guards added:
- Protocol.connect() throws if already connected to a transport
- Stateless transport.handleRequest() throws if called more than once
Also fixes three examples that shared a single McpServer across sessions:
- standaloneSseWithGetStreamableHttp.ts
- ssePollingExample.ts
- elicitationFormExample.ts
Related: #820, #204, #243
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: correct misleading test name and add per-request cleanup
- Rename 'should reject second SSE stream even in stateless mode' to
'should allow multiple SSE streams in stateless mode with per-request
transports' since the test now asserts both streams succeed (status 200)
- Add mcpServer.close() after per-request handling in
stateManagementStreamableHttp.test.ts to prevent resource leaks,
matching the pattern used in streamableHttp.test.ts
- Remove unused mcpServers array that collected but never cleaned up
per-request server instances
* thread abort through sendRequest and notification to prevent crosstalk
* test: remove dummy objects from stateless setupServer return
In stateless mode, setupServer() was creating unused McpServer and
StreamableHTTPServerTransport instances solely to satisfy the return
type. Make mcpServer/serverTransport optional in the return type and
simplify the stateless beforeEach/afterEach to only track server and
baseUrl.
* fix: use McpError for sendRequest abort guard and fix Hono example reuse
- sendRequest abort guard now throws McpError(ErrorCode.ConnectionClosed)
instead of plain Error for consistency with the rest of the codebase
- Hono example updated to create fresh transport and server per request,
fixing breakage from the stateless transport reuse guard
* fix: use separate resolvers per protocol in transport isolation test
Address review feedback: each protocol handler now has its own resolver
returning distinct data (responseForA vs responseForB), so the test
properly demonstrates that responses route to the correct transport.
Uses explicit 'handler entered' promises for deterministic synchronization.
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* Add secure default for DNS rebinding, use in examples
* Update README examples to use createMcpExpressApp, bump to 1.23.0
- Update all server examples to use createMcpExpressApp() for secure defaults
- Rewrite DNS Rebinding Protection section to document new middleware approach
- Bump version from 1.23.0-beta.0 to 1.23.0
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Add IPv6 support, allowedHosts option, and warning for unprotected servers
- Use native URL API to parse Host headers (handles IPv6 correctly)
- Add [::1] (IPv6 localhost) to localhostHostValidation
- Add ::1 to list of localhost hosts that get automatic protection
- Add allowedHosts option to createMcpExpressApp for custom host validation
- Warn when binding to 0.0.0.0 or :: without allowedHosts configured
- Add tests for IPv6 and allowedHosts functionality
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Update remaining examples to use createMcpExpressApp and add DNS rebinding docs
- Update simpleTaskInteractive.ts, ssePollingExample.ts, and elicitationUrlExample.ts
to use createMcpExpressApp() instead of express() + express.json()
- Add DNS rebinding protection section to docs/server.md explaining how to use
createMcpExpressApp() and hostHeaderValidation middleware
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>