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

This commit is contained in:
Aiden Cline
2026-05-26 18:28:03 -05:00
committed by GitHub
parent 0e669bbd18
commit c0bc020ad6
2 changed files with 16 additions and 2 deletions
+12 -2
View File
@@ -234,6 +234,7 @@ interface AuthResult {
// --- Effect Service --- // --- Effect Service ---
interface State { interface State {
config: Record<string, ConfigMCP.Info>
status: Record<string, Status> status: Record<string, Status>
clients: Record<string, MCPClient> clients: Record<string, MCPClient>
defs: Record<string, MCPToolDef[]> defs: Record<string, MCPToolDef[]>
@@ -525,6 +526,7 @@ export const layer = Layer.effect(
const bridge = yield* EffectBridge.make() const bridge = yield* EffectBridge.make()
const config = cfg.mcp ?? {} const config = cfg.mcp ?? {}
const s: State = { const s: State = {
config: {},
status: {}, status: {},
clients: {}, clients: {},
defs: {}, defs: {},
@@ -619,6 +621,10 @@ export const layer = Layer.effect(
result[key] = s.status[key] ?? { status: "disabled" } result[key] = s.status[key] ?? { status: "disabled" }
} }
for (const key of Object.keys(s.config)) {
result[key] = s.status[key] ?? { status: "disabled" }
}
return result return result
}) })
@@ -642,8 +648,9 @@ export const layer = Layer.effect(
}) })
const add = Effect.fn("MCP.add")(function* (name: string, mcp: ConfigMCP.Info) { const add = Effect.fn("MCP.add")(function* (name: string, mcp: ConfigMCP.Info) {
yield* createAndStore(name, mcp)
const s = yield* InstanceState.get(state) const s = yield* InstanceState.get(state)
s.config[name] = mcp
yield* createAndStore(name, mcp)
return { status: s.status } return { status: s.status }
}) })
@@ -677,7 +684,7 @@ export const layer = Layer.effect(
([clientName, client]) => ([clientName, client]) =>
Effect.gen(function* () { Effect.gen(function* () {
const mcpConfig = config[clientName] 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] const listed = s.defs[clientName]
if (!listed) { if (!listed) {
@@ -756,6 +763,9 @@ export const layer = Layer.effect(
}) })
const getMcpConfig = Effect.fnUntraced(function* (mcpName: string) { 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 cfg = yield* cfgSvc.get()
const mcpConfig = cfg.mcp?.[mcpName] const mcpConfig = cfg.mcp?.[mcpName]
if (!mcpConfig || !isMcpConfigured(mcpConfig)) return undefined if (!mcpConfig || !isMcpConfigured(mcpConfig)) return undefined
@@ -109,6 +109,10 @@ describe("mcp HttpApi", () => {
expect(added.status).toBe(200) expect(added.status).toBe(200)
expect(yield* json(added)).toMatchObject({ added: { status: "disabled" } }) 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" }) const connected = yield* request(handler, "/mcp/demo/connect", tmp.directory, { method: "POST" })
expect(connected.status).toBe(200) expect(connected.status).toBe(200)
expect(yield* json(connected)).toBe(true) expect(yield* json(connected)).toBe(true)