# Qwen Code 0.12.0 MCP & Extension Management 优化方案 ## 问题梳理与解决方案 根据钉钉文档《0.12.0 体验反馈》中提出的问题,本文件详细分析了每个问题的根本原因,并提供具体的解决方案和代码修改建议。 --- ## 文档问题概览 本文档共包含 **6 个问题** (3 个 P1 + 3 个 P2),分为两个主要部分: ### Part 1: MCP Management TUI (5 个问题) - **P1 级别**: 3 个问题 - **P2 级别**: 2 个细节问题 (共 10 个小点) ### Part 2: Extension Management TUI (1 个问题) - **P2 级别**: 1 个命令报错问题 ## 问题 1: 【P1】Auth 属于 manage 的一部分,应该加到 manage 里 ### 问题描述 - **现状**: 当前 MCP Management Dialog 中**没有 OAuth 认证功能**,用户必须使用 `/mcp auth ` 命令进行认证 - **问题**: - Auth 功能独立于 Manage Dialog 之外,用户体验割裂 - 需要记住命令行才能认证,不够直观 - MCP 管理对话框中只能查看服务器状态和工具,无法进行认证操作 - **文档建议**: Auth 应该整合到 manage dialog 中,在 UI 界面内完成所有 MCP 管理操作 ### 根本原因分析 #### 当前实现 ```typescript // packages/cli/src/ui/commands/mcpCommand.ts const mcpCommand: SlashCommand = { name: 'mcp', subCommands: [manageCommand, authCommand], // auth 作为独立子命令存在 action: async (): Promise => ({ type: 'dialog', dialog: 'mcp', // 默认打开管理对话框 }), }; ``` #### MCP Management Dialog 现状 ```typescript // packages/cli/src/ui/components/mcp/MCPManagementDialog.tsx // 当前的步骤类型 export const MCP_MANAGEMENT_STEPS = { SERVER_LIST: 'server-list', SERVER_DETAIL: 'server-detail', DISABLE_SCOPE_SELECT: 'disable-scope-select', TOOL_LIST: 'tool-list', TOOL_DETAIL: 'tool-detail', } as const; // ServerDetailStep 中的操作选项 const actions = [ { label: 'View tools', value: 'view-tools' }, { label: 'Reconnect', value: 'reconnect' }, { label: 'Enable/Disable', value: 'toggle-disable' }, // ❌ 缺少 'Authenticate' 选项 ]; ``` #### 问题分析 1. **UI 层面**: MCP Management Dialog 中没有认证相关的 UI 组件和操作入口 2. **代码层面**: OAuth 认证逻辑只在命令行 handler 中实现 (`mcpCommand.ts` 的 `authCommand`) 3. **体验层面**: 用户需要在 TUI 和 CLI 之间切换,无法在一个界面内完成所有操作 ### 解决方案 #### 方案 A: 在 MCP Dialog 中集成完整的 OAuth 认证功能 (强烈推荐) **核心思路**: - 在 Server Detail 页面添加 "Authenticate" 操作选项 - 复用现有的 `MCPOAuthProvider` 和 OAuth 流程 - 通过事件系统显示认证过程中的提示信息 **实现步骤**: ##### 1. 扩展 MCP_MANAGEMENT_STEPS ```typescript // packages/cli/src/ui/components/mcp/types.ts export const MCP_MANAGEMENT_STEPS = { SERVER_LIST: 'server-list', SERVER_DETAIL: 'server-detail', DISABLE_SCOPE_SELECT: 'disable-scope-select', TOOL_LIST: 'tool-list', TOOL_DETAIL: 'tool-detail', AUTHENTICATE: 'authenticate', // 新增:认证步骤 } as const; ``` ##### 2. 在 ServerDetailStep 中添加认证选项 ```typescript // packages/cli/src/ui/components/mcp/steps/ServerDetailStep.tsx type ServerAction = | 'view-tools' | 'reconnect' | 'toggle-disable' | 'authenticate'; // 新增 const actions = useMemo(() => { const result: Array<{ label: string; value: ServerAction }> = []; result.push({ label: t('View Tools'), value: 'view-tools' }); if (!server.isDisabled && server.status === MCPServerStatus.DISCONNECTED) { result.push({ label: t('Reconnect'), value: 'reconnect' }); } // 新增:显示认证选项的场景 const needsAuth = server.config.oauth?.enabled || server.status === MCPServerStatus.DISCONNECTED || server.errorMessage?.includes('401') || server.errorMessage?.includes('OAuth'); if (needsAuth) { result.push({ label: t('Authenticate'), value: 'authenticate', icon: '🔐', // 可选:添加图标增强视觉提示 }); } result.push({ label: server.isDisabled ? t('Enable') : t('Disable'), value: 'toggle-disable', }); return result; }, [server]); ``` ##### 3. 在 MCPManagementDialog 中实现认证逻辑 ```typescript // packages/cli/src/ui/components/mcp/MCPManagementDialog.tsx import { MCPOAuthProvider, MCPOAuthConfig } from '@qwen-code/qwen-code-core'; import { appEvents, AppEvent } from '../../utils/events.js'; // 新增:处理认证 const handleAuthenticate = useCallback(async () => { if (!config || !selectedServer) return; try { setIsLoading(true); // 显示开始认证提示 context.ui.addItem( { type: 'info', text: t("Starting OAuth authentication for '{{name}}'...", { name: selectedServer.name, }), }, Date.now() ); // 监听并显示认证过程中的消息 const displayListener = (message: string) => { context.ui.addItem({ type: 'info', text: message }, Date.now()); }; appEvents.on(AppEvent.OauthDisplayMessage, displayListener); // 准备 OAuth 配置 let oauthConfig: MCPOAuthConfig = selectedServer.config.oauth || { enabled: false }; // 执行认证 const authProvider = new MCPOAuthProvider(new MCPOAuthTokenStorage()); await authProvider.authenticate( selectedServer.name, oauthConfig, selectedServer.config.httpUrl || selectedServer.config.url ); // 认证成功 context.ui.addItem( { type: 'success', text: t("✓ Authentication successful for '{{name}}'", { name: selectedServer.name, }), }, Date.now() ); // 移除消息监听器 appEvents.off(AppEvent.OauthDisplayMessage, displayListener); // 重新加载服务器数据以更新状态 await reloadServers(); // 返回上一级 handleNavigateBack(); } catch (error) { debugLogger.error( `Authentication failed for '${selectedServer.name}':`, error ); context.ui.addItem( { type: 'error', text: t("✗ Authentication failed: {{error}}", { error: getErrorMessage(error), }), }, Date.now() ); } finally { setIsLoading(false); } }, [config, selectedServer, reloadServers, handleNavigateBack, context]); // 在 renderStepContent 中添加认证步骤的处理 case MCP_MANAGEMENT_STEPS.AUTHENTICATE: // 可以直接执行认证,或者显示一个确认对话框 void handleAuthenticate(); return {t('Authenticating...')}; ``` ##### 4. 更新 i18n 翻译文件 ```javascript // packages/cli/src/i18n/locales/en.js { 'Authenticate': 'Authenticate', 'Authenticate with OAuth': 'Authenticate with OAuth', "Starting OAuth authentication for '{{name}}'...": "Starting OAuth authentication for '{{name}}'...", "✓ Authentication successful for '{{name}}'": "✓ Authentication successful for '{{name}}'", "✗ Authentication failed: {{error}}": "✗ Authentication failed: {{error}}", } ``` **优点**: - ✅ 用户体验统一,所有 MCP 管理操作在一个界面完成 - ✅ 复用现有 OAuth 认证逻辑,开发成本低 - ✅ 直观的视觉反馈,认证过程透明 - ✅ 符合现代 UI/UX 设计原则 **缺点**: - ⚠️ 需要处理浏览器跳转和回调 (已有完善实现,风险低) #### 方案 B: 保留命令行但改进引导提示 如果某些场景下确实需要命令行认证 (如自动化脚本),可以: - 保留 `/mcp auth` 命令 - 在 Dialog 中提供快速复制的命令模板 - 添加"Copy Auth Command"按钮 但这会增加复杂性,不如方案 A 简洁。 --- ## 问题 2: 【P1】一些异常状态 ### 2.1 禁用之后还可以点击"查看工具",点进去是空的 #### 问题描述 - **现象**: MCP Server 被禁用后,仍然可以在 UI 中看到"查看工具"选项,点击进入后显示空列表 - **期望**: 禁用后的服务器不应该显示"查看工具"选项,或者应该给出明确的提示信息 #### 根本原因分析 当前代码逻辑: ```typescript // packages/cli/src/ui/components/mcp/steps/ServerDetailStep.tsx const actions = useMemo(() => { const result: Array<{ label: string; value: ServerAction }> = []; // 无论服务器是否禁用,都添加"查看工具"选项 result.push({ label: t('View Tools'), value: 'view-tools' }); if (server.status === 'disconnected') { result.push({ label: t('Reconnect'), value: 'reconnect' }); } result.push({ label: server.isDisabled ? t('Enable') : t('Disable'), value: 'toggle-disable', }); return result; }, [server]); ``` 问题在于: 1. 没有根据 `server.isDisabled` 状态过滤操作选项 2. 禁用服务器的工具列表获取逻辑可能存在问题 3. 缺少用户友好的提示信息 #### 解决方案 **方案 A: 禁用时隐藏"查看工具"选项 (推荐)** **代码修改**: ```typescript // packages/cli/src/ui/components/mcp/steps/ServerDetailStep.tsx const actions = useMemo(() => { const result: Array<{ label: string; value: ServerAction }> = []; // 只在服务器启用且已连接时显示"查看工具"选项 if (!server.isDisabled && server.status === MCPServerStatus.CONNECTED) { result.push({ label: t('View Tools'), value: 'view-tools', disabled: server.toolCount === 0, // 可选:工具数量为 0 时禁用 }); } // 禁用状态下显示提示信息 if (server.isDisabled) { result.push({ label: t('Enable to view tools'), value: 'toggle-disable', }); } else { if (server.status === MCPServerStatus.DISCONNECTED) { result.push({ label: t('Reconnect'), value: 'reconnect' }); } result.push({ label: t('Disable'), value: 'toggle-disable', }); } return result; }, [server]); ``` **同时修改 ToolListStep**: ```typescript // packages/cli/src/ui/components/mcp/steps/ToolListStep.tsx export const ToolListStep: React.FC = ({ tools, serverName, onSelect, onBack, }) => { // 添加禁用状态检查 if (tools.length === 0) { return ( {t('No tools available for this server.')} {/* 添加提示:服务器可能被禁用 */} {t('Note: This server may be disabled. Please enable it in the server settings.')} ); } // ... 其余代码保持不变 }; ``` **方案 B: 显示友好提示并阻止导航** 在 `MCPManagementDialog` 中添加拦截逻辑: ```typescript // packages/cli/src/ui/components/mcp/MCPManagementDialog.tsx const handleViewTools = useCallback(() => { if (!selectedServer) return; // 检查服务器是否禁用 if (selectedServer.isDisabled) { // 显示提示信息,不执行导航 debugLogger.warn( `Cannot view tools for disabled server '${selectedServer.name}'`, ); // 可选:在 UI 上显示临时消息 return; } // 检查是否有工具 if (selectedServer.toolCount === 0) { debugLogger.info(`No tools available for server '${selectedServer.name}'`); // 仍然可以进入查看,但会显示空状态提示 } handleNavigateToStep(MCP_MANAGEMENT_STEPS.TOOL_LIST); }, [selectedServer, handleNavigateToStep]); ``` #### 推荐方案:方案 A + ToolListStep 的提示增强 --- ### 2.2 禁用之后还能重新连接 #### 问题描述 - **现象**: MCP Server 被禁用后,仍然可以看到"重新连接"选项 - **期望**: 禁用之后应该没有"重新连接"入口 - **文档建议**: 禁用之后应该没有"重新连接"入口 #### 根本原因分析 当前代码逻辑: ```typescript // packages/cli/src/ui/components/mcp/steps/ServerDetailStep.tsx if (server.status === 'disconnected') { result.push({ label: t('Reconnect'), value: 'reconnect' }); } ``` 问题在于: 1. 只检查了连接状态,没有检查禁用状态 2. 禁用的服务器不应该允许重新连接操作 3. 逻辑上矛盾:既然禁用了就不应该尝试连接 #### 解决方案 **代码修改**: ```typescript // packages/cli/src/ui/components/mcp/steps/ServerDetailStep.tsx const actions = useMemo(() => { const result: Array<{ label: string; value: ServerAction }> = []; // View Tools 选项 if (!server.isDisabled && server.toolCount > 0) { result.push({ label: t('View Tools'), value: 'view-tools' }); } // Reconnect 选项:只在未禁用且断开连接时显示 if (!server.isDisabled && server.status === MCPServerStatus.DISCONNECTED) { result.push({ label: t('Reconnect'), value: 'reconnect' }); } // Enable/Disable 选项 result.push({ label: server.isDisabled ? t('Enable Server') : t('Disable Server'), value: 'toggle-disable', }); return result; }, [server]); ``` **同时在 ServerListStep 中添加视觉提示**: ```typescript // packages/cli/src/ui/components/mcp/steps/ServerListStep.tsx {server.isDisabled && ( {' '} {t('(disabled - no connection possible)')} )} ``` --- ### 问题 3: 【P1】禁用有个选择设置的 dialog,有点费解 #### 问题描述 - **现象**: 禁用服务器时会弹出一个对话框让用户选择禁用范围 (user/workspace) - **问题**: 这个选择让用户体验困惑,特别是当 MCP server 在项目级配置时,在用户级别禁用就有点费解 - **文档建议**: MCP server 在哪里,就在哪里禁用(如果 MCP server 在项目级,在用户级别禁用就有点费解) #### 根本原因分析 当前实现逻辑: ```typescript // packages/cli/src/ui/components/mcp/MCPManagementDialog.tsx const handleSelectDisableScope = useCallback( async (scope: 'user' | 'workspace') => { // 允许用户在 user 或 workspace 层面禁用服务器 // 即使服务器配置在 workspace 层面,也允许在 user 层面禁用 }, [config, selectedServer, handleNavigateBack, reloadServers], ); ``` 问题在于: 1. 用户可以跨 scope 禁用服务器,造成配置混乱 2. 不符合"在哪里配置就在哪里管理"的直觉 3. 增加了不必要的复杂性 #### 解决方案 **方案 A: 根据服务器来源自动确定禁用 scope (强烈推荐)** **核心思路**: - User 级别的配置 → 只能在 User 级别禁用 - Workspace 级别的配置 → 只能在 Workspace 级别禁用 - Extension 级别的配置 → 不允许禁用 (只能卸载扩展) **代码修改**: ```typescript // packages/cli/src/ui/components/mcp/MCPManagementDialog.tsx // 修改 handleDisable 函数 const handleDisable = useCallback(() => { if (!selectedServer) return; // 如果服务器已经被禁用,直接启用 if (selectedServer.isDisabled) { void handleEnableServer(); return; } // Extension 提供的服务器不允许禁用 if (selectedServer.source === 'extension') { debugLogger.warn( `Cannot disable extension-provided server '${selectedServer.name}'`, ); // 显示提示信息 return; } // 根据服务器 scope 直接禁用,不再询问 const scope = selectedServer.scope === 'extension' ? SettingScope.User : selectedServer.scope === 'workspace' ? SettingScope.Workspace : SettingScope.User; // 直接执行禁用操作 void executeDisable(scope); }, [selectedServer, handleEnableServer]); // 新增执行禁用函数 const executeDisable = useCallback( async (scope: SettingScope) => { if (!config || !selectedServer) return; try { setIsLoading(true); const settings = loadSettings(); const scopeSettings = settings.forScope(scope).settings; const currentExcluded = scopeSettings.mcp?.excluded || []; if (!currentExcluded.includes(selectedServer.name)) { const newExcluded = [...currentExcluded, selectedServer.name]; settings.setValue(scope, 'mcp.excluded', newExcluded); } const toolRegistry = config.getToolRegistry(); if (toolRegistry) { await toolRegistry.disableMcpServer(selectedServer.name); } await reloadServers(); handleNavigateBack(); } catch (error) { debugLogger.error( `Error disabling server '${selectedServer.name}':`, error, ); } finally { setIsLoading(false); } }, [config, selectedServer, reloadServers, handleNavigateBack], ); // 移除 DisableScopeSelectStep 相关的代码和导航逻辑 ``` **同时修改 UI 提示**: ```typescript // packages/cli/src/ui/components/mcp/steps/ServerDetailStep.tsx {t('Scope:')} {t(server.scope)} {server.source === 'extension' && ( {' '}({t('provided by {{name}}', { name: server.config.extensionName })}) )} // 禁用按钮文本根据 scope 调整 {server.isDisabled ? ( {t('Enable (will remove from exclusion list)')} ) : server.source === 'extension' ? ( {t('Cannot disable extension server')} ) : ( {t('Disable (in {{scope}})', { scope: server.scope })} )} ``` **方案 B: 保留选择但改进 UX** 如果确实需要支持跨 scope 禁用 (考虑到某些特殊场景),至少应该: 1. 明确显示当前服务器的配置位置 2. 说明不同选择的影响 3. 给出推荐选项 但这会增加复杂性,不如方案 A 简洁明了。 #### 推荐方案:方案 A --- ## 实施计划 --- ## 问题 6: 【P2】Extension Management - /extension manage 报错 ### 问题描述 - **现象**: 使用 `/extension manage` 命令时直接报错 - **期望**: 应该能正常打开 Extension Management Dialog ### 根本原因分析 #### 可能的原因 1. **命令拼写错误** (最可能) - 正确的命令是 `/extensions manage` (复数形式) - 用户可能输入了 `/extension manage` (单数形式) 2. **ExtensionManager 未正确初始化** ```typescript // packages/cli/src/ui/commands/extensionsCommand.ts#L103-108 async function listAction(_context: CommandContext, _args: string) { const extensionManager = context.services.config?.getExtensionManager(); if (!(extensionManager instanceof ExtensionManager)) { debugLogger.error( `Cannot ${context.invocation?.name} extensions in this environment`, ); return; // ❌ 这里直接返回,没有给用户任何提示 } // ... } ``` 3. **环境限制** - 某些环境下无法加载 ExtensionManager - 沙箱模式可能限制扩展管理功能 #### 当前错误处理问题 - 如果 `getExtensionManager()` 返回 null 或不是 ExtensionManager 实例 - 代码只是记录 debug 日志并静默返回 - **用户看不到任何错误提示**,只会感到困惑 ### 解决方案 #### 方案 A: 改进错误提示 (强烈推荐) **代码修改**: ```typescript // packages/cli/src/ui/commands/extensionsCommand.ts async function listAction(context: CommandContext, _args: string) { const extensionManager = context.services.config?.getExtensionManager(); if (!(extensionManager instanceof ExtensionManager)) { debugLogger.error( `Cannot ${context.invocation?.name} extensions in this environment`, ); // ✅ 添加用户友好的错误提示 context.ui.addItem( { type: MessageType.ERROR, text: t( 'Extension management is not available in the current environment. ' + 'This feature may not be supported in your current mode or configuration.', ), }, Date.now(), ); return; } return { type: 'dialog' as const, dialog: 'extensions_manage' as const, }; } ``` #### 方案 B: 检查命令拼写并给出提示 在命令解析层面添加提示: ```typescript // packages/cli/src/ui/commands/registry.ts 或相关位置 // 当检测到用户输入 '/extension'(单数) 时,给出提示 if (commandName === 'extension') { context.ui.addItem( { type: MessageType.INFO, text: t('Did you mean "/extensions"? (plural form)'), }, Date.now(), ); } ``` #### 方案 C: 同时支持单复数形式 为了用户体验,可以同时支持两种形式: ```typescript // packages/cli/src/ui/commands/extensionsCommand.ts export const extensionsCommand: SlashCommand = { name: 'extensions', // 主要命令 (复数) aliases: ['extension'], // ✅ 添加别名 (单数) get description() { return t('Manage extensions'); }, kind: CommandKind.BUILT_IN, subCommands: [ manageExtensionsCommand, installCommand, exploreExtensionsCommand, ], action: async (context, args) => manageExtensionsCommand.action!(context, args), }; ``` **注意**: 需要检查 SlashCommand 类型定义是否支持 `aliases` 属性 ### 推荐方案 **采用方案 A + 方案 C**: 1. 改进错误提示,让用户知道发生了什么 2. 如果可能,同时支持单复数形式 --- ## 实施计划 ### Phase 1: 修复异常状态问题 (优先级:高) 1. **修复问题 2.1**: 禁用后可查看工具 - 修改 `ServerDetailStep.tsx` 的操作列表逻辑 - 修改 `ToolListStep.tsx` 添加友好提示 - 预计工时:2 小时 2. **修复问题 2.2**: 禁用后可重新连接 - 修改 `ServerDetailStep.tsx` 的 reconnect 选项条件 - 预计工时:1 小时 ### Phase 2: 在 Dialog 中集成 Auth 功能 (优先级:高) 3. **修复问题 1**: MCP Dialog 集成 OAuth 认证 - 扩展 `MCP_MANAGEMENT_STEPS` 添加认证步骤 - 在 `ServerDetailStep` 中添加"Authenticate"选项 - 在 `MCPManagementDialog` 中实现认证逻辑 - 更新 i18n 翻译文件 - 预计工时:4 小时 ### Phase 3: 改进禁用体验 (优先级:中) 4. **修复问题 3**: 简化禁用流程 - 移除 `DisableScopeSelectStep` - 实现自动 scope 判断逻辑 - 更新 UI 提示 - 预计工时:4 小时 ### Phase 4: UI 细节优化 (优先级:中) 5. **修复问题 4**: Dialog 1 细节优化 - 移除重复的来源显示 - 优化错误信息显示逻辑 (只在有错误时显示) - 移除多余的空格 - 优化布局紧凑度 - 预计工时:3 小时 6. **修复问题 5**: Dialog 2 细节优化 - 统一来源颜色与其他部分一致 - 添加功能说明 tooltip - 统一选中色为 theme.text.accent - 优化工具标注文案 (如"destructive, open-world") - 移除不必要的序号 - 预计工时:3 小时 ### Phase 5: Extension Management 修复 (优先级:低) 7. **修复问题 6**: Extension 命令报错 - 改进错误提示 (方案 A) - 考虑支持单复数形式 (方案 C) - 预计工时:2 小时 ### Phase 6: 测试与验证 (优先级:高) 8. **回归测试** - 更新所有相关测试用例 - 手动测试各个场景 - 确保没有破坏性变更 - 预计工时:4 小时 **总预计工时**: 约 23 小时 (约 3 个工作日) --- ## 影响评估 ### 兼容性影响 - **Breaking Changes**: 无 - **Deprecation**: 无 - **新功能**: MCP Dialog 集成 OAuth 认证功能 ### 需要更新的文档 1. `docs/developers/tools/mcp-server.md` - 更新 MCP 管理对话框使用说明 2. `docs/users/features/mcp-servers.md` - 更新用户指南 3. `docs/users/features/extensions.md` - 更新扩展管理说明 4. 内联帮助文本和 i18n 文件 ### 需要更新的测试 1. `packages/cli/src/ui/commands/mcpCommand.test.ts` 2. `packages/cli/src/ui/components/mcp/MCPManagementDialog.test.tsx` 3. `packages/cli/src/ui/components/mcp/steps/ServerDetailStep.test.tsx` 4. `packages/cli/src/ui/commands/extensionsCommand.test.ts` 5. `packages/cli/src/ui/components/extensions/ExtensionsManagerDialog.test.tsx` --- ## 验收标准 ### 问题 1 验收标准 - [ ] MCP Management Dialog 中显示"Authenticate"选项 (针对需要认证的服务器) - [ ] 点击认证后能正确启动 OAuth 流程 - [ ] 认证过程中显示友好的提示信息 - [ ] 认证成功后自动刷新服务器状态 - [ ] 认证失败时显示明确的错误信息 - [ ] 保留 `/mcp auth` 命令作为备选方案 (可选) ### 问题 2.1 验收标准 - [ ] 禁用的服务器不显示"查看工具"选项,或显示友好提示 - [ ] 工具列表为空时,明确提示原因 - [ ] 用户不会看到空的工具列表页面 ### 问题 2.2 验收标准 - [ ] 禁用的服务器不显示"重新连接"选项 - [ ] UI 逻辑自洽,不会出现矛盾的操作选项 - [ ] 禁用状态下只能看到"启用"选项 ### 问题 3 验收标准 - [ ] 禁用操作一键完成,无需选择 scope - [ ] 禁用范围自动匹配配置范围 - [ ] UI 明确显示服务器的配置位置 - [ ] 用户体验流畅,无困惑点 ### 问题 4 验收标准 (Dialog 1 细节优化) - [ ] 移除重复的来源显示 - [ ] 只在有错误时显示"运行 qwen --debug..."提示 - [ ] 没有错误时不显示多余的空格 - [ ] 布局更加紧凑,接近 claude code 的视觉效果 ### 问题 5 验收标准 (Dialog 2 细节优化) - [ ] 来源颜色与其他部分统一 - [ ] 添加清晰的功能说明 - [ ] 统一选中色为 theme.text.accent - [ ] 工具标注文案更易懂 (如改为"Destructive, Open-world") - [ ] 移除列表项前的序号 (1、2、3...) ### 问题 6 验收标准 (Extension Management) - [ ] `/extensions manage` 命令能正常工作 - [ ] 如果 ExtensionManager 不可用,显示明确的错误提示 - [ ] 考虑支持 `/extension`(单数) 作为别名 (可选) - [ ] 测试不同环境下的行为 (普通模式、沙箱模式等) --- ## 技术细节补充 ### 关键文件清单 ``` # MCP Management packages/cli/src/ui/commands/mcpCommand.ts packages/cli/src/ui/components/mcp/MCPManagementDialog.tsx packages/cli/src/ui/components/mcp/steps/ServerDetailStep.tsx packages/cli/src/ui/components/mcp/steps/ServerListStep.tsx packages/cli/src/ui/components/mcp/steps/ToolListStep.tsx packages/cli/src/ui/components/mcp/types.ts packages/core/src/tools/mcp-client-manager.ts packages/core/src/config/config.ts # Extension Management packages/cli/src/ui/commands/extensionsCommand.ts packages/cli/src/ui/components/extensions/ExtensionsManagerDialog.tsx packages/cli/src/ui/components/extensions/types.ts packages/core/src/extension/extensionManager.ts ``` ### 依赖关系 - MCP Management Dialog 依赖于 Config、ToolRegistry、PromptRegistry - 禁用逻辑涉及 Settings 的多 scope 管理 - 状态跟踪通过 `getMCPServerStatus` 和状态监听器实现 ### 潜在风险点 1. **OAuth 认证流程**: 确保在 Dialog 中集成的认证功能不影响现有命令行认证 2. **多 Scope 配置**: 确保自动 scope 判断不会误删其他 scope 的配置 3. **Extension 集成**: 确保扩展提供的服务器正确处理 4. **环境兼容性**: 确保 Extension Management 在不同环境下都能给出正确的错误提示 --- ## 总结 本文档针对 0.12.0 版本体验反馈中提出的 **6 个问题** (3 个 P1 + 3 个 P2) 进行了详细分析,并提供了具体的解决方案。所有修改都遵循以下原则: 1. **用户体验优先**: 简化操作流程,减少困惑 2. **逻辑一致性**: 确保 UI 状态和行为逻辑自洽 3. **向后兼容**: 避免破坏性变更 4. **代码质量**: 简化代码结构,提高可维护性 5. **错误友好**: 提供清晰、有帮助的错误信息 建议按优先级分阶段实施,确保每个问题都得到妥善解决。