diff --git a/src/components/mcp/McpFormModal.tsx b/src/components/mcp/McpFormModal.tsx index 4d27cd6..63d865e 100644 --- a/src/components/mcp/McpFormModal.tsx +++ b/src/components/mcp/McpFormModal.tsx @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import React, { useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import { X, Save, AlertCircle, ChevronDown, ChevronUp } from "lucide-react"; import { McpServer, McpServerSpec } from "../../types"; @@ -117,6 +117,31 @@ const McpFormModal: React.FC = ({ // 判断是否使用 TOML 格式 const useToml = appType === "codex"; + const wizardInitialSpec = useMemo(() => { + const fallback = initialData?.server; + if (!formConfig.trim()) { + return fallback; + } + + if (useToml) { + try { + return tomlToMcpServer(formConfig); + } catch { + return fallback; + } + } + + try { + const parsed = JSON.parse(formConfig); + if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) { + return parsed as McpServerSpec; + } + return fallback; + } catch { + return fallback; + } + }, [formConfig, initialData, useToml]); + // 预设选择状态(仅新增模式显示;-1 表示自定义) const [selectedPreset, setSelectedPreset] = useState( isEditing ? null : -1, @@ -661,6 +686,8 @@ const McpFormModal: React.FC = ({ onClose={() => setIsWizardOpen(false)} onApply={handleWizardApply} onNotify={onNotify} + initialTitle={formId} + initialServer={wizardInitialSpec} /> ); diff --git a/src/components/mcp/McpWizardModal.tsx b/src/components/mcp/McpWizardModal.tsx index 1239ce2..984b57f 100644 --- a/src/components/mcp/McpWizardModal.tsx +++ b/src/components/mcp/McpWizardModal.tsx @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import React, { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { X, Save } from "lucide-react"; import { McpServerSpec } from "../../types"; @@ -13,6 +13,8 @@ interface McpWizardModalProps { type: "success" | "error", duration?: number, ) => void; + initialTitle?: string; + initialServer?: McpServerSpec; } /** @@ -72,6 +74,8 @@ const McpWizardModal: React.FC = ({ onClose, onApply, onNotify, + initialTitle, + initialServer, }) => { const { t } = useTranslation(); const [wizardType, setWizardType] = useState<"stdio" | "http">("stdio"); @@ -162,6 +166,55 @@ const McpWizardModal: React.FC = ({ } }; + useEffect(() => { + if (!isOpen) return; + + const title = initialTitle ?? ""; + setWizardTitle(title); + + const resolvedType = + initialServer?.type ?? + (initialServer?.url ? "http" : "stdio"); + + setWizardType(resolvedType); + + if (resolvedType === "http") { + setWizardUrl(initialServer?.url ?? ""); + const headersCandidate = initialServer?.headers; + const headers = + headersCandidate && typeof headersCandidate === "object" + ? headersCandidate + : undefined; + setWizardHeaders( + headers + ? Object.entries(headers) + .map(([k, v]) => `${k}: ${v ?? ""}`) + .join("\n") + : "", + ); + setWizardCommand(""); + setWizardArgs(""); + setWizardEnv(""); + return; + } + + setWizardCommand(initialServer?.command ?? ""); + const argsValue = initialServer?.args; + setWizardArgs(Array.isArray(argsValue) ? argsValue.join("\n") : ""); + const envCandidate = initialServer?.env; + const env = + envCandidate && typeof envCandidate === "object" ? envCandidate : undefined; + setWizardEnv( + env + ? Object.entries(env) + .map(([k, v]) => `${k}=${v ?? ""}`) + .join("\n") + : "", + ); + setWizardUrl(""); + setWizardHeaders(""); + }, [isOpen]); + if (!isOpen) return null; const preview = generatePreview();