feat(mcp): enhance wizard with title field and optimize placeholders

- Add MCP title field to wizard (required)
- Remove working directory (cwd) field and related logic
- Update wizard callback to return both title and JSON
- Optimize placeholder text for better user guidance:
  - Command: "npx or uvx"
  - Args: "arg1\narg2"
  - Env: "KEY1=value1\nKEY2=value2"
  - Headers: "Authorization: Bearer your_token_here\n..."
- Simplify args label by removing "(one per line)" hint
- Update parent component to handle title from wizard
This commit is contained in:
Jason
2025-10-11 11:43:32 +08:00
parent 2a60d20841
commit a6ee3ba35f
4 changed files with 35 additions and 41 deletions

View File

@@ -152,7 +152,8 @@ const McpFormModal: React.FC<McpFormModalProps> = ({
setJsonError(""); setJsonError("");
}; };
const handleWizardApply = (json: string) => { const handleWizardApply = (title: string, json: string) => {
setFormId(title);
setFormJson(json); setFormJson(json);
setJsonError(validateJson(json)); setJsonError(validateJson(json));
}; };

View File

@@ -7,7 +7,7 @@ import { isLinux } from "../../lib/platform";
interface McpWizardModalProps { interface McpWizardModalProps {
isOpen: boolean; isOpen: boolean;
onClose: () => void; onClose: () => void;
onApply: (json: string) => void; onApply: (title: string, json: string) => void;
onNotify?: ( onNotify?: (
message: string, message: string,
type: "success" | "error", type: "success" | "error",
@@ -75,10 +75,10 @@ const McpWizardModal: React.FC<McpWizardModalProps> = ({
}) => { }) => {
const { t } = useTranslation(); const { t } = useTranslation();
const [wizardType, setWizardType] = useState<"stdio" | "http">("stdio"); const [wizardType, setWizardType] = useState<"stdio" | "http">("stdio");
const [wizardTitle, setWizardTitle] = useState("");
// stdio 字段 // stdio 字段
const [wizardCommand, setWizardCommand] = useState(""); const [wizardCommand, setWizardCommand] = useState("");
const [wizardArgs, setWizardArgs] = useState(""); const [wizardArgs, setWizardArgs] = useState("");
const [wizardCwd, setWizardCwd] = useState("");
const [wizardEnv, setWizardEnv] = useState(""); const [wizardEnv, setWizardEnv] = useState("");
// http 字段 // http 字段
const [wizardUrl, setWizardUrl] = useState(""); const [wizardUrl, setWizardUrl] = useState("");
@@ -102,10 +102,6 @@ const McpWizardModal: React.FC<McpWizardModalProps> = ({
.filter((s) => s.length > 0); .filter((s) => s.length > 0);
} }
if (wizardCwd.trim()) {
config.cwd = wizardCwd.trim();
}
if (wizardEnv.trim()) { if (wizardEnv.trim()) {
const env = parseEnvText(wizardEnv); const env = parseEnvText(wizardEnv);
if (Object.keys(env).length > 0) { if (Object.keys(env).length > 0) {
@@ -129,6 +125,10 @@ const McpWizardModal: React.FC<McpWizardModalProps> = ({
}; };
const handleApply = () => { const handleApply = () => {
if (!wizardTitle.trim()) {
onNotify?.(t("mcp.error.idRequired"), "error", 3000);
return;
}
if (wizardType === "stdio" && !wizardCommand.trim()) { if (wizardType === "stdio" && !wizardCommand.trim()) {
onNotify?.(t("mcp.error.commandRequired"), "error", 3000); onNotify?.(t("mcp.error.commandRequired"), "error", 3000);
return; return;
@@ -139,16 +139,16 @@ const McpWizardModal: React.FC<McpWizardModalProps> = ({
} }
const json = generatePreview(); const json = generatePreview();
onApply(json); onApply(wizardTitle.trim(), json);
handleClose(); handleClose();
}; };
const handleClose = () => { const handleClose = () => {
// 重置表单 // 重置表单
setWizardType("stdio"); setWizardType("stdio");
setWizardTitle("");
setWizardCommand(""); setWizardCommand("");
setWizardArgs(""); setWizardArgs("");
setWizardCwd("");
setWizardEnv(""); setWizardEnv("");
setWizardUrl(""); setWizardUrl("");
setWizardHeaders(""); setWizardHeaders("");
@@ -247,6 +247,21 @@ const McpWizardModal: React.FC<McpWizardModalProps> = ({
</div> </div>
</div> </div>
{/* Title */}
<div>
<label className="mb-1 block text-sm font-medium text-gray-900 dark:text-gray-100">
{t("mcp.form.title")} <span className="text-red-500">*</span>
</label>
<input
type="text"
value={wizardTitle}
onChange={(e) => setWizardTitle(e.target.value)}
onKeyDown={handleKeyDown}
placeholder={t("mcp.form.titlePlaceholder")}
className="w-full rounded-lg border border-gray-200 px-3 py-2 text-sm font-mono focus:outline-none focus:ring-2 focus:ring-emerald-500/20 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-100"
/>
</div>
{/* Stdio 类型字段 */} {/* Stdio 类型字段 */}
{wizardType === "stdio" && ( {wizardType === "stdio" && (
<> <>
@@ -280,21 +295,6 @@ const McpWizardModal: React.FC<McpWizardModalProps> = ({
/> />
</div> </div>
{/* CWD */}
<div>
<label className="mb-1 block text-sm font-medium text-gray-900 dark:text-gray-100">
{t("mcp.wizard.cwd")}
</label>
<input
type="text"
value={wizardCwd}
onChange={(e) => setWizardCwd(e.target.value)}
onKeyDown={handleKeyDown}
placeholder={t("mcp.wizard.cwdPlaceholder")}
className="w-full rounded-lg border border-gray-200 px-3 py-2 text-sm font-mono focus:outline-none focus:ring-2 focus:ring-emerald-500/20 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-100"
/>
</div>
{/* Env */} {/* Env */}
<div> <div>
<label className="mb-1 block text-sm font-medium text-gray-900 dark:text-gray-100"> <label className="mb-1 block text-sm font-medium text-gray-900 dark:text-gray-100">
@@ -350,7 +350,6 @@ const McpWizardModal: React.FC<McpWizardModalProps> = ({
{/* Preview */} {/* Preview */}
{(wizardCommand || {(wizardCommand ||
wizardArgs || wizardArgs ||
wizardCwd ||
wizardEnv || wizardEnv ||
wizardUrl || wizardUrl ||
wizardHeaders) && ( wizardHeaders) && (

View File

@@ -292,24 +292,21 @@
"hint": "Quickly configure MCP server and auto-generate JSON configuration", "hint": "Quickly configure MCP server and auto-generate JSON configuration",
"type": "Type", "type": "Type",
"command": "Command", "command": "Command",
"commandPlaceholder": "uvx", "commandPlaceholder": "npx or uvx",
"args": "Arguments (one per line)", "args": "Arguments",
"argsPlaceholder": "mcp-server-fetch\n--config config.json", "argsPlaceholder": "arg1\narg2",
"cwd": "Working Directory",
"cwdPlaceholder": "/path/to/project",
"env": "Environment Variables", "env": "Environment Variables",
"envPlaceholder": "KEY=VALUE\n(one per line)", "envPlaceholder": "KEY1=value1\nKEY2=value2",
"url": "URL", "url": "URL",
"urlPlaceholder": "https://api.example.com/mcp", "urlPlaceholder": "https://api.example.com/mcp",
"urlRequired": "Please enter URL", "urlRequired": "Please enter URL",
"headers": "Headers (optional)", "headers": "Headers (optional)",
"headersPlaceholder": "Authorization: Bearer token\nContent-Type: application/json", "headersPlaceholder": "Authorization: Bearer your_token_here\nContent-Type: application/json",
"preview": "Configuration Preview", "preview": "Configuration Preview",
"apply": "Apply Configuration" "apply": "Apply Configuration"
}, },
"id": "Identifier (unique)", "id": "Identifier (unique)",
"type": "Type", "type": "Type",
"cwd": "Working Directory (optional)",
"command": "Command", "command": "Command",
"validateCommand": "Validate Command", "validateCommand": "Validate Command",
"args": "Args", "args": "Args",

View File

@@ -292,24 +292,21 @@
"hint": "快速配置 MCP 服务器,自动生成 JSON 配置", "hint": "快速配置 MCP 服务器,自动生成 JSON 配置",
"type": "类型", "type": "类型",
"command": "命令", "command": "命令",
"commandPlaceholder": "uvx", "commandPlaceholder": "npx 或 uvx",
"args": "参数(每行一个)", "args": "参数",
"argsPlaceholder": "mcp-server-fetch\n--config config.json", "argsPlaceholder": "arg1\narg2",
"cwd": "工作目录",
"cwdPlaceholder": "/path/to/project",
"env": "环境变量", "env": "环境变量",
"envPlaceholder": "KEY=VALUE\n(一行一个)", "envPlaceholder": "KEY1=value1\nKEY2=value2",
"url": "URL", "url": "URL",
"urlPlaceholder": "https://api.example.com/mcp", "urlPlaceholder": "https://api.example.com/mcp",
"urlRequired": "请输入 URL", "urlRequired": "请输入 URL",
"headers": "请求头(可选)", "headers": "请求头(可选)",
"headersPlaceholder": "Authorization: Bearer token\nContent-Type: application/json", "headersPlaceholder": "Authorization: Bearer your_token_here\nContent-Type: application/json",
"preview": "配置预览", "preview": "配置预览",
"apply": "应用配置" "apply": "应用配置"
}, },
"id": "标识 (唯一)", "id": "标识 (唯一)",
"type": "类型", "type": "类型",
"cwd": "工作目录 (可选)",
"command": "命令", "command": "命令",
"validateCommand": "校验命令", "validateCommand": "校验命令",
"args": "参数", "args": "参数",