Skip to main content

lean_ctx/tools/registered/
ctx_symbol.rs

1use rmcp::model::Tool;
2use rmcp::ErrorData;
3use serde_json::{json, Map, Value};
4
5use crate::server::tool_trait::{get_str, McpTool, ToolContext, ToolOutput};
6use crate::tool_defs::tool_def;
7
8pub struct CtxSymbolTool;
9
10impl McpTool for CtxSymbolTool {
11    fn name(&self) -> &'static str {
12        "ctx_symbol"
13    }
14
15    fn tool_def(&self) -> Tool {
16        tool_def(
17            "ctx_symbol",
18            "Read a specific symbol (function, struct, class) by name. Returns only the symbol \
19code block instead of the entire file. 90-97% fewer tokens than full file read.",
20            json!({
21                "type": "object",
22                "properties": {
23                    "name": { "type": "string", "description": "Symbol name (function, struct, class, method)" },
24                    "file": { "type": "string", "description": "Optional: file path to narrow search" },
25                    "kind": { "type": "string", "description": "Optional: fn|struct|class|method|trait|enum" }
26                },
27                "required": ["name"]
28            }),
29        )
30    }
31
32    fn handle(
33        &self,
34        args: &Map<String, Value>,
35        ctx: &ToolContext,
36    ) -> Result<ToolOutput, ErrorData> {
37        let sym_name = get_str(args, "name")
38            .ok_or_else(|| ErrorData::invalid_params("name is required", None))?;
39        let file = get_str(args, "file");
40        let kind = get_str(args, "kind");
41
42        let (result, original) = crate::tools::ctx_symbol::handle(
43            &sym_name,
44            file.as_deref(),
45            kind.as_deref(),
46            &ctx.project_root,
47        );
48        let sent = crate::core::tokens::count_tokens(&result);
49        let saved = original.saturating_sub(sent);
50
51        Ok(ToolOutput {
52            text: result,
53            original_tokens: original,
54            saved_tokens: saved,
55            mode: kind,
56            path: file,
57        })
58    }
59}