fix(opencode): disconnect dynamically added mcp servers (#29452)
This commit is contained in:
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user