Skip to main content

lean_ctx/tools/registered/
ctx_plan.rs

1use 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 CtxPlanTool;
9
10impl McpTool for CtxPlanTool {
11    fn name(&self) -> &'static str {
12        "ctx_plan"
13    }
14
15    fn tool_def(&self) -> Tool {
16        tool_def(
17            "ctx_plan",
18            "WORKFLOW: set task+profile -> ctx_plan -> use results with ctx_read/ctx_compose.\n\
19            ANTIPATTERN: NOT for compressing already-selected files (use ctx_fill).\n\
20            Selects files for context via Phi scoring + budget + policy.\n\
21            task=short English; budget=token limit (default 12000);\n\
22            profile=ultra_lean|balanced|forensic. Saves tokens by prioritizing relevant files.",
23            json!({
24                "type": "object",
25                "properties": {
26                    "task": { "type": "string", "description": "Task description (short English preferred)" },
27                    "budget": { "type": "integer", "description": "Token budget limit (default: 12000)" },
28                    "profile": { "type": "string", "description": "ultra_lean (minimal)|balanced (default)|forensic (exhaustive)" }
29                },
30                "required": ["task"]
31            }),
32        )
33    }
34
35    fn handle(
36        &self,
37        args: &Map<String, Value>,
38        ctx: &ToolContext,
39    ) -> Result<ToolOutput, ErrorData> {
40        let ledger = crate::core::context_ledger::ContextLedger::load();
41
42        let root = if let Some(ref session_lock) = ctx.session {
43            crate::server::bounded_lock::read(session_lock, "ctx_plan:session")
44                .as_ref()
45                .and_then(|s| s.project_root.clone())
46                .unwrap_or_else(|| ctx.project_root.clone())
47        } else {
48            ctx.project_root.clone()
49        };
50
51        let policies = crate::core::context_policies::PolicySet::load_project(
52            &std::path::PathBuf::from(&root),
53        );
54        let result = crate::tools::ctx_plan::handle(Some(args), &ledger, &policies);
55
56        Ok(ToolOutput::simple(result))
57    }
58}