1use std::path::Path;
2
3use crate::error::Result;
4
5pub fn register_tool(
6 mcp_config_path: &Path,
7 tool_id: &str,
8 command: &str,
9 args: &[String],
10) -> Result<()> {
11 let mut config: serde_json::Value = if mcp_config_path.exists() {
12 let raw = std::fs::read_to_string(mcp_config_path)?;
13 if raw.trim().is_empty() {
14 serde_json::json!({})
15 } else {
16 serde_json::from_str(&raw).unwrap_or(serde_json::json!({}))
17 }
18 } else {
19 serde_json::json!({})
20 };
21
22 let servers = config
23 .as_object_mut()
24 .and_then(|object| {
25 object
26 .entry("mcpServers")
27 .or_insert_with(|| serde_json::json!({}))
28 .as_object_mut()
29 })
30 .expect("new JSON object always has a mutable object map");
31
32 servers.insert(
33 tool_id.to_string(),
34 serde_json::json!({"command": command, "args": args}),
35 );
36
37 if let Some(parent) = mcp_config_path.parent() {
38 std::fs::create_dir_all(parent)?;
39 }
40 std::fs::write(
41 mcp_config_path,
42 serde_json::to_string_pretty(&config)? + "\n",
43 )?;
44 Ok(())
45}
46
47pub fn remove_tool(mcp_config_path: &Path, tool_id: &str) -> Result<()> {
48 if !mcp_config_path.exists() {
49 return Ok(());
50 }
51
52 let raw = std::fs::read_to_string(mcp_config_path)?;
53 let mut config: serde_json::Value = serde_json::from_str(&raw).unwrap_or(serde_json::json!({}));
54
55 if let Some(servers) = config
56 .as_object_mut()
57 .and_then(|object| object.get_mut("mcpServers"))
58 .and_then(serde_json::Value::as_object_mut)
59 {
60 servers.remove(tool_id);
61 }
62
63 std::fs::write(
64 mcp_config_path,
65 serde_json::to_string_pretty(&config)? + "\n",
66 )?;
67 Ok(())
68}