Skip to main content

cc_switch_lib/database/dao/
mcp.rs

1//! MCP 服务器数据访问对象
2//!
3//! 提供 MCP 服务器的 CRUD 操作。
4
5use crate::app_config::{McpApps, McpServer};
6use crate::database::{lock_conn, Database};
7use crate::error::AppError;
8use indexmap::IndexMap;
9use rusqlite::params;
10
11impl Database {
12    /// 获取所有 MCP 服务器
13    pub fn get_all_mcp_servers(&self) -> Result<IndexMap<String, McpServer>, AppError> {
14        let conn = lock_conn!(self.conn);
15        let mut stmt = conn.prepare(
16            "SELECT id, name, server_config, description, homepage, docs, tags, enabled_claude, enabled_codex, enabled_gemini, enabled_opencode, enabled_hermes
17             FROM mcp_servers
18             ORDER BY name ASC, id ASC"
19        ).map_err(|e| AppError::Database(e.to_string()))?;
20
21        let server_iter = stmt
22            .query_map([], |row| {
23                let id: String = row.get(0)?;
24                let name: String = row.get(1)?;
25                let server_config_str: String = row.get(2)?;
26                let description: Option<String> = row.get(3)?;
27                let homepage: Option<String> = row.get(4)?;
28                let docs: Option<String> = row.get(5)?;
29                let tags_str: String = row.get(6)?;
30                let enabled_claude: bool = row.get(7)?;
31                let enabled_codex: bool = row.get(8)?;
32                let enabled_gemini: bool = row.get(9)?;
33                let enabled_opencode: bool = row.get(10)?;
34                let enabled_hermes: bool = row.get(11)?;
35
36                let server = serde_json::from_str(&server_config_str).unwrap_or_default();
37                let tags = serde_json::from_str(&tags_str).unwrap_or_default();
38
39                Ok((
40                    id.clone(),
41                    McpServer {
42                        id,
43                        name,
44                        server,
45                        apps: McpApps {
46                            claude: enabled_claude,
47                            codex: enabled_codex,
48                            gemini: enabled_gemini,
49                            opencode: enabled_opencode,
50                            hermes: enabled_hermes,
51                        },
52                        description,
53                        homepage,
54                        docs,
55                        tags,
56                    },
57                ))
58            })
59            .map_err(|e| AppError::Database(e.to_string()))?;
60
61        let mut servers = IndexMap::new();
62        for server_res in server_iter {
63            let (id, server) = server_res.map_err(|e| AppError::Database(e.to_string()))?;
64            servers.insert(id, server);
65        }
66        Ok(servers)
67    }
68
69    /// 保存 MCP 服务器
70    pub fn save_mcp_server(&self, server: &McpServer) -> Result<(), AppError> {
71        let conn = lock_conn!(self.conn);
72        conn.execute(
73            "INSERT INTO mcp_servers (
74                id, name, server_config, description, homepage, docs, tags,
75                enabled_claude, enabled_codex, enabled_gemini, enabled_opencode, enabled_hermes
76            ) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12)
77            ON CONFLICT(id) DO UPDATE SET
78                name = excluded.name,
79                server_config = excluded.server_config,
80                description = excluded.description,
81                homepage = excluded.homepage,
82                docs = excluded.docs,
83                tags = excluded.tags,
84                enabled_claude = excluded.enabled_claude,
85                enabled_codex = excluded.enabled_codex,
86                enabled_gemini = excluded.enabled_gemini,
87                enabled_opencode = excluded.enabled_opencode,
88                enabled_hermes = excluded.enabled_hermes",
89            params![
90                server.id,
91                server.name,
92                serde_json::to_string(&server.server).map_err(|e| AppError::Database(format!(
93                    "Failed to serialize server config: {e}"
94                )))?,
95                server.description,
96                server.homepage,
97                server.docs,
98                serde_json::to_string(&server.tags)
99                    .map_err(|e| AppError::Database(format!("Failed to serialize tags: {e}")))?,
100                server.apps.claude,
101                server.apps.codex,
102                server.apps.gemini,
103                server.apps.opencode,
104                server.apps.hermes,
105            ],
106        )
107        .map_err(|e| AppError::Database(e.to_string()))?;
108        Ok(())
109    }
110
111    /// 删除 MCP 服务器
112    pub fn delete_mcp_server(&self, id: &str) -> Result<(), AppError> {
113        let conn = lock_conn!(self.conn);
114        conn.execute("DELETE FROM mcp_servers WHERE id = ?1", params![id])
115            .map_err(|e| AppError::Database(e.to_string()))?;
116        Ok(())
117    }
118}