[BUG] MCP Streamable-HTTP session cleanup uses wrong key (auto-UUID) — sessions leak forever
- Dominant language
- Java
- Stars
- 8.8k
- Forks
- 3.1k
- Avg merge
- 7d 1h
- Merged PRs (30d)
- 85
Description
## Description
`ShenyuStreamableHttpServerTransportProvider.handleInitializeRequest` builds `new StreamableHttpSessionTransport()` (constructor sets `this.sessionId = UUID.randomUUID()` — the auto-UUID), but stores the session under `newSessionId = session.getId()` (the `McpServerSession`'s id, different from the transport's auto-UUID). `transport.close()`/`closeGracefully()` call `removeSession(this.sessionId)` (the auto-UUID), which removes nothing; the entries under `newSessionId` stay forever. There is also no TTL/eviction on `sessions`/`sessionTransports`/`ShenyuMcpExchangeHolder.EXCHANGE_MAP`.
## Location
- `shenyu-plugin/shenyu-plugin-mcp-server/src/main/java/org/apache/shenyu/plugin/mcp/server/transport/ShenyuStreamableHttpServerTransportProvider.java:321-329` (configureExchangeForSession + store under newSessionId), `1020-1023` (transport sessionId = auto-UUID), `1071-1088` (close/closeGracefully call removeSession(this.sessionId)), `763-766` (removeSession)
## Impact
Unbounded memory growth / DoS — every Streamable-HTTP session leaks until process shutdown. (The temporary-session path at :433 correctly uses `session.getId()` for cleanup, which highlights that the permanent-session path is the bug.)
## Suggested fix
Store sessions under the same key the transport uses for cleanup (or make `removeSession` look up by transport's sessionId); add a TTL/last-seen eviction sweep.
## Related existing
Distinct from MCP-05 (#6644, `createSessionAndRestoreId` restore-path creation leak) — this is the main initialize-path cleanup-key mismatch plus total absence of expiry.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start in shenyu-plugin/shenyu-plugin-mcp-server/src/main/java/org/apache/shenyu/plugin/mcp/server/transport/ShenyuStreamableHttpServerTransportProvider.java, especially configureExchangeForSession, handleInitializeRequest, removeSession, and the transport close methods at the cited lines. Trace how the permanent-session key differs from the transport sessionId, then review the existing temporary-session cleanup path. Done means sessions and exchange entries are removed on close and receive the proposed TTL or last-seen eviction behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 68/100