Skip to main content

mcp_memory/
tools.rs

1pub struct ToolMeta {
2    pub name: &'static str,
3    pub write: bool,
4}
5
6pub const ALL_TOOLS: &[ToolMeta] = &[
7    ToolMeta { name: "create_entities",    write: true  },
8    ToolMeta { name: "create_relations",   write: true  },
9    ToolMeta { name: "add_observations",   write: true  },
10    ToolMeta { name: "delete_entities",    write: true  },
11    ToolMeta { name: "delete_observations",write: true  },
12    ToolMeta { name: "delete_relations",   write: true  },
13    ToolMeta { name: "read_graph",         write: false },
14    ToolMeta { name: "search_nodes",       write: false },
15    ToolMeta { name: "open_nodes",         write: false },
16    ToolMeta { name: "get_entity",         write: false },
17    ToolMeta { name: "graph_stats",        write: false },
18    ToolMeta { name: "search_relations",   write: false },
19    ToolMeta { name: "find_path",          write: false },
20    ToolMeta { name: "compact",            write: true  },
21    ToolMeta { name: "get_neighbors",      write: false },
22    ToolMeta { name: "describe_entity",    write: false },
23    ToolMeta { name: "list_entity_types",  write: false },
24    ToolMeta { name: "list_relation_types",write: false },
25    ToolMeta { name: "upsert_entities",    write: true  },
26    ToolMeta { name: "export_graph",       write: false },
27];
28
29#[inline]
30pub fn tool_exists(name: &str) -> bool {
31    ALL_TOOLS.iter().any(|t| t.name == name)
32}
33
34#[inline]
35pub fn is_write_tool(name: &str) -> bool {
36    ALL_TOOLS.iter().find(|t| t.name == name).map(|t| t.write).unwrap_or(false)
37}
38
39#[cfg(test)]
40mod tests {
41    use super::*;
42
43    #[test]
44    fn test_tool_exists_known() {
45        assert!(tool_exists("create_entities"));
46        assert!(tool_exists("read_graph"));
47        assert!(tool_exists("search_nodes"));
48    }
49
50    #[test]
51    fn test_tool_exists_unknown() {
52        assert!(!tool_exists("nonexistent_tool"));
53    }
54
55    #[test]
56    fn test_is_write_tool() {
57        assert!(is_write_tool("create_entities"));
58        assert!(is_write_tool("delete_entities"));
59        assert!(!is_write_tool("read_graph"));
60        assert!(!is_write_tool("search_nodes"));
61    }
62
63    #[test]
64    fn test_all_tools_unique() {
65        let mut names: Vec<&str> = ALL_TOOLS.iter().map(|t| t.name).collect();
66        names.sort();
67        names.dedup();
68        assert_eq!(names.len(), ALL_TOOLS.len(), "Duplicate tool names");
69    }
70
71    #[test]
72    fn test_tools_json_matches_all_tools() {
73        let tools_json = include_str!("../tools.json");
74        let parsed: Vec<serde_json::Value> =
75            serde_json::from_str(tools_json).expect("tools.json must be valid JSON");
76
77        let mut json_names: Vec<&str> = parsed
78            .iter()
79            .map(|t| t["name"].as_str().expect("each tool needs a name"))
80            .collect();
81        let mut meta_names: Vec<&str> = ALL_TOOLS.iter().map(|t| t.name).collect();
82        json_names.sort_unstable();
83        meta_names.sort_unstable();
84
85        assert_eq!(
86            json_names, meta_names,
87            "tools.json and ALL_TOOLS must declare the same tool names"
88        );
89    }
90}