From c6a062f64a3b3b224bae834d03ccae5afd1750ab Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 8 Oct 2025 22:35:07 +0800 Subject: [PATCH] feat(mcp): implement MCP management panel (list, form, templates) - Add McpPanel with enable toggle, server list and add/edit form - Quick template: mcp-fetch (uvx mcp-server-fetch) - Command validation UI and open ~/.claude shortcut - Wire MCP button in App to open panel --- src/App.tsx | 10 +- src/components/mcp/McpPanel.tsx | 406 ++++++++++++++++++++++++++++++++ 2 files changed, 413 insertions(+), 3 deletions(-) create mode 100644 src/components/mcp/McpPanel.tsx diff --git a/src/App.tsx b/src/App.tsx index 09b8214..8a5ef6d 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -10,6 +10,7 @@ import { AppSwitcher } from "./components/AppSwitcher"; import SettingsModal from "./components/SettingsModal"; import { UpdateBadge } from "./components/UpdateBadge"; import { Plus, Settings, Moon, Sun } from "lucide-react"; +import McpPanel from "./components/mcp/McpPanel"; import { buttonStyles } from "./lib/styles"; import { useDarkMode } from "./hooks/useDarkMode"; import { extractErrorMessage } from "./utils/errorUtils"; @@ -36,6 +37,7 @@ function App() { onConfirm: () => void; } | null>(null); const [isSettingsOpen, setIsSettingsOpen] = useState(false); + const [isMcpOpen, setIsMcpOpen] = useState(false); const timeoutRef = useRef | null>(null); // 设置通知的辅助函数 @@ -307,9 +309,7 @@ function App() { + + + {/* Content */} +
+ {/* Left: status & list */} +
+
+
+
+ {t("mcp.enableProject")} +
+
+ {status?.settingsLocalPath} +
+
+
+ + {/* Right: form */} +
+
+ {editingId ? t("mcp.editServer") : t("mcp.addServer")} +
+ +
+
+ + setForm((s) => ({ ...s, id: e.target.value }))} + /> +
+ +
+
+ + +
+
+ + setForm((s) => ({ ...s, cwd: e.target.value }))} + /> +
+
+ +
+ +
+ setForm((s) => ({ ...s, command: e.target.value }))} + /> + +
+
+ +
+ + setFormArgsText(e.target.value)} + /> +
+ +
+ +