mirror of
https://github.com/modelcontextprotocol/servers.git
synced 2026-04-19 16:43:24 +02:00
For both sse and streamableHttp, a server instance needs to be created for each transport. Otherwise, when a new client connects and its new transport is connected to the single server, the previous transport is overwritten in the server instance and can no longer communicate.
* In sse.ts
- remove global server, cleanup, and transport vars
- add transports map
- in sse GET handler,
- check for sessionId, there shouldn't be one, so comment "Reconnecting?" and do nothing if present
- if sessionId not present
- create new server and transport instance
- connect server to transport
- add transport to transports map
- in server.onclose, delete the transport from the transports map and call cleanup
- in /message POST handler
- get the sessionId from the request
- get the transport from the map by sessionId
- handle the message if the transport was found
* In streamableHttp.ts
- remove the global server and cleanup vars
- change transports var to Map
- in /mcp POST handler
- when creating a new session
- create a server instance
- in server.onclose, delete the transport from the transports map and call cleanup
- remove the calls to cleanup and server.close in the SIGINT handler, because the transport is closed and its onclose handler closes the server.
52 lines
1.6 KiB
TypeScript
52 lines
1.6 KiB
TypeScript
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
|
|
import express from "express";
|
|
import { createServer } from "./everything.js";
|
|
|
|
console.error('Starting SSE server...');
|
|
|
|
const app = express();
|
|
|
|
const transports: Map<string, SSEServerTransport> = new Map<string, SSEServerTransport>();
|
|
|
|
app.get("/sse", async (req, res) => {
|
|
let transport: SSEServerTransport;
|
|
const { server, cleanup } = createServer();
|
|
|
|
if (req?.query?.sessionId) {
|
|
const sessionId = (req?.query?.sessionId as string) || "none";
|
|
transport = transports.get(sessionId) as SSEServerTransport;
|
|
console.error("Client Reconnecting? ", transport.sessionId);
|
|
} else {
|
|
// Create and store transport for new session
|
|
transport = new SSEServerTransport("/message", res);
|
|
transports.set(transport.sessionId, transport);
|
|
|
|
// Connect server to transport
|
|
await server.connect(transport);
|
|
console.error("Client Connected: ", transport.sessionId);
|
|
|
|
// Handle close of connection
|
|
server.onclose = async () => {
|
|
console.error("Client Disconnected: ", transport.sessionId);
|
|
transports.delete(transport.sessionId);
|
|
await cleanup();
|
|
};
|
|
|
|
}
|
|
|
|
});
|
|
|
|
app.post("/message", async (req, res) => {
|
|
const sessionId = (req?.query?.sessionId as string) || "none";
|
|
const transport = transports.get(sessionId);
|
|
if (transport) {
|
|
console.error("Client Message from", sessionId);
|
|
await transport.handlePostMessage(req, res);
|
|
}
|
|
});
|
|
|
|
const PORT = process.env.PORT || 3001;
|
|
app.listen(PORT, () => {
|
|
console.error(`Server is running on port ${PORT}`);
|
|
});
|