feat(gemini): implement full MCP management functionality

- Add gemini_mcp.rs module for Gemini MCP file I/O operations
- Implement sync_enabled_to_gemini to export enabled MCPs to ~/.gemini/settings.json
- Implement import_from_gemini to import MCPs from Gemini config
- Add Gemini sync logic in services/mcp.rs (upsert_server, delete_server, set_enabled)
- Register Tauri commands for Gemini MCP sync and import
- Update frontend API calls and McpPanel to support Gemini

Fixes the issue where adding MCP servers in Gemini tab would not sync to ~/.gemini/settings.json
This commit is contained in:
Jason
2025-11-14 10:02:27 +08:00
parent 146b42fb68
commit 1616c63c0b
7 changed files with 344 additions and 7 deletions

View File

@@ -30,11 +30,12 @@ impl McpService {
spec: Value,
sync_other_side: bool,
) -> Result<bool, AppError> {
let (changed, snapshot, sync_claude, sync_codex): (
let (changed, snapshot, sync_claude, sync_codex, sync_gemini): (
bool,
Option<MultiAppConfig>,
bool,
bool,
bool,
) = {
let mut cfg = state.config.write()?;
let changed = mcp::upsert_in_config_for(&mut cfg, &app, id, spec)?;
@@ -51,6 +52,7 @@ impl McpService {
let mut sync_claude = matches!(app, AppType::Claude) && enabled;
let mut sync_codex = matches!(app, AppType::Codex) && enabled;
let mut sync_gemini = matches!(app, AppType::Gemini) && enabled;
// 修复sync_other_side=true 时,先将 MCP 复制到另一侧,然后强制同步
// 这才是"同步到另一侧"的正确语义:将 MCP 跨应用复制
@@ -83,13 +85,13 @@ impl McpService {
}
}
let snapshot = if sync_claude || sync_codex {
let snapshot = if sync_claude || sync_codex || sync_gemini {
Some(cfg.clone())
} else {
None
};
(changed, snapshot, sync_claude, sync_codex)
(changed, snapshot, sync_claude, sync_codex, sync_gemini)
};
// 保持原有行为:始终尝试持久化,避免遗漏 normalize 带来的隐式变更
@@ -102,6 +104,9 @@ impl McpService {
if sync_codex {
mcp::sync_enabled_to_codex(&snapshot)?;
}
if sync_gemini {
mcp::sync_enabled_to_gemini(&snapshot)?;
}
}
Ok(changed)
@@ -121,7 +126,7 @@ impl McpService {
match app {
AppType::Claude => mcp::sync_enabled_to_claude(&snapshot)?,
AppType::Codex => mcp::sync_enabled_to_codex(&snapshot)?,
AppType::Gemini => {} // Gemini 暂不支持 MCP 同步
AppType::Gemini => mcp::sync_enabled_to_gemini(&snapshot)?,
}
}
}
@@ -148,7 +153,7 @@ impl McpService {
match app {
AppType::Claude => mcp::sync_enabled_to_claude(&snapshot)?,
AppType::Codex => mcp::sync_enabled_to_codex(&snapshot)?,
AppType::Gemini => {} // Gemini 暂不支持 MCP 同步
AppType::Gemini => mcp::sync_enabled_to_gemini(&snapshot)?,
}
}
}
@@ -168,7 +173,7 @@ impl McpService {
match app {
AppType::Claude => mcp::sync_enabled_to_claude(&snapshot)?,
AppType::Codex => mcp::sync_enabled_to_codex(&snapshot)?,
AppType::Gemini => {} // Gemini 暂不支持 MCP 同步
AppType::Gemini => mcp::sync_enabled_to_gemini(&snapshot)?,
}
Ok(())
}
@@ -194,4 +199,15 @@ impl McpService {
}
Ok(changed)
}
/// 从 Gemini 客户端配置导入 MCP 定义。
pub fn import_from_gemini(state: &AppState) -> Result<usize, AppError> {
let mut cfg = state.config.write()?;
let changed = mcp::import_from_gemini(&mut cfg)?;
drop(cfg);
if changed > 0 {
state.save()?;
}
Ok(changed)
}
}