diff --git a/tui-plugins/oc-session-all.js b/tui-plugins/oc-session-all.js index 81e41e2..8039f62 100644 --- a/tui-plugins/oc-session-all.js +++ b/tui-plugins/oc-session-all.js @@ -46,8 +46,9 @@ function projectDisplayName(session, projectMap) { return session.projectID ? session.projectID.slice(0, 8) : "unknown" } -// MCP server 名单:opencode.json 里 enabled:false 的项(启动无 toast), +// MCP server 名单:opencode.json 里 disabled:true 的项(启动无自动连接、无 toast), // 由本插件运行时 connect 启用(官方语义:overriding disabled config until restart)。 +// 注意:enabled 字段会被 OC 的 server schema 剥掉,真正生效的开关是 disabled。 // 新增被禁用的 MCP server 时把名字加进来即可。 const MCP_NAMES = ["baota-mcp"] @@ -86,39 +87,39 @@ export default Plugin.define({ log("[oc-session-all] toast interceptor install ERROR: " + e.message) } - // ── MCP 运行时启用(config enabled:false + 插件 connect)──────────── + // ── MCP 运行时启用(config disabled:true + 插件 connect 覆盖)───────── + // OC 启动后 location/config 异步就绪(实测约 4~5s),过早调用会 list 为空 + // → connect 返回 404 "MCP server not found"。这里每 2s 重试直到成功(上限 90s)。 const enableMcp = async () => { - // 等服务端 MCP 子系统初始化完成 await delay(1500) - try { - // 1) dump 现状(供后续动态化:字段名/状态一并写日志) + const deadline = Date.now() + 90000 + let attempt = 0 + let pending = MCP_NAMES.slice() + while (pending.length && Date.now() < deadline) { + attempt++ try { const list = await context.client.mcp.list({ location: context.location }) const data = list && list.data !== undefined ? list.data : list - log("[oc-session-all] mcp.list dump: " + JSON.stringify(data).substring(0, 800)) + const names = Array.isArray(data) ? data.map((s) => s && s.name).filter(Boolean) : [] + log("[oc-session-all] mcp.list attempt=" + attempt + " names=[" + names.join(",") + "]") } catch (e) { - log("[oc-session-all] mcp.list ERROR: " + e.message) + log("[oc-session-all] mcp.list attempt=" + attempt + " ERROR: " + e.message) } - // 2) 逐个 connect(POST /api/experimental/mcp/:server/connect) - for (const name of MCP_NAMES) { + for (const name of pending.slice()) { try { await context.client.mcp.connect({ server: name, location: context.location }) - log("[oc-session-all] mcp.connect(" + name + ") OK") + log("[oc-session-all] mcp.connect(" + name + ") OK attempt=" + attempt) + pending = pending.filter((n) => n !== name) } catch (e) { - log("[oc-session-all] mcp.connect(" + name + ") ERROR: " + e.message) + const msg = String((e && e.message) || e) + log("[oc-session-all] mcp.connect(" + name + ") attempt=" + attempt + " ERROR: " + msg) + if (/already/i.test(msg)) pending = pending.filter((n) => n !== name) } } - // 3) connect 后再拉一次 list(服务端状态已变,日志记录结果) - try { - const after = await context.client.mcp.list({ location: context.location }) - const data = after && after.data !== undefined ? after.data : after - log("[oc-session-all] mcp.list after connect: " + JSON.stringify(data).substring(0, 800)) - } catch (e) { - log("[oc-session-all] mcp.list(after) ERROR: " + e.message) - } - } catch (e) { - log("[oc-session-all] enableMcp ERROR: " + e.message) + if (pending.length) await delay(2000) } + if (pending.length) log("[oc-session-all] enableMcp gave up, pending: " + pending.join(",")) + else log("[oc-session-all] enableMcp done, all connected") } void enableMcp()