From 156631c26343ba209501b64d584e4f1f57a8016d Mon Sep 17 00:00:00 2001 From: Syngnat Date: Wed, 10 Jun 2026 18:19:10 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat(ai):=20=E5=AE=8C=E5=96=84=20MC?= =?UTF-8?q?P=20=E6=96=B0=E5=A2=9E=E5=AD=97=E6=AE=B5=E5=A1=AB=E5=86=99?= =?UTF-8?q?=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 增加 command、args、env、timeout 的应填与勿填对照 - 抽取 MCP 字段指南卡片复用速查与表单说明 - 补充 AI 设置 MCP 区域渲染测试 --- .../src/components/ai/AIMCPFieldGuideCard.tsx | 71 +++++++++++++++++++ .../components/ai/AIMCPServerGuidePanel.tsx | 54 +++----------- .../ai/AISettingsMCPSection.test.tsx | 5 ++ .../components/ai/AISettingsMCPSection.tsx | 26 +++---- frontend/src/utils/mcpServerGuidance.ts | 16 +++++ 5 files changed, 111 insertions(+), 61 deletions(-) create mode 100644 frontend/src/components/ai/AIMCPFieldGuideCard.tsx diff --git a/frontend/src/components/ai/AIMCPFieldGuideCard.tsx b/frontend/src/components/ai/AIMCPFieldGuideCard.tsx new file mode 100644 index 0000000..10a8f7d --- /dev/null +++ b/frontend/src/components/ai/AIMCPFieldGuideCard.tsx @@ -0,0 +1,71 @@ +import React from 'react'; + +import type { OverlayWorkbenchTheme } from '../../utils/overlayWorkbenchTheme'; +import type { MCPFieldGuide } from '../../utils/mcpServerGuidance'; +import { buildMCPFieldTone, buildMCPHintStyle } from './AIMCPHelpBlock'; + +interface AIMCPFieldGuideCardProps { + item: MCPFieldGuide; + cardBorder: string; + darkMode: boolean; + overlayTheme: OverlayWorkbenchTheme; + compact?: boolean; +} + +const AIMCPFieldGuideCard: React.FC = ({ + item, + cardBorder, + darkMode, + overlayTheme, + compact = false, +}) => { + const tone = buildMCPFieldTone(item.fieldState, darkMode); + return ( +
+
+
{item.title}
+ + {tone.label} + +
+
{item.summary}
+ {!compact &&
{item.detail}
} +
+ 应填: + {item.fill} +
+
+ 不要填: + {item.avoid} +
+ {item.example ? ( +
+ 示例值: + {' '} + {item.example} +
+ ) : null} +
+ ); +}; + +export default AIMCPFieldGuideCard; diff --git a/frontend/src/components/ai/AIMCPServerGuidePanel.tsx b/frontend/src/components/ai/AIMCPServerGuidePanel.tsx index 8739191..575c198 100644 --- a/frontend/src/components/ai/AIMCPServerGuidePanel.tsx +++ b/frontend/src/components/ai/AIMCPServerGuidePanel.tsx @@ -11,7 +11,8 @@ import { MCP_TROUBLESHOOTING_GUIDES, } from '../../utils/mcpServerGuidance'; import AIMCPCommandDraftPreview from './AIMCPCommandDraftPreview'; -import { buildMCPFieldTone, buildMCPHintStyle, mcpLabelStyle } from './AIMCPHelpBlock'; +import AIMCPFieldGuideCard from './AIMCPFieldGuideCard'; +import { buildMCPHintStyle, mcpLabelStyle } from './AIMCPHelpBlock'; interface AIMCPServerGuidePanelProps { cardBorder: string; @@ -73,48 +74,15 @@ const AIMCPServerGuidePanel: React.FC = ({ 如果看到某个参数名不知道该填什么,先看这一块;下面每个字段也都有更具体的示例和注意事项。
- {MCP_FIELD_GUIDES.map((item) => { - const tone = buildMCPFieldTone(item.fieldState, darkMode); - return ( -
-
-
{item.title}
- - {tone.label} - -
-
{item.summary}
-
{item.detail}
- {item.example ? ( -
- 示例值: - {' '} - {item.example} -
- ) : null} -
- ); - })} + {MCP_FIELD_GUIDES.map((item) => ( + + ))}
diff --git a/frontend/src/components/ai/AISettingsMCPSection.test.tsx b/frontend/src/components/ai/AISettingsMCPSection.test.tsx index 6b26a7b..12505e6 100644 --- a/frontend/src/components/ai/AISettingsMCPSection.test.tsx +++ b/frontend/src/components/ai/AISettingsMCPSection.test.tsx @@ -107,8 +107,13 @@ describe('AISettingsMCPSection', () => { expect(markup).toContain('env'); expect(markup).toContain('timeout'); expect(markup).toContain('只填程序名或启动器本身'); + expect(markup).toContain('应填:'); + expect(markup).toContain('填 npx、node、uvx、python,或某个 exe 的绝对路径'); + expect(markup).toContain('不要填整行命令,例如不要填 npx -y pkg --stdio'); expect(markup).toContain('把脚本名、模块名、开关参数拆开逐项填写'); + expect(markup).toContain('不要再填 npx/node/uvx/python'); expect(markup).toContain('给 MCP Server 传入 KEY=VALUE 形式的配置'); + expect(markup).toContain('不要写 export、set 或 $env: 前缀'); expect(markup).toContain('单次工具发现或调用最多等待多久'); expect(markup).toContain('常见启动方式模板'); expect(markup).toContain('npx 包'); diff --git a/frontend/src/components/ai/AISettingsMCPSection.tsx b/frontend/src/components/ai/AISettingsMCPSection.tsx index 8968b79..56fba2f 100644 --- a/frontend/src/components/ai/AISettingsMCPSection.tsx +++ b/frontend/src/components/ai/AISettingsMCPSection.tsx @@ -8,6 +8,7 @@ import { MCP_FIELD_GUIDES } from '../../utils/mcpServerGuidance'; import { MCP_SERVER_DRAFT_TEMPLATES } from '../../utils/mcpServerTemplates'; import type { OverlayWorkbenchTheme } from '../../utils/overlayWorkbenchTheme'; import AIMCPClientInstallPanel from './AIMCPClientInstallPanel'; +import AIMCPFieldGuideCard from './AIMCPFieldGuideCard'; import AIMCPServerCard from './AIMCPServerCard'; export type { MCPClientKey } from '../../utils/mcpClientInstallStatus'; @@ -98,25 +99,14 @@ const AISettingsMCPSection: React.FC = ({
{MCP_FIELD_GUIDES.filter((item) => ['command', 'args', 'env', 'timeout'].includes(item.key)).map((item) => ( -
-
{item.title}
-
{item.summary}
- {item.example ? ( -
- 例: - {' '} - {item.example} -
- ) : null} -
+ item={item} + cardBorder={cardBorder} + darkMode={darkMode} + overlayTheme={overlayTheme} + compact + /> ))}
diff --git a/frontend/src/utils/mcpServerGuidance.ts b/frontend/src/utils/mcpServerGuidance.ts index 6546556..ccbda12 100644 --- a/frontend/src/utils/mcpServerGuidance.ts +++ b/frontend/src/utils/mcpServerGuidance.ts @@ -5,6 +5,8 @@ export interface MCPFieldGuide { title: string; summary: string; detail: string; + fill: string; + avoid: string; fieldState: MCPFieldState; example?: string; } @@ -46,6 +48,8 @@ export const MCP_FIELD_GUIDES: MCPFieldGuide[] = [ title: '服务名称', summary: '保存后显示给你和 AI 看的名字。', detail: '按用途命名,建议写成 Browser、GitHub、Filesystem 这类一眼能认出的名字。', + fill: '这个 MCP 的用途名,例如 GitHub 或 Filesystem。', + avoid: '不要写 server、test、mcp1 这类看不出用途的名字。', fieldState: 'required', example: 'Filesystem / Browser / GitHub', }, @@ -54,6 +58,8 @@ export const MCP_FIELD_GUIDES: MCPFieldGuide[] = [ title: '启用状态', summary: '控制这条配置现在要不要参与工具发现和调用。', detail: '禁用只是不使用,不会删除下面填好的配置。', + fill: '临时不用选已禁用;确认要给 AI 用时选已启用。', + avoid: '不要用删除代替临时停用,避免重新配置 command、args、env。', fieldState: 'optional', example: '已启用 / 已禁用', }, @@ -62,6 +68,8 @@ export const MCP_FIELD_GUIDES: MCPFieldGuide[] = [ title: '传输方式', summary: 'GoNavi 用什么方式和这个 MCP Server 通信。', detail: '当前固定为 stdio,表示本机直接启动进程并通过标准输入输出交互。', + fill: '保持 stdio。', + avoid: '不要填写 HTTP、SSE、URL 或端口;当前新增入口不是远程 MCP URL 配置。', fieldState: 'fixed', example: 'stdio', }, @@ -70,6 +78,8 @@ export const MCP_FIELD_GUIDES: MCPFieldGuide[] = [ title: '启动命令', summary: '只填程序名或启动器本身。', detail: '常见是 npx、node、uvx、python;包名、脚本名和 --stdio 这类内容放到参数里。', + fill: '填 npx、node、uvx、python,或某个 exe 的绝对路径。', + avoid: '不要填整行命令,例如不要填 npx -y pkg --stdio。', fieldState: 'required', example: 'npx / node / uvx / python', }, @@ -78,6 +88,8 @@ export const MCP_FIELD_GUIDES: MCPFieldGuide[] = [ title: '命令参数', summary: '把脚本名、模块名、开关参数拆开逐项填写。', detail: '例如 npx -y pkg --stdio,要拆成 -y、pkg 和 --stdio;node server.js --stdio 要拆成 server.js 和 --stdio。', + fill: '逐项填 -y、包名、脚本名、-m、--stdio 等参数。', + avoid: '不要再填 npx/node/uvx/python,也不要把多个参数粘成一个长字符串。', fieldState: 'optional', example: '-y / @modelcontextprotocol/server-filesystem / --stdio / server.js', }, @@ -86,6 +98,8 @@ export const MCP_FIELD_GUIDES: MCPFieldGuide[] = [ title: '环境变量', summary: '给 MCP Server 传入 KEY=VALUE 形式的配置。', detail: '通常用来放 API Key、服务地址、工作目录等;每行一条,不要写 export。', + fill: '每行一条 KEY=VALUE,例如 GITHUB_TOKEN=...。', + avoid: '不要写 export、set 或 $env: 前缀;也不要把环境变量混进 command 或 args。', fieldState: 'optional', example: 'OPENAI_API_KEY=... / GITHUB_TOKEN=...', }, @@ -94,6 +108,8 @@ export const MCP_FIELD_GUIDES: MCPFieldGuide[] = [ title: '超时(秒)', summary: '单次工具发现或调用最多等待多久。', detail: '本机常规工具一般 20 秒就够,启动慢或远端链路再适当调大。', + fill: '常规填 20;启动慢时填 45 或 60。', + avoid: '不要随意填过小,3 秒以下很容易让工具发现误判失败。', fieldState: 'optional', example: '20 / 45 / 60', },