diff --git a/frontend/src/components/ai/AIMCPClientInstallPanel.test.tsx b/frontend/src/components/ai/AIMCPClientInstallPanel.test.tsx index 1cd2273..62c62f8 100644 --- a/frontend/src/components/ai/AIMCPClientInstallPanel.test.tsx +++ b/frontend/src/components/ai/AIMCPClientInstallPanel.test.tsx @@ -63,13 +63,17 @@ describe('AIMCPClientInstallPanel', () => { ); expect(markup).toContain('这里是在把 GoNavi MCP 接入 Claude Code / Codex'); + expect(markup).toContain('给外部工具调用'); + expect(markup).toContain('这里的“安装”只会写入外部 CLI 的用户级 MCP 配置'); expect(markup).toContain('接入外部客户端'); - expect(markup).toContain('目标客户端'); + expect(markup).toContain('选择外部客户端(二选一)'); expect(markup).toContain('选择目标客户端'); expect(markup).toContain('写入接入配置'); expect(markup).toContain('重启目标客户端'); expect(markup).toContain('未接入'); expect(markup).toContain('需更新'); + expect(markup).toContain('外部工具接入状态:已存在旧配置,需更新'); + expect(markup).toContain('外部工具接入状态:未接入'); expect(markup).toContain('复制配置路径'); expect(markup).toContain('复制启动命令'); expect(markup).toContain('更新 Codex 接入配置'); @@ -127,7 +131,7 @@ describe('AIMCPClientInstallPanel', () => { />, ); - expect(markup).toContain('接入到 Claude Code'); + expect(markup).toContain('安装到 Claude Code(外部工具)'); expect(markup).toContain('CLI 检测:未检测到 claude'); expect(markup).toContain('未检测到本机 claude 命令'); expect(markup).toContain('已接入'); @@ -182,8 +186,8 @@ describe('AIMCPClientInstallPanel', () => { ); expect(markup).toContain('当前状态:已接入当前 GoNavi,无需重复操作'); - expect(markup).toContain('Claude Code 已接入当前 GoNavi'); - expect(markup).toContain('下面的主按钮会自动禁用,避免重复操作'); + expect(markup).toContain('Claude Code 已接入,无需重复安装'); + expect(markup).toContain('下面的主按钮会自动禁用,避免重复写入'); }); it('prefers the client that already matches current GoNavi over another stale installed record', () => { diff --git a/frontend/src/components/ai/AIMCPClientInstallPanel.tsx b/frontend/src/components/ai/AIMCPClientInstallPanel.tsx index c96aedc..2c23632 100644 --- a/frontend/src/components/ai/AIMCPClientInstallPanel.tsx +++ b/frontend/src/components/ai/AIMCPClientInstallPanel.tsx @@ -56,6 +56,19 @@ const getStatusTone = (status: AIMCPClientInstallStatus | undefined, darkMode: b }; }; +const getInstallStateLabel = (status: AIMCPClientInstallStatus | undefined) => { + if (status?.matchesCurrent) { + return '外部工具接入状态:已接入当前 GoNavi'; + } + if (status?.installed) { + return '外部工具接入状态:已存在旧配置,需更新'; + } + if (hasStatusIssue(status)) { + return '外部工具接入状态:读取失败'; + } + return '外部工具接入状态:未接入'; +}; + const resolveClientCommandName = (status: AIMCPClientInstallStatus | undefined) => { const command = String(status?.clientCommand || '').trim(); if (command) { @@ -116,12 +129,12 @@ const getSelectedClientStateLine = (status: AIMCPClientInstallStatus | undefined const resolveActionLabel = (status: AIMCPClientInstallStatus | undefined) => { const label = status?.displayName || '目标客户端'; if (status?.matchesCurrent) { - return `${label} 已接入当前 GoNavi`; + return `${label} 已接入,无需重复安装`; } if (status?.installed) { return `更新 ${label} 接入配置`; } - return `接入到 ${label}`; + return `安装到 ${label}(外部工具)`; }; const AIMCPClientInstallPanel: React.FC = ({ @@ -165,17 +178,17 @@ const AIMCPClientInstallPanel: React.FC = ({ }} >
- 这里是在把 GoNavi MCP 接入 Claude Code / Codex,不是给 GoNavi 自己安装插件。 + 这里是在把 GoNavi MCP 接入 Claude Code / Codex,给外部工具调用,不是给 GoNavi 自己安装插件。
- 你只需要选中 Claude Code 或 Codex 其中一个目标,GoNavi 就会把“如何启动当前这份 GoNavi MCP”的信息写入那个客户端的用户级配置文件,不会重装 GoNavi,也不会替换 GoNavi 自己的程序文件。 + 这里的“安装”只会写入外部 CLI 的用户级 MCP 配置,让它知道如何启动当前这份 GoNavi MCP;不会重装 GoNavi,也不会替换 GoNavi 自己的程序文件。
接入外部客户端
- 先选择 1 个目标客户端,再执行接入或更新。GoNavi 会自动把当前安装路径写入它的用户级 MCP 配置文件,不需要你自己找本机 exe,也不需要手动改配置。 + 先在 Claude Code 和 Codex 中选择 1 个目标客户端,再执行安装或更新。每个选项会直接显示是否已接入当前 GoNavi,已接入时主按钮会禁用,避免重复写入。
= ({
-
目标客户端
-
+
选择外部客户端(二选一)
+
{statuses.map((status) => { const client = status.client === 'codex' ? 'codex' : 'claude-code'; const active = selectedClient === client; @@ -238,6 +255,8 @@ const AIMCPClientInstallPanel: React.FC = ({