From cbcf191fdb7fbbf28ca1b48855dcb5daf12fb434 Mon Sep 17 00:00:00 2001 From: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> Date: Sat, 18 Jul 2026 23:38:07 -0500 Subject: [PATCH] fix(core): detach disposed MCP registrations from root scope (#37660) --- packages/core/src/mcp/index.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/core/src/mcp/index.ts b/packages/core/src/mcp/index.ts index 8271102880..7586f26272 100644 --- a/packages/core/src/mcp/index.ts +++ b/packages/core/src/mcp/index.ts @@ -210,7 +210,12 @@ export const layer = Layer.effect( entry.integrationID = integrationID owned.add(integrationID) const methodID = Integration.MethodID.make(suffix) - entry.registration = yield* integration + // Each registration gets its own child scope so disposal detaches it from the root scope + // entirely; registering directly on root would accumulate a dead finalizer per replaced or + // removed server for the lifetime of the layer. + const scope = yield* Scope.fork(root) + entry.registration = { dispose: Scope.close(scope, Exit.void) } + yield* integration .transform((draft) => { draft.update(integrationID, (ref) => { ref.name = name @@ -221,7 +226,7 @@ export const layer = Layer.effect( authorize: () => MCPOAuth.authorize({ name, config: remote, methodID }), }) }) - .pipe(Scope.provide(root)) + .pipe(Scope.provide(scope)) }) yield* Effect.forEach(runtime, ([name, entry]) => register(name, entry), { discard: true })