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_openclaw, 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_openclaw: bool = row.get(11)?;
35                let enabled_hermes: bool = row.get(12)?;
36
37                let server = serde_json::from_str(&server_config_str).unwrap_or_default();
38                let tags = serde_json::from_str(&tags_str).unwrap_or_default();
39
40                Ok((
41                    id.clone(),
42                    McpServer {
43                        id,
44                        name,
45                        server,
46                        apps: McpApps {
47                            claude: enabled_claude,
48                            codex: enabled_codex,
49                            gemini: enabled_gemini,
50                            opencode: enabled_opencode,
51                            openclaw: enabled_openclaw,
52                            hermes: enabled_hermes,
53                        },
54                        description,
55                        homepage,
56                        docs,
57                        tags,
58                    },
59                ))
60            })
61            .map_err(|e| AppError::Database(e.to_string()))?;
62
63        let mut servers = IndexMap::new();
64        for server_res in server_iter {
65            let (id, server) = server_res.map_err(|e| AppError::Database(e.to_string()))?;
66            servers.insert(id, server);
67        }
68        Ok(servers)
69    }
70
71    /// 保存 MCP 服务器
72    pub fn save_mcp_server(&self, server: &McpServer) -> Result<(), AppError> {
73        let conn = lock_conn!(self.conn);
74        conn.execute(
75            "INSERT INTO mcp_servers (
76                id, name, server_config, description, homepage, docs, tags,
77                enabled_claude, enabled_codex, enabled_gemini, enabled_opencode, enabled_openclaw, enabled_hermes
78            ) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13)
79            ON CONFLICT(id) DO UPDATE SET
80                name = excluded.name,
81                server_config = excluded.server_config,
82                description = excluded.description,
83                homepage = excluded.homepage,
84                docs = excluded.docs,
85                tags = excluded.tags,
86                enabled_claude = excluded.enabled_claude,
87                enabled_codex = excluded.enabled_codex,
88                enabled_gemini = excluded.enabled_gemini,
89                enabled_opencode = excluded.enabled_opencode,
90                enabled_openclaw = excluded.enabled_openclaw,
91                enabled_hermes = excluded.enabled_hermes",
92            params![
93                server.id,
94                server.name,
95                serde_json::to_string(&server.server).map_err(|e| AppError::Database(format!(
96                    "Failed to serialize server config: {e}"
97                )))?,
98                server.description,
99                server.homepage,
100                server.docs,
101                serde_json::to_string(&server.tags)
102                    .map_err(|e| AppError::Database(format!("Failed to serialize tags: {e}")))?,
103                server.apps.claude,
104                server.apps.codex,
105                server.apps.gemini,
106                server.apps.opencode,
107                server.apps.openclaw,
108                server.apps.hermes,
109            ],
110        )
111        .map_err(|e| AppError::Database(e.to_string()))?;
112        Ok(())
113    }
114
115    /// 删除 MCP 服务器
116    pub fn delete_mcp_server(&self, id: &str) -> Result<(), AppError> {
117        let conn = lock_conn!(self.conn);
118        conn.execute("DELETE FROM mcp_servers WHERE id = ?1", params![id])
119            .map_err(|e| AppError::Database(e.to_string()))?;
120        Ok(())
121    }
122}