fix(mcp): correct Codex MCP configuration format to [mcp_servers]

BREAKING CHANGE: The [mcp.servers] format was completely incorrect and not
any official Codex format. The only correct format is [mcp_servers] at the
top level of config.toml.

Changes:
- Remove incorrect [mcp.servers] nested table support
- Always use [mcp_servers] top-level table (official Codex format)
- Auto-migrate and cleanup erroneous [mcp.servers] entries on write
- Preserve error-tolerant import for migrating old incorrect configs
- Simplify sync logic by removing format selection branches (~60 lines)
- Update all documentation and tests to reflect correct format
- Add warning logs when detecting and cleaning incorrect format

Backend (Rust):
- mcp.rs: Simplify sync_enabled_to_codex by removing Target enum
- mcp.rs: sync_single_server_to_codex now always uses [mcp_servers]
- mcp.rs: remove_server_from_codex cleans both locations
- mcp.rs: Update import_from_codex comments to clarify format status
- tests: Rename test to sync_enabled_to_codex_migrates_erroneous_*
- tests: Update assertions to verify migration behavior

Frontend (TypeScript):
- tomlUtils.ts: Prioritize [mcp_servers] format in parsing
- tomlUtils.ts: Update error messages to guide correct format

Documentation:
- README.md: Correct MCP format reference to [mcp_servers]
- CLAUDE.md: Add comprehensive format specification with examples

All 79 tests pass. This ensures backward compatibility while enforcing
the correct Codex official standard going forward.

Refs: https://github.com/openai/codex/issues/3441
This commit is contained in:
Jason
2025-11-17 22:57:04 +08:00
parent 3051743bd3
commit 67bd8f5c11
10 changed files with 147 additions and 167 deletions

View File

@@ -184,8 +184,7 @@ pub async fn get_common_config_snippet(
use crate::app_config::AppType;
use std::str::FromStr;
let app = AppType::from_str(&app_type)
.map_err(|e| format!("无效的应用类型: {}", e))?;
let app = AppType::from_str(&app_type).map_err(|e| format!("无效的应用类型: {}", e))?;
let guard = state
.config
@@ -205,8 +204,7 @@ pub async fn set_common_config_snippet(
use crate::app_config::AppType;
use std::str::FromStr;
let app = AppType::from_str(&app_type)
.map_err(|e| format!("无效的应用类型: {}", e))?;
let app = AppType::from_str(&app_type).map_err(|e| format!("无效的应用类型: {}", e))?;
let mut guard = state
.config