fix(mcp): migrate import functions to unified v3.7.0 structure
- Rewrite import_from_claude/codex/gemini to write directly to mcp.servers - Implement skip-on-error strategy for fault tolerance (single invalid item no longer aborts entire batch) - Smart merge logic: existing servers only enable corresponding app, preserve other configs - Remove deprecated markers from service layer - Export McpApps type for test usage - Update mcp_commands tests to use unified structure Fixes runtime import issue where data was written to legacy structure (mcp.claude/codex.servers) but unified panel reads from new structure (mcp.servers), causing "imported but invisible" bug.
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
use std::{fs, sync::RwLock};
|
||||
use std::{collections::HashMap, fs, sync::RwLock};
|
||||
|
||||
use serde_json::json;
|
||||
|
||||
use cc_switch_lib::{
|
||||
get_claude_mcp_path, get_claude_settings_path, import_default_config_test_hook, AppError,
|
||||
AppState, AppType, McpService, MultiAppConfig,
|
||||
AppState, AppType, McpApps, McpServer, McpService, MultiAppConfig,
|
||||
};
|
||||
|
||||
#[path = "support.rs"]
|
||||
@@ -126,16 +126,12 @@ fn import_mcp_from_claude_creates_config_and_enables_servers() {
|
||||
);
|
||||
|
||||
let guard = state.config.read().expect("lock config");
|
||||
let claude_servers = &guard.mcp.claude.servers;
|
||||
let entry = claude_servers
|
||||
.get("echo")
|
||||
.expect("server imported into config.json");
|
||||
// v3.7.0: 检查统一结构
|
||||
let servers = guard.mcp.servers.as_ref().expect("unified servers should exist");
|
||||
let entry = servers.get("echo").expect("server imported into unified structure");
|
||||
assert!(
|
||||
entry
|
||||
.get("enabled")
|
||||
.and_then(|v| v.as_bool())
|
||||
.unwrap_or(false),
|
||||
"imported server should be marked enabled"
|
||||
entry.apps.claude,
|
||||
"imported server should have Claude app enabled"
|
||||
);
|
||||
drop(guard);
|
||||
|
||||
@@ -181,43 +177,61 @@ fn import_mcp_from_claude_invalid_json_preserves_state() {
|
||||
fn set_mcp_enabled_for_codex_writes_live_config() {
|
||||
let _guard = test_mutex().lock().expect("acquire test mutex");
|
||||
reset_test_fs();
|
||||
ensure_test_home();
|
||||
let home = ensure_test_home();
|
||||
|
||||
// 创建 Codex 配置目录和文件
|
||||
let codex_dir = home.join(".codex");
|
||||
fs::create_dir_all(&codex_dir).expect("create codex dir");
|
||||
fs::write(codex_dir.join("auth.json"), r#"{"OPENAI_API_KEY":"test-key"}"#)
|
||||
.expect("create auth.json");
|
||||
fs::write(codex_dir.join("config.toml"), "")
|
||||
.expect("create empty config.toml");
|
||||
|
||||
let mut config = MultiAppConfig::default();
|
||||
config.ensure_app(&AppType::Codex);
|
||||
config.mcp.codex.servers.insert(
|
||||
|
||||
// v3.7.0: 使用统一结构
|
||||
config.mcp.servers = Some(HashMap::new());
|
||||
config.mcp.servers.as_mut().unwrap().insert(
|
||||
"codex-server".into(),
|
||||
json!({
|
||||
"id": "codex-server",
|
||||
"name": "Codex Server",
|
||||
"server": {
|
||||
McpServer {
|
||||
id: "codex-server".to_string(),
|
||||
name: "Codex Server".to_string(),
|
||||
server: json!({
|
||||
"type": "stdio",
|
||||
"command": "echo"
|
||||
}),
|
||||
apps: McpApps {
|
||||
claude: false,
|
||||
codex: false, // 初始未启用
|
||||
gemini: false,
|
||||
},
|
||||
"enabled": false
|
||||
}),
|
||||
description: None,
|
||||
homepage: None,
|
||||
docs: None,
|
||||
tags: Vec::new(),
|
||||
},
|
||||
);
|
||||
|
||||
let state = AppState {
|
||||
config: RwLock::new(config),
|
||||
};
|
||||
|
||||
McpService::set_enabled(&state, AppType::Codex, "codex-server", true)
|
||||
.expect("set enabled should succeed");
|
||||
// v3.7.0: 使用 toggle_app 替代 set_enabled
|
||||
McpService::toggle_app(&state, "codex-server", AppType::Codex, true)
|
||||
.expect("toggle_app should succeed");
|
||||
|
||||
let guard = state.config.read().expect("lock config");
|
||||
let entry = guard
|
||||
.mcp
|
||||
.codex
|
||||
.servers
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.get("codex-server")
|
||||
.expect("codex server exists");
|
||||
assert!(
|
||||
entry
|
||||
.get("enabled")
|
||||
.and_then(|v| v.as_bool())
|
||||
.unwrap_or(false),
|
||||
"server should be marked enabled after command"
|
||||
entry.apps.codex,
|
||||
"server should have Codex app enabled after toggle"
|
||||
);
|
||||
drop(guard);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user