Skip to main content

tuff_core/
mcp.rs

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}