lean_ctx/tools/registered/
ctx_expand.rs1use rmcp::ErrorData;
2use rmcp::model::Tool;
3use serde_json::{Map, Value, json};
4
5use crate::server::tool_trait::{McpTool, ToolContext, ToolOutput};
6use crate::tool_defs::tool_def;
7
8pub struct CtxExpandTool;
9
10impl McpTool for CtxExpandTool {
11 fn name(&self) -> &'static str {
12 "ctx_expand"
13 }
14
15 fn tool_def(&self) -> Tool {
16 tool_def(
17 "ctx_expand",
18 "Retrieve archived tool output by ID (e.g. id=@F1 from [Archived:ID] hints).\n\
19 WORKFLOW: see [Archived:ID] → ctx_expand id=ID to restore full content.\n\
20 Supports head/tail/search to filter lines and save tokens on re-read.\n\
21 action=list browses all archives. action=search_all queries across archives.\n\
22 Zero-loss: original preserved.\n\
23 ANTIPATTERN: not for reading project files — use ctx_read or ctx_compose.",
24 json!({
25 "type": "object",
26 "properties": {
27 "id": { "type": "string", "description": "Archive ID or @F1 ref" },
28 "action": { "type": "string", "description": "retrieve|list|search_all" },
29 "start_line": { "type": "integer", "description": "1-based start line" },
30 "end_line": { "type": "integer", "description": "1-based end line" },
31 "head": { "type": "integer", "description": "First N lines" },
32 "tail": { "type": "integer", "description": "Last N lines" },
33 "search": { "type": "string", "description": "Lines matching substring" },
34 "json_keys": { "type": "boolean", "description": "List JSON keys" },
35 "json_path": { "type": "string", "description": "JSON path, e.g. data.items.0" },
36 "query": { "type": "string", "description": "search_all query" },
37 "session_id": { "type": "string", "description": "Filter by session ID" }
38 }
39 }),
40 )
41 }
42
43 fn handle(
44 &self,
45 args: &Map<String, Value>,
46 _ctx: &ToolContext,
47 ) -> Result<ToolOutput, ErrorData> {
48 let args_val = Value::Object(args.clone());
49 let result = crate::tools::ctx_expand::handle(&args_val);
50 Ok(ToolOutput::simple(result))
51 }
52}