Skip to content

Commit bc17ace

Browse files
authored
fix(mcp-server): enforce session binding and response isolation in HTTP SSE transport (#312)
* fix(mcp-server): enforce session binding and response isolation in HTTP SSE transport * Updated reference to latest sei-assetlist repo from Seitrace * Added changeset
1 parent 9168186 commit bc17ace

5 files changed

Lines changed: 197 additions & 65 deletions

File tree

.changeset/calm-houses-listen.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
"@sei-js/mcp-server": patch
3+
---
4+
5+
Fix session binding and response isolation in the HTTP SSE transport.
6+
7+
- POST handler now validates `sessionId` on every request — rejects missing session IDs (400) and unknown session IDs (404)
8+
- Each POST is routed to the transport instance that owns the matching session ID, preventing cross-client request injection
9+
- Session IDs now use the MCP SDK's `transport.sessionId` rather than `Date.now()`

.gitmodules

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[submodule "packages/registry/community-assetlist"]
22
path = packages/registry/community-assetlist
3-
url = https://github.com/Sei-Public-Goods/sei-assetlist.git
3+
url = https://github.com/Seitrace/sei-assetlist.git
44
[submodule "packages/registry/chain-registry"]
55
path = packages/registry/chain-registry
66
url = https://github.com/sei-protocol/chain-registry.git

packages/mcp-server/src/server/transport/http-sse.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,12 @@ export class HttpSseTransport implements McpTransport {
4040

4141
this.app.get(this.path, (req: Request, res: Response) => {
4242
console.error(`SSE connection from ${req.ip}`);
43-
43+
4444
// Create SSE transport - it will handle headers automatically
4545
const transport = new SSEServerTransport(`${this.path}/message`, res);
46-
const sessionId = Date.now().toString();
46+
const sessionId = transport.sessionId
4747
this.connections.set(sessionId, transport);
48-
48+
4949
// Connect transport to MCP server
5050
if (this.mcpServer) {
5151
this.mcpServer.connect(transport);
@@ -61,10 +61,15 @@ export class HttpSseTransport implements McpTransport {
6161
// Message endpoint for SSE transport
6262
this.app.post(`${this.path}/message`, async (req: Request, res: Response) => {
6363
try {
64-
// Find the first available transport (simple approach for now)
65-
const transport = Array.from(this.connections.values())[0];
64+
const sessionId = typeof req.query.sessionId === 'string' ? req.query.sessionId : undefined;
65+
if (!sessionId) {
66+
res.status(400).json({ error: 'Missing sessionId' });
67+
return;
68+
}
69+
70+
const transport = this.connections.get(sessionId);
6671
if (!transport) {
67-
res.status(404).json({ error: 'No active SSE connection' });
72+
res.status(404).json({ error: 'Session not found' });
6873
return;
6974
}
7075

0 commit comments

Comments
 (0)