Browse Source

fix(opencode): disconnect dynamically added mcp servers (#29452)

Aiden Cline 3 months ago
parent
commit
c0bc020ad6

+ 12 - 2
packages/opencode/src/mcp/index.ts

@@ -234,6 +234,7 @@ interface AuthResult {
 // --- Effect Service ---
 
 interface State {
+  config: Record<string, ConfigMCP.Info>
   status: Record<string, Status>
   clients: Record<string, MCPClient>
   defs: Record<string, MCPToolDef[]>
@@ -525,6 +526,7 @@ export const layer = Layer.effect(
         const bridge = yield* EffectBridge.make()
         const config = cfg.mcp ?? {}
         const s: State = {
+          config: {},
           status: {},
           clients: {},
           defs: {},
@@ -619,6 +621,10 @@ export const layer = Layer.effect(
         result[key] = s.status[key] ?? { status: "disabled" }
       }
 
+      for (const key of Object.keys(s.config)) {
+        result[key] = s.status[key] ?? { status: "disabled" }
+      }
+
       return result
     })
 
@@ -642,8 +648,9 @@ export const layer = Layer.effect(
     })
 
     const add = Effect.fn("MCP.add")(function* (name: string, mcp: ConfigMCP.Info) {
-      yield* createAndStore(name, mcp)
       const s = yield* InstanceState.get(state)
+      s.config[name] = mcp
+      yield* createAndStore(name, mcp)
       return { status: s.status }
     })
 
@@ -677,7 +684,7 @@ export const layer = Layer.effect(
         ([clientName, client]) =>
           Effect.gen(function* () {
             const mcpConfig = config[clientName]
-            const entry = mcpConfig && isMcpConfigured(mcpConfig) ? mcpConfig : undefined
+            const entry = mcpConfig && isMcpConfigured(mcpConfig) ? mcpConfig : s.config[clientName]
 
             const listed = s.defs[clientName]
             if (!listed) {
@@ -756,6 +763,9 @@ export const layer = Layer.effect(
     })
 
     const getMcpConfig = Effect.fnUntraced(function* (mcpName: string) {
+      const s = yield* InstanceState.get(state)
+      if (s.config[mcpName]) return s.config[mcpName]
+
       const cfg = yield* cfgSvc.get()
       const mcpConfig = cfg.mcp?.[mcpName]
       if (!mcpConfig || !isMcpConfigured(mcpConfig)) return undefined

+ 4 - 0
packages/opencode/test/server/httpapi-mcp.test.ts

@@ -109,6 +109,10 @@ describe("mcp HttpApi", () => {
         expect(added.status).toBe(200)
         expect(yield* json(added)).toMatchObject({ added: { status: "disabled" } })
 
+        const addedDisconnected = yield* request(handler, "/mcp/added/disconnect", tmp.directory, { method: "POST" })
+        expect(addedDisconnected.status).toBe(200)
+        expect(yield* json(addedDisconnected)).toBe(true)
+
         const connected = yield* request(handler, "/mcp/demo/connect", tmp.directory, { method: "POST" })
         expect(connected.status).toBe(200)
         expect(yield* json(connected)).toBe(true)