From 56da8799a7c3ec4c67cf5af6a569f65c90338e0f Mon Sep 17 00:00:00 2001 From: laiyanbiao66-debug Date: Sat, 30 May 2026 13:21:37 +0800 Subject: [PATCH] =?UTF-8?q?feat(settings):=20=E6=96=B0=E5=A2=9E=20MCP=20?= =?UTF-8?q?=E6=9C=8D=E5=8A=A1=E5=99=A8=E5=90=AF=E7=94=A8/=E7=A6=81?= =?UTF-8?q?=E7=94=A8=E5=BC=80=E5=85=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- desktop/src/App.tsx | 5 +++ desktop/src/i18n/en.ts | 2 ++ desktop/src/i18n/zh-CN.ts | 2 ++ desktop/src/protocol.ts | 1 + desktop/src/styles.css | 57 ++++++++++++++++++++++++++++++ desktop/src/ui/mcp-server-card.tsx | 18 ++++++++++ desktop/src/ui/settings.tsx | 6 ++++ src/cli/commands/desktop.ts | 43 ++++++++++++++++++++++ 8 files changed, 134 insertions(+) diff --git a/desktop/src/App.tsx b/desktop/src/App.tsx index 286a4868e..52f827448 100644 --- a/desktop/src/App.tsx +++ b/desktop/src/App.tsx @@ -1618,6 +1618,10 @@ function TabRuntime({ (raw: string) => sendRpc({ cmd: "mcp_specs_retry", raw }), [sendRpc], ); + const toggleMcpSpec = useCallback( + (raw: string) => sendRpc({ cmd: "mcp_specs_toggle", raw }), + [sendRpc], + ); const newChat = useCallback(() => { clearAbortDraft(); resetPromptHistoryNav(); @@ -2891,6 +2895,7 @@ function TabRuntime({ onRemoveMcpSpec={removeMcpSpec} onUpdateMcpSpec={updateMcpSpec} onRetryMcpSpec={retryMcpSpec} + onToggleMcpSpec={toggleMcpSpec} onReadMemory={(path) => sendRpc({ cmd: "memory_read", path })} /> ) : null} diff --git a/desktop/src/i18n/en.ts b/desktop/src/i18n/en.ts index 059e95b71..5e55f213c 100644 --- a/desktop/src/i18n/en.ts +++ b/desktop/src/i18n/en.ts @@ -658,6 +658,8 @@ export const en = { hideTools: "Hide tools", availableTools: "{count} available tools", noTools: "Connected, but this server did not expose callable tools", + toggleOn: "ON", + toggleOff: "OFF", }, jobs: { title: "Background jobs", diff --git a/desktop/src/i18n/zh-CN.ts b/desktop/src/i18n/zh-CN.ts index 11f80343c..98f54cdf3 100644 --- a/desktop/src/i18n/zh-CN.ts +++ b/desktop/src/i18n/zh-CN.ts @@ -655,6 +655,8 @@ export const zhCN: typeof en = { hideTools: "收起工具", availableTools: "{count} 个可用工具", noTools: "已连接,但该服务器未暴露可调用工具", + toggleOn: "开启", + toggleOff: "关闭", }, contextPanel: { reservedKey: "预留", diff --git a/desktop/src/protocol.ts b/desktop/src/protocol.ts index 4f5414f7e..882b93a62 100644 --- a/desktop/src/protocol.ts +++ b/desktop/src/protocol.ts @@ -622,6 +622,7 @@ export type OutgoingCommand = { tabId?: string } & ( | { cmd: "mcp_import_servers"; servers: ImportedMcpServer[] } | { cmd: "mcp_specs_update"; raw: string; server: ImportedMcpServer } | { cmd: "mcp_specs_retry"; raw: string } + | { cmd: "mcp_specs_toggle"; raw: string } | { cmd: "skills_get" } | { cmd: "skill_run"; name: string; args?: string } | { cmd: "jobs_list" } diff --git a/desktop/src/styles.css b/desktop/src/styles.css index 73b51e078..9d8ff58d3 100644 --- a/desktop/src/styles.css +++ b/desktop/src/styles.css @@ -5718,6 +5718,63 @@ html:not([data-platform="macos"]) .cmdk-row .kb .shortcut kbd[data-key="mod"] { .mcp-server-card .rot { transform: rotate(180deg); } +.mcp-toggle { + display: flex; + align-items: center; + gap: 6px; + padding: 4px 8px; + border: 1px solid var(--border); + border-radius: 16px; + cursor: pointer; + transition: all 0.2s ease; +} +.mcp-toggle.on { + background: color-mix(in srgb, var(--success) 15%, transparent); + border-color: color-mix(in srgb, var(--success) 40%, var(--border)); +} +.mcp-toggle.off { + background: var(--bg-2); + border-color: var(--border); +} +.mcp-toggle:hover { + border-color: color-mix(in srgb, var(--fg) 30%, var(--border)); +} +.mcp-toggle-track { + position: relative; + width: 28px; + height: 16px; + border-radius: 8px; + background: var(--bg-3); + transition: background 0.2s ease; +} +.mcp-toggle.on .mcp-toggle-track { + background: var(--success); +} +.mcp-toggle.off .mcp-toggle-track { + background: var(--muted); +} +.mcp-toggle-thumb { + position: absolute; + top: 2px; + left: 2px; + width: 12px; + height: 12px; + border-radius: 50%; + background: white; + transition: transform 0.2s ease; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2); +} +.mcp-toggle.on .mcp-toggle-thumb { + transform: translateX(12px); +} +.mcp-toggle.off .mcp-toggle-thumb { + transform: translateX(0); +} +.mcp-toggle-label { + font-size: 11px; + font-weight: 500; + color: var(--fg); +} .mcp-tools-detail { margin-top: 10px; padding: 10px; diff --git a/desktop/src/ui/mcp-server-card.tsx b/desktop/src/ui/mcp-server-card.tsx index 88a4fb44c..b15b86efe 100644 --- a/desktop/src/ui/mcp-server-card.tsx +++ b/desktop/src/ui/mcp-server-card.tsx @@ -46,12 +46,14 @@ export function McpServerCard({ onEdit, onRetry, onRemove, + onToggle, }: { spec: McpSpecInfo; mode?: McpServerCardMode; onEdit?: (spec: McpSpecInfo) => void; onRetry?: (raw: string) => void; onRemove?: (raw: string) => void; + onToggle?: (raw: string) => void; }) { const [toolsOpen, setToolsOpen] = useState(false); const [detailOpen, setDetailOpen] = useState(false); @@ -66,6 +68,7 @@ export function McpServerCard({ spec.status === "failed" && spec.statusReason ? `${statusText}\n${spec.statusReason}` : statusText; + const isDisabled = spec.status === "disabled"; return (
@@ -85,6 +88,21 @@ export function McpServerCard({
+ {mode === "settings" && onToggle && !spec.parseError ? ( + + ) : null} {canExpandTools ? (