mirror of
https://github.com/modelcontextprotocol/servers.git
synced 2026-04-27 16:25:19 +02:00
[WIP] Refactor everything server to be more modular and use recommended APIs.
Adding resource subscriptions:
* Updated architecture.md
* In server/index.ts
- imported Transport, setSubscriptionHandlers,beginSimulatedResourceUpdates, and stopSimulatedResourceUpdates
- call setSubscriptionHandlers passing server
- in returned object,
- refactor/renamed startNotificationIntervals placehodler to clientConnected, which takes a transport argument and calls beginSimulatedResourceUpdates, passing the transport
- replaced cleanup placeholder with a function that takes an optional sessionId and calls stopSimulatedResourceUpdates, passing the sessionId
* In sse.ts, stdio.ts, and streamableHttp.ts
- when transport is connected, called clientConnect, passing transport
- when disconnecting, called cleanup, passing sessionId
* Added subscriptions.ts
- tracks subscriber session id lists by URI
- tracks transport by session id
- tracks subscription update intervals by sessionId
- in setSubscriptionHandlers
- set request handlers for SubscribeRequestSchema and UnsubscribeRequestSchema
- in beginSimulatedResourceUpdates
- starts an interval to send updates to the transport for all subscribed resources
- in stopSimulatedResourceUpdates
- removes intervals and transport for gien session id
This commit is contained in:
@@ -21,7 +21,7 @@ const transports: Map<string, SSEServerTransport> = new Map<
|
||||
|
||||
app.get("/sse", async (req, res) => {
|
||||
let transport: SSEServerTransport;
|
||||
const { server, cleanup, startNotificationIntervals } = createServer();
|
||||
const { server, clientConnected, cleanup } = createServer();
|
||||
|
||||
if (req?.query?.sessionId) {
|
||||
const sessionId = req?.query?.sessionId as string;
|
||||
@@ -39,14 +39,15 @@ app.get("/sse", async (req, res) => {
|
||||
await server.connect(transport);
|
||||
console.error("Client Connected: ", transport.sessionId);
|
||||
|
||||
// Start notification intervals after client connects
|
||||
startNotificationIntervals(transport.sessionId);
|
||||
// Start simulated logging and subscription updates when a client connects
|
||||
clientConnected(transport);
|
||||
|
||||
// Handle close of connection
|
||||
server.server.onclose = async () => {
|
||||
console.error("Client Disconnected: ", transport.sessionId);
|
||||
transports.delete(transport.sessionId);
|
||||
await cleanup();
|
||||
const sessionId = transport.sessionId;
|
||||
console.error("Client Disconnected: ", sessionId);
|
||||
transports.delete(sessionId);
|
||||
await cleanup(sessionId);
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
@@ -7,13 +7,15 @@ console.error("Starting default (STDIO) server...");
|
||||
|
||||
async function main() {
|
||||
const transport = new StdioServerTransport();
|
||||
const { server } = createServer();
|
||||
const { server, clientConnected, cleanup } = createServer();
|
||||
|
||||
await server.connect(transport);
|
||||
clientConnected(transport);
|
||||
|
||||
// Cleanup on exit
|
||||
process.on("SIGINT", async () => {
|
||||
await server.close();
|
||||
cleanup();
|
||||
process.exit(0);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ app.post("/mcp", async (req: Request, res: Response) => {
|
||||
// Reuse existing transport
|
||||
transport = transports.get(sessionId)!;
|
||||
} else if (!sessionId) {
|
||||
const { server } = createServer();
|
||||
const { server, clientConnected, cleanup } = createServer();
|
||||
|
||||
// New initialization request
|
||||
const eventStore = new InMemoryEventStore();
|
||||
@@ -43,10 +43,13 @@ app.post("/mcp", async (req: Request, res: Response) => {
|
||||
sessionIdGenerator: () => randomUUID(),
|
||||
eventStore, // Enable resumability
|
||||
onsessioninitialized: (sessionId: string) => {
|
||||
// Store the transport by session ID when session is initialized
|
||||
// Store the transport by session ID when a session is initialized
|
||||
// This avoids race conditions where requests might come in before the session is stored
|
||||
console.log(`Session initialized with ID: ${sessionId}`);
|
||||
transports.set(sessionId, transport);
|
||||
|
||||
// Start simulated logging and subscription updates when a client connects
|
||||
clientConnected(transport);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -58,6 +61,7 @@ app.post("/mcp", async (req: Request, res: Response) => {
|
||||
`Transport closed for session ${sid}, removing from transports map`
|
||||
);
|
||||
transports.delete(sid);
|
||||
cleanup(sid);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user