From f4b8aed29a13ba58a4be9d8e0723d98c40046486 Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 14 Nov 2025 15:47:04 +0800 Subject: [PATCH] refactor(frontend): remove MCP import functionality for v3.7.0 Auto-migration at startup is sufficient for upgrading from v3.6.x. Manual import adds unnecessary complexity since: - Gemini MCP support launches with v3.7.0 (no legacy data) - Existing Claude/Codex MCP configs are auto-migrated on first run - All MCP management should happen within CC Switch Changes: - Remove McpImportDialog component - Remove "Import" button from UnifiedMcpPanel - Remove import-related i18n translations (en/zh) - Simplify user experience with single management interface Note: Backend import commands (import_mcp_from_*) remain for backward compatibility but are no longer exposed in UI. --- src/components/mcp/McpImportDialog.tsx | 178 ------------------------- src/components/mcp/UnifiedMcpPanel.tsx | 27 +--- src/i18n/locales/en.json | 10 -- src/i18n/locales/zh.json | 10 -- 4 files changed, 2 insertions(+), 223 deletions(-) delete mode 100644 src/components/mcp/McpImportDialog.tsx diff --git a/src/components/mcp/McpImportDialog.tsx b/src/components/mcp/McpImportDialog.tsx deleted file mode 100644 index 6c1572c..0000000 --- a/src/components/mcp/McpImportDialog.tsx +++ /dev/null @@ -1,178 +0,0 @@ -import React, { useState } from "react"; -import { useTranslation } from "react-i18next"; -import { toast } from "sonner"; -import { Download, FileJson, FileCode, Sparkles } from "lucide-react"; -import { Button } from "@/components/ui/button"; -import { - Dialog, - DialogContent, - DialogHeader, - DialogTitle, - DialogFooter, -} from "@/components/ui/dialog"; -import { mcpApi } from "@/lib/api"; -import type { AppId } from "@/lib/api/types"; - -interface McpImportDialogProps { - open: boolean; - onOpenChange: (open: boolean) => void; - onImportComplete?: () => void; -} - -/** - * MCP 导入对话框 - * 支持从 Claude/Codex/Gemini 的 live 配置导入 MCP 服务器 - */ -const McpImportDialog: React.FC = ({ - open, - onOpenChange, - onImportComplete, -}) => { - const { t } = useTranslation(); - const [importing, setImporting] = useState(false); - const [selectedSource, setSelectedSource] = useState(null); - - const handleImport = async (source: AppId) => { - setImporting(true); - setSelectedSource(source); - - try { - let count = 0; - - switch (source) { - case "claude": - count = await mcpApi.importFromClaude(); - break; - case "codex": - count = await mcpApi.importFromCodex(); - break; - case "gemini": - count = await mcpApi.importFromGemini(); - break; - } - - if (count > 0) { - toast.success(t("mcp.unifiedPanel.import.success", { count })); - onImportComplete?.(); - onOpenChange(false); - } else { - toast.info(t("mcp.unifiedPanel.import.noServersFound")); - } - } catch (error) { - toast.error(t("common.error"), { - description: String(error), - }); - } finally { - setImporting(false); - setSelectedSource(null); - } - }; - - const importSources = [ - { - id: "claude" as AppId, - name: t("mcp.unifiedPanel.apps.claude"), - description: t("mcp.unifiedPanel.import.fromClaudeDesc"), - icon: FileJson, - color: "text-blue-600 dark:text-blue-400", - bgColor: "bg-blue-100 dark:bg-blue-900/30", - }, - { - id: "codex" as AppId, - name: t("mcp.unifiedPanel.apps.codex"), - description: t("mcp.unifiedPanel.import.fromCodexDesc"), - icon: FileCode, - color: "text-green-600 dark:text-green-400", - bgColor: "bg-green-100 dark:bg-green-900/30", - }, - { - id: "gemini" as AppId, - name: t("mcp.unifiedPanel.apps.gemini"), - description: t("mcp.unifiedPanel.import.fromGeminiDesc"), - icon: Sparkles, - color: "text-purple-600 dark:text-purple-400", - bgColor: "bg-purple-100 dark:bg-purple-900/30", - }, - ]; - - return ( - - - - {t("mcp.unifiedPanel.import.title")} - - -
-

- {t("mcp.unifiedPanel.import.description")} -

- -
- {importSources.map((source) => { - const Icon = source.icon; - const isImporting = importing && selectedSource === source.id; - - return ( - - ); - })} -
-
- - - - -
-
- ); -}; - -export default McpImportDialog; diff --git a/src/components/mcp/UnifiedMcpPanel.tsx b/src/components/mcp/UnifiedMcpPanel.tsx index 6afdb96..fed80ed 100644 --- a/src/components/mcp/UnifiedMcpPanel.tsx +++ b/src/components/mcp/UnifiedMcpPanel.tsx @@ -1,6 +1,6 @@ import React, { useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; -import { Plus, Server, Check, RefreshCw, Download } from "lucide-react"; +import { Plus, Server, Check, RefreshCw } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Dialog, @@ -14,7 +14,6 @@ import { useAllMcpServers, useToggleMcpApp, useSyncAllMcpServers } from "@/hooks import type { McpServer } from "@/types"; import type { AppId } from "@/lib/api/types"; import McpFormModal from "./McpFormModal"; -import McpImportDialog from "./McpImportDialog"; import { ConfirmDialog } from "../ConfirmDialog"; import { useDeleteMcpServer } from "@/hooks/useMcp"; import { Edit3, Trash2 } from "lucide-react"; @@ -37,7 +36,6 @@ const UnifiedMcpPanel: React.FC = ({ }) => { const { t } = useTranslation(); const [isFormOpen, setIsFormOpen] = useState(false); - const [isImportOpen, setIsImportOpen] = useState(false); const [editingId, setEditingId] = useState(null); const [confirmDialog, setConfirmDialog] = useState<{ isOpen: boolean; @@ -47,7 +45,7 @@ const UnifiedMcpPanel: React.FC = ({ } | null>(null); // Queries and Mutations - const { data: serversMap, isLoading, refetch } = useAllMcpServers(); + const { data: serversMap, isLoading } = useAllMcpServers(); const toggleAppMutation = useToggleMcpApp(); const deleteServerMutation = useDeleteMcpServer(); const syncAllMutation = useSyncAllMcpServers(); @@ -128,11 +126,6 @@ const UnifiedMcpPanel: React.FC = ({ setEditingId(null); }; - const handleImportComplete = () => { - // Refresh the servers list after import - refetch(); - }; - return ( <> @@ -141,15 +134,6 @@ const UnifiedMcpPanel: React.FC = ({
{t("mcp.unifiedPanel.title")}
-