In src/everything/resources/subscriptions.ts, subscriptions is a module-level Map<uri, Set<sessionId>>. A session id is added on resources/subscribe and removed only on resources/unsubscribe. Nothing removes it when the session ends.
Both transports call cleanup(sessionId) from server.server.onclose (transports/streamableHttp.ts, transports/sse.ts). That function (server/index.ts:109) calls stopSimulatedLogging, stopSimulatedResourceUpdates and taskStore.cleanup(), so the interval timers are cleared, but subscriptions is not touched. A client that subscribes and then disconnects without unsubscribing leaves its session id in every Set it joined, for the life of the process.
Until #4104 the else branch of sendSimulatedResourceUpdates carried a comment saying it removed disconnected subscribers. It did not (it deleted from a Set that provably lacked the element), and the branch is now gone, so there is no longer anything that even implies cleanup exists.
Impact is small for a reference server, but it is the example people copy. Suggested fix: export a removeSubscriber(sessionId) from subscriptions.ts that iterates the map, deletes the session from each Set and drops empty entries, and call it from cleanup().
In
src/everything/resources/subscriptions.ts,subscriptionsis a module-levelMap<uri, Set<sessionId>>. A session id is added onresources/subscribeand removed only onresources/unsubscribe. Nothing removes it when the session ends.Both transports call
cleanup(sessionId)fromserver.server.onclose(transports/streamableHttp.ts,transports/sse.ts). That function (server/index.ts:109) callsstopSimulatedLogging,stopSimulatedResourceUpdatesandtaskStore.cleanup(), so the interval timers are cleared, butsubscriptionsis not touched. A client that subscribes and then disconnects without unsubscribing leaves its session id in every Set it joined, for the life of the process.Until #4104 the
elsebranch ofsendSimulatedResourceUpdatescarried a comment saying it removed disconnected subscribers. It did not (it deleted from a Set that provably lacked the element), and the branch is now gone, so there is no longer anything that even implies cleanup exists.Impact is small for a reference server, but it is the example people copy. Suggested fix: export a
removeSubscriber(sessionId)fromsubscriptions.tsthat iterates the map, deletes the session from each Set and drops empty entries, and call it fromcleanup().