diff --git a/frontend/src/components/ai/AIMCPServerCard.test.tsx b/frontend/src/components/ai/AIMCPServerCard.test.tsx index 9c02f29..f8b5199 100644 --- a/frontend/src/components/ai/AIMCPServerCard.test.tsx +++ b/frontend/src/components/ai/AIMCPServerCard.test.tsx @@ -36,6 +36,10 @@ describe('AIMCPServerCard', () => { expect(markup).toContain('启动命令只填可执行程序本身'); expect(markup).toContain('推荐填写顺序'); expect(markup).toContain('小白用户可以按这个顺序填'); + expect(markup).toContain('字段速查'); + expect(markup).toContain('保存后显示给你和 AI 看的名字'); + expect(markup).toContain('当前固定为 stdio'); + expect(markup).toContain('单次工具发现或调用最多等待多久'); expect(markup).toContain('必填'); expect(markup).toContain('可选'); expect(markup).toContain('固定'); @@ -52,6 +56,9 @@ describe('AIMCPServerCard', () => { expect(markup).toContain('测试工具发现'); expect(markup).toContain('不会保存配置'); expect(markup).toContain('测试通过后,上方会显示这条服务实际发现到的工具'); + expect(markup).toContain('默认 20 秒'); + expect(markup).toContain('稍宽松 45 秒'); + expect(markup).toContain('慢启动 60 秒'); expect(markup).toContain('node server.js --stdio'); }); }); diff --git a/frontend/src/components/ai/AIMCPServerCard.tsx b/frontend/src/components/ai/AIMCPServerCard.tsx index 9bdd724..1eb4f11 100644 --- a/frontend/src/components/ai/AIMCPServerCard.tsx +++ b/frontend/src/components/ai/AIMCPServerCard.tsx @@ -63,6 +63,64 @@ const MCP_COMMAND_EXAMPLES = [ 'python -m your_mcp_server', ]; +const MCP_FIELD_GUIDES: Array<{ + key: string; + title: string; + summary: string; + detail: string; + fieldState: 'required' | 'optional' | 'fixed'; +}> = [ + { + key: 'name', + title: '服务名称', + summary: '保存后显示给你和 AI 看的名字。', + detail: '按用途命名,建议写成 Browser、GitHub、Filesystem 这类一眼能认出的名字。', + fieldState: 'required', + }, + { + key: 'enabled', + title: '启用状态', + summary: '控制这条配置现在要不要参与工具发现和调用。', + detail: '禁用只是不使用,不会删除下面填好的配置。', + fieldState: 'optional', + }, + { + key: 'transport', + title: '传输方式', + summary: 'GoNavi 用什么方式和这个 MCP Server 通信。', + detail: '当前固定为 stdio,表示本机直接启动进程并通过标准输入输出交互。', + fieldState: 'fixed', + }, + { + key: 'command', + title: '启动命令', + summary: '只填程序名或启动器本身。', + detail: '常见是 node、uvx、python;脚本名和 --stdio 这类内容放到参数里。', + fieldState: 'required', + }, + { + key: 'args', + title: '命令参数', + summary: '把脚本名、模块名、开关参数拆开逐项填写。', + detail: '例如 node server.js --stdio,要拆成 server.js 和 --stdio 两项。', + fieldState: 'optional', + }, + { + key: 'env', + title: '环境变量', + summary: '给 MCP Server 传入 KEY=VALUE 形式的配置。', + detail: '通常用来放 API Key、服务地址、工作目录等;每行一条,不要写 export。', + fieldState: 'optional', + }, + { + key: 'timeout', + title: '超时(秒)', + summary: '单次工具发现或调用最多等待多久。', + detail: '本机常规工具一般 20 秒就够,启动慢或远端链路再适当调大。', + fieldState: 'optional', + }, +]; + const quoteCommandPart = (value: string): string => { const text = String(value || '').trim(); if (!text) { @@ -193,6 +251,50 @@ export const AIMCPServerCard: React.FC = ({ +
+
字段速查
+
+ 如果看到某个参数名不知道该填什么,先看这一块;下面每个字段也都有更具体的示例和注意事项。 +
+
+ {MCP_FIELD_GUIDES.map((item) => { + const tone = buildFieldTone(item.fieldState, darkMode); + return ( +
+
+
{item.title}
+ + {tone.label} + +
+
{item.summary}
+
{item.detail}
+
+ ); + })} +
+
+
只有一条完整命令?
@@ -271,6 +373,32 @@ export const AIMCPServerCard: React.FC = ({ placeholder="超时(秒)" style={{ borderRadius: 10, background: inputBg, border: `1px solid ${cardBorder}` }} /> +
+ {[ + { label: '默认 20 秒', value: 20 }, + { label: '稍宽松 45 秒', value: 45 }, + { label: '慢启动 60 秒', value: 60 }, + ].map((option) => ( + + ))} +
diff --git a/frontend/src/components/ai/AISettingsMCPSection.tsx b/frontend/src/components/ai/AISettingsMCPSection.tsx index 7a9ba3b..5bb50a1 100644 --- a/frontend/src/components/ai/AISettingsMCPSection.tsx +++ b/frontend/src/components/ai/AISettingsMCPSection.tsx @@ -118,7 +118,7 @@ const AISettingsMCPSection: React.FC = ({
-
支持命令、参数、环境变量和超时,保存后会自动进入 AI 工具列表。
+
支持命令、参数、环境变量和超时;不确定怎么填时先看卡片里的“字段速查”,保存后会自动进入 AI 工具列表。
{mcpServers.length === 0 && (