Skip to main content

lean_ctx_server/tools/registered/
ctx_compress.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_bool};
7use lean_ctx::tool_defs::tool_def;
8
9pub struct CtxCompressTool;
10
11impl McpTool for CtxCompressTool {
12    fn name(&self) -> &'static str {
13        "ctx_compress"
14    }
15
16    fn tool_def(&self) -> Tool {
17        tool_def(
18            "ctx_compress",
19            "Compress read cache to free token budget. Does not affect session state or knowledge.\n\
20            WORKFLOW: check budget with ctx_context first, then reclaim space.",
21            json!({
22                "type": "object",
23                "properties": {
24                    "include_signatures": { "type": "boolean", "description": "Keep function/method signatures in compressed output (default: true)" }
25                }
26            }),
27        )
28    }
29
30    fn handle(
31        &self,
32        args: &Map<String, Value>,
33        ctx: &ToolContext,
34    ) -> Result<ToolOutput, ErrorData> {
35        let include_sigs = get_bool(args, "include_signatures").unwrap_or(true);
36        let cache = ctx
37            .cache
38            .as_ref()
39            .ok_or_else(|| ErrorData::internal_error("cache not available", None))?;
40        let Some(guard) = crate::server::bounded_lock::read(cache, "ctx_compress") else {
41            return Ok(ToolOutput::simple(
42                "[cache temporarily unavailable — retry in a moment]".to_string(),
43            ));
44        };
45        let result = crate::tools::ctx_compress::handle(&guard, include_sigs, ctx.crp_mode);
46        Ok(ToolOutput::simple(result))
47    }
48}