fix(opencode): clear closed MCP clients (#32084)

This commit is contained in:
Aiden Cline
2026-06-12 12:39:14 -05:00
committed by GitHub
parent be227503af
commit 1b096b4148
+20 -2
View File
@@ -398,6 +398,19 @@ export const layer = Layer.effect(
) )
function watch(s: State, name: string, client: MCPClient, bridge: EffectBridge.Shape, timeout?: number) { 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) => client.setNotificationHandler(LoggingMessageNotificationSchema, (notification) =>
bridge.promise(serverLog(name, notification.params)), bridge.promise(serverLog(name, notification.params)),
) )
@@ -472,8 +485,11 @@ export const layer = Layer.effect(
yield* Effect.addFinalizer(() => yield* Effect.addFinalizer(() =>
Effect.gen(function* () { Effect.gen(function* () {
const clients = Object.values(s.clients)
s.clients = {}
s.defs = {}
yield* Effect.forEach( yield* Effect.forEach(
Object.values(s.clients), clients,
(client) => (client) =>
Effect.gen(function* () { Effect.gen(function* () {
const pid = client.transport instanceof StdioClientTransport ? client.transport.pid : null 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) { function closeClient(s: State, name: string) {
const client = s.clients[name] const client = s.clients[name]
delete s.clients[name]
delete s.defs[name] delete s.defs[name]
if (!client) return Effect.void if (!client) return Effect.void
return Effect.tryPromise(() => client.close()).pipe(Effect.ignore) return Effect.tryPromise(() => client.close()).pipe(Effect.ignore)
@@ -512,11 +529,12 @@ export const layer = Layer.effect(
timeout?: number, timeout?: number,
) { ) {
const bridge = yield* EffectBridge.make() const bridge = yield* EffectBridge.make()
yield* closeClient(s, name) const previous = s.clients[name]
s.status[name] = { status: "connected" } s.status[name] = { status: "connected" }
s.clients[name] = client s.clients[name] = client
s.defs[name] = listed s.defs[name] = listed
watch(s, name, client, bridge, timeout) watch(s, name, client, bridge, timeout)
if (previous) yield* Effect.tryPromise(() => previous.close()).pipe(Effect.ignore)
return s.status[name] return s.status[name]
}) })