lean_ctx/tools/registered/
ctx_gain.rs1use rmcp::ErrorData;
2use rmcp::model::Tool;
3use serde_json::{Map, Value, json};
4
5use crate::server::tool_trait::{McpTool, ToolContext, ToolOutput, get_str, get_usize};
6use crate::tool_defs::tool_def;
7
8pub struct CtxGainTool;
9
10impl McpTool for CtxGainTool {
11 fn name(&self) -> &'static str {
12 "ctx_gain"
13 }
14
15 fn tool_def(&self) -> Tool {
16 tool_def(
17 "ctx_gain",
18 "Gain report — shows token savings from lean-ctx compression.\n\
19 action=wrapped for periodic/annual summary. Other actions: status|report|score|cost|tasks|heatmap|agents|json.\n\
20 period=\"week\"|\"month\"|\"all\" scopes the report.",
21 json!({
22 "type": "object",
23 "properties": {
24 "action": {
25 "type": "string",
26 "enum": ["status", "report", "score", "cost", "tasks", "heatmap", "wrapped", "agents", "json"]
27 },
28 "period": {
29 "type": "string",
30 "enum": ["week", "month", "all"]
31 },
32 "model": {
33 "type": "string"
34 },
35 "limit": {
36 "type": "integer"
37 }
38 }
39 }),
40 )
41 }
42
43 fn handle(
44 &self,
45 args: &Map<String, Value>,
46 _ctx: &ToolContext,
47 ) -> Result<ToolOutput, ErrorData> {
48 let action = get_str(args, "action").unwrap_or_else(|| "status".to_string());
49 let period = get_str(args, "period");
50 let model = get_str(args, "model");
51 let limit = get_usize(args, "limit").map(|n| n.min(100_000));
52
53 let result =
54 crate::tools::ctx_gain::handle(&action, period.as_deref(), model.as_deref(), limit);
55
56 Ok(ToolOutput {
57 text: result,
58 original_tokens: 0,
59 saved_tokens: 0,
60 mode: Some(action),
61 path: None,
62 changed: false,
63 shell_outcome: None,
64 content_blocks: None,
65 })
66 }
67}