Skip to main content

lean_ctx_server/tools/registered/
ctx_heatmap.rs

1// SPDX-License-Identifier: Apache-2.0
2use rmcp::ErrorData;
3use rmcp::model::Tool;
4use serde_json::{Map, Value, json};
5
6use crate::server::tool_trait::{McpTool, ToolContext, ToolOutput, get_str};
7use lean_ctx::tool_defs::tool_def;
8
9pub struct CtxHeatmapTool;
10
11impl McpTool for CtxHeatmapTool {
12    fn name(&self) -> &'static str {
13        "ctx_heatmap"
14    }
15
16    fn tool_def(&self) -> Tool {
17        tool_def(
18            "ctx_heatmap",
19            "File access heatmap — shows most frequently accessed files per session.\n\
20             action=status (default) for summary, action=detail for per-file access counts.\n\
21             Identify hot files to optimize context usage.",
22            json!({
23                "type": "object",
24                "properties": {
25                    "action": { "type": "string", "description": "status|detail" },
26                    "path": { "type": "string" }
27                }
28            }),
29        )
30    }
31
32    fn handle(
33        &self,
34        args: &Map<String, Value>,
35        ctx: &ToolContext,
36    ) -> Result<ToolOutput, ErrorData> {
37        let action = get_str(args, "action").unwrap_or_else(|| "status".to_string());
38        let path = get_str(args, "path")
39            .map(|raw| lean_ctx::core::workspace_authority::confine(&raw, &ctx.project_root, false))
40            .transpose()
41            .map_err(|error| ErrorData::invalid_params(error, None))?;
42        let result = crate::tools::ctx_heatmap::handle(&action, path.as_deref());
43        Ok(ToolOutput {
44            text: result,
45            original_tokens: 0,
46            saved_tokens: 0,
47            mode: Some(action),
48            path: None,
49            changed: false,
50            shell_outcome: None,
51            content_blocks: None,
52        })
53    }
54}