From 1b096b4148e3eb274462157276c694f96fc4078c Mon Sep 17 00:00:00 2001 From: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> Date: Fri, 12 Jun 2026 12:39:14 -0500 Subject: [PATCH] fix(opencode): clear closed MCP clients (#32084) --- packages/opencode/src/mcp/index.ts | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/packages/opencode/src/mcp/index.ts b/packages/opencode/src/mcp/index.ts index 9a4beab158..36e0a44558 100644 --- a/packages/opencode/src/mcp/index.ts +++ b/packages/opencode/src/mcp/index.ts @@ -398,6 +398,19 @@ export const layer = Layer.effect( ) function watch(s: State, name: string, client: MCPClient, bridge: EffectBridge.Shape, timeout?: number) { + client.onclose = () => { + if (s.clients[name] !== client) return + delete s.clients[name] + delete s.defs[name] + s.status[name] = { status: "failed", error: "Connection closed" } + bridge.fork( + Effect.logWarning("MCP connection closed", { server: name }).pipe( + Effect.andThen(events.publish(ToolsChanged, { server: name })), + Effect.ignore, + ), + ) + } + client.setNotificationHandler(LoggingMessageNotificationSchema, (notification) => bridge.promise(serverLog(name, notification.params)), ) @@ -472,8 +485,11 @@ export const layer = Layer.effect( yield* Effect.addFinalizer(() => Effect.gen(function* () { + const clients = Object.values(s.clients) + s.clients = {} + s.defs = {} yield* Effect.forEach( - Object.values(s.clients), + clients, (client) => Effect.gen(function* () { const pid = client.transport instanceof StdioClientTransport ? client.transport.pid : null @@ -499,6 +515,7 @@ export const layer = Layer.effect( function closeClient(s: State, name: string) { const client = s.clients[name] + delete s.clients[name] delete s.defs[name] if (!client) return Effect.void return Effect.tryPromise(() => client.close()).pipe(Effect.ignore) @@ -512,11 +529,12 @@ export const layer = Layer.effect( timeout?: number, ) { const bridge = yield* EffectBridge.make() - yield* closeClient(s, name) + const previous = s.clients[name] s.status[name] = { status: "connected" } s.clients[name] = client s.defs[name] = listed watch(s, name, client, bridge, timeout) + if (previous) yield* Effect.tryPromise(() => previous.close()).pipe(Effect.ignore) return s.status[name] })