mirror of
https://github.com/modelcontextprotocol/servers.git
synced 2026-04-18 00:03:23 +02:00
[WIP] Refactor everything server to be more modular and use recommended APIs.
Adding simulated logging and refactoring subscriptions to not need to track transports
* Updated architecture.md
* In server/index.ts
- remove import of Transport
- import beginSimulatedLogging and stopSimulatedLogging
- in clientConnected()
- change argument to sessionId? instead of transport
- add call to beginSimulatedLogging
- send server and sessionId to beginSimulatedResourceUpdates and beginSimulatedLogging
- in cleanup()
- add call to stopSimulatedLogging passing sessionId
* Added server/logging.ts
- Initialize logsUpdateIntervals to Map session ID to the interval for sending logging messages to the client
- in beginSimulatedLogging()
- create an array of logging meesages, customized with the sessionId if present
- if the interval for the sessionId hasn't been set, create one, calling server.sendLoggingMessage with a random message to the client each time the interval elapses
- in stopSimulatedLogging()
- if a logging interval exists for the sessionId, clear it and remove it
* In subscriptions.ts
- remove import of Transport
- remove transports map
- in beginSimulatedResourceUpdates()
- change arguments to server and sessionId
- check for the subsUpdateInterval for the session
- remove all transport storage and interaction
- instead use the server to send the notification
- in stopSimulatedResourceUpdates()
- remove management of transports map
* In sse.ts and streamableHttp.ts
- when calling clientConnected, pass sessionId instead of transport
* In stdio.ts,
- when calling clientConnected, pass nothing instead of transport
* In subscriptions.ts
- updated inline doc
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
||||
import { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
|
||||
import {
|
||||
SubscribeRequestSchema,
|
||||
UnsubscribeRequestSchema,
|
||||
@@ -11,12 +10,6 @@ const subscriptions: Map<string, Set<string | undefined>> = new Map<
|
||||
Set<string | undefined>
|
||||
>();
|
||||
|
||||
// Track transport by session id
|
||||
const transports: Map<string | undefined, Transport> = new Map<
|
||||
string | undefined,
|
||||
Transport
|
||||
>();
|
||||
|
||||
// Interval to send notifications to subscribers
|
||||
const subsUpdateIntervals: Map<string | undefined, NodeJS.Timeout | undefined> =
|
||||
new Map<string | undefined, NodeJS.Timeout | undefined>();
|
||||
@@ -105,35 +98,28 @@ export const setSubscriptionHandlers = (server: McpServer) => {
|
||||
|
||||
/**
|
||||
* Starts the process of simulating resource updates and sending server notifications
|
||||
* to subscribed clients at regular intervals. If the update interval is already active,
|
||||
* invoking this function will not start another interval.
|
||||
* to the client for the resources they are subscribed to. If the update interval is
|
||||
* already active, invoking this function will not start another interval.
|
||||
*
|
||||
* Note that tracking and sending updates on the transport of the subscriber allows for
|
||||
* multiple clients to be connected and independently receive only updates about their
|
||||
* own subscriptions. Had we used `server.notification` instead, all clients would
|
||||
* receive updates for all subscriptions.
|
||||
*
|
||||
* @param {Transport} transport - The transport to the subscriber
|
||||
* @param server
|
||||
* @param sessionId
|
||||
*/
|
||||
export const beginSimulatedResourceUpdates = (transport: Transport) => {
|
||||
const sessionId = transport?.sessionId;
|
||||
if (!transports.has(sessionId)) {
|
||||
// Store the transport
|
||||
transports.set(sessionId, transport);
|
||||
|
||||
// Set the interval to send notifications to the subscribers
|
||||
export const beginSimulatedResourceUpdates = (
|
||||
server: McpServer,
|
||||
sessionId: string | undefined
|
||||
) => {
|
||||
if (!subsUpdateIntervals.has(sessionId)) {
|
||||
// Set the interval to send resource update notifications to this client
|
||||
subsUpdateIntervals.set(
|
||||
sessionId,
|
||||
setInterval(async () => {
|
||||
// Send notifications to all subscribers for each URI
|
||||
// Search all URIs for ones this client is subscribed to
|
||||
for (const uri of subscriptions.keys()) {
|
||||
const subscribers = subscriptions.get(uri) as Set<string | undefined>;
|
||||
|
||||
// Get the transport for the subscriber and send the notification
|
||||
// If this client is subscribed, send the notification
|
||||
if (subscribers.has(sessionId)) {
|
||||
const transport = transports.get(sessionId) as Transport;
|
||||
await transport.send({
|
||||
jsonrpc: "2.0",
|
||||
await server.server.notification({
|
||||
method: "notifications/resources/updated",
|
||||
params: { uri },
|
||||
});
|
||||
@@ -162,8 +148,4 @@ export const stopSimulatedResourceUpdates = (sessionId?: string) => {
|
||||
clearInterval(subsUpdateInterval);
|
||||
subsUpdateIntervals.delete(sessionId);
|
||||
}
|
||||
// Remove transport for the session
|
||||
if (transports.has(sessionId)) {
|
||||
transports.delete(sessionId);
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user