Skip to main content

weavatrix_rust/tools/
catalog.rs

1use blazingly_json::{Map, Value, json};
2use serde::Serialize;
3
4#[derive(Debug, Clone, Serialize)]
5#[serde(rename_all = "camelCase")]
6pub struct ToolDefinition {
7    pub name: &'static str,
8    pub description: &'static str,
9    pub input_schema: Value,
10}
11
12#[must_use]
13#[allow(clippy::too_many_lines)]
14pub fn catalog() -> Vec<ToolDefinition> {
15    let mut tools = vec![
16        tool(
17            "graph_stats",
18            "Graph size, evidence and build freshness.",
19            &[],
20        ),
21        tool("get_node", "Resolve one exact graph node.", &["label"]),
22        tool(
23            "get_neighbors",
24            "Direct typed incoming and outgoing relationships.",
25            &["label"],
26        ),
27        tool(
28            "query_graph",
29            "Bounded BFS or DFS around exact or textual seeds.",
30            &[],
31        ),
32        tool("god_nodes", "Rank high-connectivity production nodes.", &[]),
33        tool(
34            "shortest_path",
35            "Shortest typed dependency path between two nodes.",
36            &["source", "target"],
37        ),
38        tool(
39            "get_dependents",
40            "Bounded transitive reverse blast radius.",
41            &["label"],
42        ),
43        tool(
44            "change_impact",
45            "Read-only Git change impact with graph evidence.",
46            &[],
47        ),
48        tool(
49            "git_history",
50            "Bounded direct Git history without launching git.",
51            &[],
52        ),
53        tool(
54            "cross_repo_git",
55            "Parallel histories, shared commits, or diffs across local repositories.",
56            &["repositories"],
57        ),
58        tool(
59            "verified_change",
60            "Composite pre-commit evidence and conservative verdict.",
61            &["task"],
62        ),
63        tool(
64            "trace_api_contract",
65            "Cross-repository HTTP, GraphQL, gRPC and event-transport contract evidence.",
66            &["backend", "clients"],
67        ),
68        tool(
69            "get_community",
70            "Return one weak graph component.",
71            &["community_id"],
72        ),
73        tool(
74            "search_code",
75            "Literal or Rust-regex repository search without ripgrep.",
76            &["query"],
77        ),
78        tool(
79            "read_source",
80            "Bounded source context by node or repository path.",
81            &[],
82        ),
83        tool(
84            "inspect_symbol",
85            "Definition, direct relationships and source evidence.",
86            &["label"],
87        ),
88        tool(
89            "context_bundle",
90            "Compact graph and source bundle for one symbol.",
91            &["label"],
92        ),
93        tool(
94            "find_duplicates",
95            "Deterministic Type-1/2/3 clone families.",
96            &[],
97        ),
98        tool(
99            "find_dead_code",
100            "Conservative unreferenced-symbol review queue.",
101            &[],
102        ),
103        tool(
104            "run_audit",
105            "Repository structure and evidence completeness audit.",
106            &[],
107        ),
108        tool(
109            "coverage_map",
110            "Measured coverage discovery or explicit static reachability.",
111            &[],
112        ),
113        tool(
114            "hot_path_review",
115            "Rank high-connectivity and large source symbols.",
116            &[],
117        ),
118        tool(
119            "list_communities",
120            "List deterministic weak graph components.",
121            &[],
122        ),
123        tool("module_map", "Production folder and dependency map.", &[]),
124        tool(
125            "list_endpoints",
126            "Inventory statically extracted HTTP endpoints.",
127            &[],
128        ),
129        tool(
130            "trace_endpoint",
131            "Resolve an endpoint and its bounded call neighborhood.",
132            &["path"],
133        ),
134        tool(
135            "rebuild_graph",
136            "Rebuild the derived in-memory graph without source writes.",
137            &[],
138        ),
139        tool(
140            "graph_diff",
141            "Compare the current snapshot with an immutable Git revision.",
142            &["base_ref"],
143        ),
144        tool(
145            "get_architecture_contract",
146            "Read or preview the local target-architecture contract.",
147            &[],
148        ),
149        tool(
150            "prepare_change",
151            "Select architecture rules for intended changed files.",
152            &["files"],
153        ),
154        tool(
155            "verify_architecture",
156            "Verify graph dependencies against the active contract.",
157            &[],
158        ),
159        tool(
160            "explain_architecture_violation",
161            "Explain one active contract violation.",
162            &["fingerprint"],
163        ),
164        tool(
165            "propose_architecture_exception",
166            "Return a reviewable exception proposal without writing it.",
167            &["fingerprint", "reason"],
168        ),
169        tool(
170            "open_repo",
171            "Retarget to another local repository.",
172            &["path"],
173        ),
174        tool(
175            "list_known_repos",
176            "List repositories opened by this server process.",
177            &[],
178        ),
179        tool(
180            "semantic_link",
181            "Build inferred semantic graph evidence from supplied vectors.",
182            &["vectors"],
183        ),
184        tool(
185            "vector_search",
186            "Exact or bounded approximate nearest-neighbor search.",
187            &["vectors", "query"],
188        ),
189        tool(
190            "seo_link_suggestions",
191            "Directional SEO internal-link evidence from supplied page profiles.",
192            &["vectors", "pages"],
193        ),
194        tool(
195            "memory_context",
196            "Compile bounded temporal memory context from supplied events.",
197            &["events", "request"],
198        ),
199    ];
200    tools.retain(|tool| capability_is_compiled(tool.name));
201    tools
202}
203
204#[must_use]
205pub fn catalog_for_profile(profile: crate::mcp::McpProfile) -> Vec<ToolDefinition> {
206    catalog()
207        .into_iter()
208        .filter(|tool| profile.allows(tool.name))
209        .collect()
210}
211
212#[allow(clippy::needless_bool)]
213fn capability_is_compiled(tool: &str) -> bool {
214    if tool == "find_duplicates" {
215        cfg!(feature = "clone")
216    } else if matches!(
217        tool,
218        "change_impact" | "git_history" | "cross_repo_git" | "verified_change" | "graph_diff"
219    ) {
220        cfg!(feature = "git")
221    } else if tool == "search_code" {
222        cfg!(feature = "search")
223    } else if matches!(tool, "semantic_link" | "seo_link_suggestions") {
224        cfg!(feature = "semantic")
225    } else if tool == "vector_search" {
226        cfg!(feature = "vector")
227    } else if tool == "memory_context" {
228        cfg!(feature = "memory")
229    } else {
230        true
231    }
232}
233
234fn tool(
235    tool_name: &'static str,
236    description: &'static str,
237    required: &[&'static str],
238) -> ToolDefinition {
239    let mut properties = Map::from_iter([(
240        "output_format".to_owned(),
241        json!({
242            "type": "string",
243            "enum": ["text", "json"],
244            "default": "json"
245        }),
246    )]);
247    for name in super::catalog_schema::optional_fields(tool_name) {
248        properties.insert(
249            (*name).to_owned(),
250            super::catalog_schema::field_schema(tool_name, name),
251        );
252    }
253    for name in required {
254        let schema = super::catalog_schema::field_schema(tool_name, name);
255        properties.insert((*name).to_owned(), schema);
256    }
257    let required = required
258        .iter()
259        .map(|value| json!(value))
260        .collect::<Vec<_>>();
261    ToolDefinition {
262        name: tool_name,
263        description,
264        input_schema: json!({
265            "type": "object",
266            "additionalProperties": true,
267            "properties": properties,
268            "required": required
269        }),
270    }
271}