From e1982a42b23be16f775c4599fca13ca1d139b45e Mon Sep 17 00:00:00 2001 From: Ariane Emory Date: Wed, 4 Mar 2026 08:44:19 -0500 Subject: [PATCH 1/2] feat: add click-to-toggle functionality for MCP servers in sidebar - Add click handlers to MCP server entries in the TUI sidebar - Integrate with existing local.mcp.toggle() API - Add loading state to prevent concurrent toggles - Show 'Loading...' indicator during toggle operations - Refresh MCP status from server after toggle - Maintain visual feedback with muted text during loading --- .../cli/cmd/tui/routes/session/sidebar.tsx | 29 +++++++++++++++++-- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/sidebar.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/sidebar.tsx index 42ac5fbe080..f2ff2938996 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/sidebar.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/sidebar.tsx @@ -1,5 +1,5 @@ import { useSync } from "@tui/context/sync" -import { createMemo, For, Show, Switch, Match } from "solid-js" +import { createMemo, createSignal, For, Show, Switch, Match } from "solid-js" import { createStore } from "solid-js/store" import { useTheme } from "../../context/theme" import { Locale } from "@/util/locale" @@ -10,6 +10,8 @@ import { Installation } from "@/installation" import { useKeybind } from "../../context/keybind" import { useDirectory } from "../../context/directory" import { useKV } from "../../context/kv" +import { useLocal } from "@tui/context/local" +import { useSDK } from "@tui/context/sdk" import { TodoItem } from "../../component/todo-item" export function Sidebar(props: { sessionID: string; overlay?: boolean }) { @@ -27,6 +29,24 @@ export function Sidebar(props: { sessionID: string; overlay?: boolean }) { lsp: true, }) + const local = useLocal() + const sdk = useSDK() + const [loading, setLoading] = createSignal(null) + + async function handleToggle(name: string) { + if (loading() !== null) return + setLoading(name) + try { + await local.mcp.toggle(name) + const status = await sdk.client.mcp.status() + if (status.data) sync.set("mcp", status.data) + } catch (error) { + console.error("Failed to toggle MCP:", error) + } finally { + setLoading(null) + } + } + // Sort MCP servers alphabetically for consistent display order const mcpEntries = createMemo(() => Object.entries(sync.data.mcp).sort(([a], [b]) => a.localeCompare(b))) @@ -130,7 +150,7 @@ export function Sidebar(props: { sessionID: string; overlay?: boolean }) { {([key, item]) => ( - + handleToggle(key)}> • - + {key}{" "} + + Loading… + Connected {(val) => {val().error}} Disabled From 49841df46d80e4034b803bf69e3f66f1c3cfd968 Mon Sep 17 00:00:00 2001 From: Ariane Emory Date: Sat, 7 Mar 2026 10:36:46 -0500 Subject: [PATCH 2/2] Replace console.error with Log.Default.error in sidebar Use the proper logging utility instead of console.error for the MCP toggle error. --- .../opencode/src/cli/cmd/tui/routes/session/sidebar.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/sidebar.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/sidebar.tsx index f2ff2938996..97db280c9bf 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/sidebar.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/sidebar.tsx @@ -13,6 +13,7 @@ import { useKV } from "../../context/kv" import { useLocal } from "@tui/context/local" import { useSDK } from "@tui/context/sdk" import { TodoItem } from "../../component/todo-item" +import { Log } from "@/util/log" export function Sidebar(props: { sessionID: string; overlay?: boolean }) { const sync = useSync() @@ -41,7 +42,11 @@ export function Sidebar(props: { sessionID: string; overlay?: boolean }) { const status = await sdk.client.mcp.status() if (status.data) sync.set("mcp", status.data) } catch (error) { - console.error("Failed to toggle MCP:", error) + Log.Default.error("Failed to toggle MCP", { + error: error instanceof Error ? error.message : String(error), + name: error instanceof Error ? error.name : undefined, + stack: error instanceof Error ? error.stack : undefined, + }) } finally { setLoading(null) }