lean_ctx/tools/registered/
ctx_architecture.rs1use rmcp::ErrorData;
2use rmcp::model::Tool;
3use serde_json::{Map, Value, json};
4
5use crate::server::tool_trait::{McpTool, ToolContext, ToolOutput, get_str};
6use crate::tool_defs::tool_def;
7
8pub struct CtxArchitectureTool;
9
10impl McpTool for CtxArchitectureTool {
11 fn name(&self) -> &'static str {
12 "ctx_architecture"
13 }
14
15 fn tool_def(&self) -> Tool {
16 tool_def(
17 "ctx_architecture",
18 "Architecture analysis — understand module structure without reading every file.\n\
19 WORKFLOW: use ctx_compose FIRST for code understanding; ctx_architecture for high-level structure.\n\
20 action=overview→high-level; clusters|communities→groupings;\n\
21 layers|cycles→dependency violations; entrypoints|hotspots→risk areas;\n\
22 health→quality; module path='src/' to zoom into a specific module.\n\
23 ANTIPATTERN: does NOT show source code — only structural relationships.",
24 json!({
25 "type": "object",
26 "properties": {
27 "action": {
28 "type": "string",
29 "enum": ["overview", "clusters", "communities", "layers", "cycles", "entrypoints", "hotspots", "health", "module"],
30 "description": "overview|clusters|communities|layers|cycles|entrypoints|hotspots|health|module"
31 },
32 "path": {
33 "type": "string",
34 "description": "Module/file path"
35 },
36 "root": {
37 "type": "string",
38 "description": "Project root"
39 },
40 "format": {
41 "type": "string",
42 "description": "Output format: text|json (default text)"
43 }
44 }
45 }),
46 )
47 }
48
49 fn handle(
50 &self,
51 args: &Map<String, Value>,
52 ctx: &ToolContext,
53 ) -> Result<ToolOutput, ErrorData> {
54 let action = get_str(args, "action").unwrap_or_else(|| "overview".to_string());
55 let path = get_str(args, "path");
56 let format = get_str(args, "format");
57 let root = if let Some(p) = ctx
58 .resolved_path("root")
59 .or(ctx.resolved_path("project_root"))
60 {
61 p
62 } else if let Some(err) = ctx.path_error("root").or(ctx.path_error("project_root")) {
63 return Err(ErrorData::invalid_params(format!("root: {err}"), None));
64 } else {
65 &ctx.project_root
66 };
67
68 let result = crate::tools::ctx_architecture::handle(
69 &action,
70 path.as_deref(),
71 root,
72 format.as_deref(),
73 );
74
75 Ok(ToolOutput::simple(result))
76 }
77}