diff --git a/packages/opencode/src/cli/cmd/tui/context/sync.tsx b/packages/opencode/src/cli/cmd/tui/context/sync.tsx index 0edc911344c..ada6c277d78 100644 --- a/packages/opencode/src/cli/cmd/tui/context/sync.tsx +++ b/packages/opencode/src/cli/cmd/tui/context/sync.tsx @@ -300,6 +300,11 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({ break } + case "tui.mcp.refresh": { + sdk.client.mcp.status().then((x) => setStore("mcp", reconcile(x.data!))) + break + } + case "vcs.branch.updated": { setStore("vcs", { branch: event.properties.branch }) break diff --git a/packages/opencode/src/cli/cmd/tui/event.ts b/packages/opencode/src/cli/cmd/tui/event.ts index 7c75523c136..56ba24931ca 100644 --- a/packages/opencode/src/cli/cmd/tui/event.ts +++ b/packages/opencode/src/cli/cmd/tui/event.ts @@ -4,6 +4,7 @@ import z from "zod" export const TuiEvent = { PromptAppend: BusEvent.define("tui.prompt.append", z.object({ text: z.string() })), + McpRefresh: BusEvent.define("tui.mcp.refresh", z.object({})), CommandExecute: BusEvent.define( "tui.command.execute", z.object({ diff --git a/packages/opencode/src/mcp/index.ts b/packages/opencode/src/mcp/index.ts index aca0c663152..4ea0be15d83 100644 --- a/packages/opencode/src/mcp/index.ts +++ b/packages/opencode/src/mcp/index.ts @@ -269,6 +269,9 @@ export namespace MCP { s.clients[name] = result.mcpClient s.status[name] = result.status + // Notify TUI to refresh MCP status + Bus.publish(TuiEvent.McpRefresh, {}) + return { status: s.status, } @@ -488,6 +491,13 @@ export namespace MCP { result[key] = s.status[key] ?? { status: "disabled" } } + // Include dynamically registered MCPs not in config + for (const [key, status] of Object.entries(s.status)) { + if (!(key in result)) { + result[key] = status + } + } + return result } diff --git a/packages/sdk/js/src/v2/gen/sdk.gen.ts b/packages/sdk/js/src/v2/gen/sdk.gen.ts index f83913ea5e1..dd27a7a9f59 100644 --- a/packages/sdk/js/src/v2/gen/sdk.gen.ts +++ b/packages/sdk/js/src/v2/gen/sdk.gen.ts @@ -18,6 +18,7 @@ import type { ConfigUpdateResponses, EventSubscribeResponses, EventTuiCommandExecute, + EventTuiMcpRefresh, EventTuiPromptAppend, EventTuiSessionSelect, EventTuiToastShow, @@ -2898,7 +2899,12 @@ export class Tui extends HeyApiClient { public publish( parameters?: { directory?: string - body?: EventTuiPromptAppend | EventTuiCommandExecute | EventTuiToastShow | EventTuiSessionSelect + body?: + | EventTuiPromptAppend + | EventTuiMcpRefresh + | EventTuiCommandExecute + | EventTuiToastShow + | EventTuiSessionSelect }, options?: Options, ) { diff --git a/packages/sdk/js/src/v2/gen/types.gen.ts b/packages/sdk/js/src/v2/gen/types.gen.ts index 9cb7222aa5f..5a3ad44933f 100644 --- a/packages/sdk/js/src/v2/gen/types.gen.ts +++ b/packages/sdk/js/src/v2/gen/types.gen.ts @@ -632,6 +632,13 @@ export type EventTuiPromptAppend = { } } +export type EventTuiMcpRefresh = { + type: "tui.mcp.refresh" + properties: { + [key: string]: unknown + } +} + export type EventTuiCommandExecute = { type: "tui.command.execute" properties: { @@ -862,6 +869,7 @@ export type Event = | EventFileEdited | EventTodoUpdated | EventTuiPromptAppend + | EventTuiMcpRefresh | EventTuiCommandExecute | EventTuiToastShow | EventTuiSessionSelect @@ -4605,7 +4613,7 @@ export type TuiShowToastResponses = { export type TuiShowToastResponse = TuiShowToastResponses[keyof TuiShowToastResponses] export type TuiPublishData = { - body?: EventTuiPromptAppend | EventTuiCommandExecute | EventTuiToastShow | EventTuiSessionSelect + body?: EventTuiPromptAppend | EventTuiMcpRefresh | EventTuiCommandExecute | EventTuiToastShow | EventTuiSessionSelect path?: never query?: { directory?: string