lean_ctx/server/
schema_hook.rs1use std::borrow::Cow;
4
5use crate::core::context_kernel::list_tools_opt;
6
7#[must_use]
9pub fn optimize_tools(tools: Vec<rmcp::model::Tool>, client_name: &str) -> Vec<rmcp::model::Tool> {
10 if !list_tools_opt::should_optimize_for_client(client_name) {
11 return tools;
12 }
13
14 let tuples = tools
15 .iter()
16 .map(|tool| {
17 let parameter_count = tool
18 .input_schema
19 .get("properties")
20 .and_then(serde_json::Value::as_object)
21 .map_or(0, serde_json::Map::len);
22 (
23 tool.name.to_string(),
24 tool.description.as_deref().unwrap_or("").to_owned(),
25 parameter_count,
26 )
27 })
28 .collect();
29 let optimized = list_tools_opt::optimize_descriptions(tuples, client_name);
30
31 tools
32 .into_iter()
33 .zip(optimized)
34 .map(|(mut tool, (_, description, _))| {
35 tool.description = Some(Cow::Owned(description));
36 tool
37 })
38 .collect()
39}
40
41#[must_use]
43pub fn summary() -> list_tools_opt::SchemaOptSummary {
44 list_tools_opt::schema_opt_summary()
45}
46
47#[cfg(test)]
48mod tests {
49 use std::sync::MutexGuard;
50
51 use super::list_tools_opt;
52 use crate::core::context_kernel::kernel_config::{self, KERNEL_TEST_LOCK, KernelFeatures};
53
54 fn setup() -> MutexGuard<'static, ()> {
55 let guard = KERNEL_TEST_LOCK
56 .lock()
57 .unwrap_or_else(std::sync::PoisonError::into_inner);
58 kernel_config::reset_features();
59 list_tools_opt::reset();
60 guard
61 }
62
63 #[test]
64 fn disabled_returns_same_count() {
65 let _guard = setup();
66 let features = KernelFeatures {
67 enabled: false,
68 ..KernelFeatures::default()
69 };
70 kernel_config::update_features(features);
71 let tools = vec![("tool".to_owned(), "description".to_owned(), 1)];
72
73 assert_eq!(
74 list_tools_opt::optimize_descriptions(tools, "cursor").len(),
75 1
76 );
77 }
78
79 #[test]
80 fn summary_works() {
81 let _guard = setup();
82 let summary = list_tools_opt::schema_opt_summary();
83
84 assert_eq!(summary.optimizations_applied, 0);
85 assert_eq!(summary.total_tokens_saved, 0);
86 assert_eq!(summary.avg_reduction_percent, 0.0);
87 }
88
89 #[test]
90 fn optimization_flag_check() {
91 let _guard = setup();
92
93 assert!(list_tools_opt::should_optimize_for_client("cursor"));
94 assert!(!list_tools_opt::should_optimize_for_client(
95 "unknown-client"
96 ));
97 }
98}