Skip to main content

lean_ctx/core/context_kernel/
mcp_e2e.rs

1//! End-to-end conformance tests for the MCP-to-kernel bridge.
2
3#[cfg(test)]
4mod tests {
5    use std::sync::{Mutex, MutexGuard};
6
7    use super::super::client_wiring::OptimizationLevel;
8    use super::super::coverage_class::CoverageClass;
9    use super::super::mcp_bridge::{self, McpCallData, McpClientInfo};
10    use super::super::mcp_coverage;
11    use super::super::mcp_receipt::{self, McpReceipt};
12    use super::super::mcp_schema_opt::{self, SchemaBudget, SchemaEntry};
13
14    static TEST_LOCK: Mutex<()> = Mutex::new(());
15
16    fn isolated_test() -> MutexGuard<'static, ()> {
17        let guard = match TEST_LOCK.lock() {
18            Ok(guard) => guard,
19            Err(poisoned) => poisoned.into_inner(),
20        };
21        mcp_bridge::reset_mcp_state();
22        mcp_receipt::reset_receipts();
23        guard
24    }
25
26    fn cursor() -> McpClientInfo {
27        McpClientInfo {
28            client_name: "cursor".to_owned(),
29            supports_roots: true,
30            supports_sampling: true,
31            tool_count: 15,
32        }
33    }
34
35    fn call(tool: &str, output_tokens: usize) -> McpCallData {
36        McpCallData {
37            tool_name: tool.to_owned(),
38            input_tokens: 1_000,
39            output_tokens,
40            is_retry: false,
41            call_number: 1,
42        }
43    }
44
45    fn receipt(tool: &str) -> McpReceipt {
46        McpReceipt {
47            tool: tool.to_owned(),
48            tokens_in: 1_000,
49            tokens_out: 400,
50            kernel_overhead: 50,
51            accepted: true,
52        }
53    }
54
55    #[test]
56    fn full_mcp_lifecycle() {
57        let _guard = isolated_test();
58        let context = mcp_bridge::process_mcp_context(&cursor());
59        assert_eq!(context.coverage, CoverageClass::FullInline);
60
61        for output_tokens in [100, 125, 150] {
62            mcp_bridge::record_mcp_call(&call("ctx_read", output_tokens));
63            mcp_receipt::record_receipt(receipt("ctx_read"));
64        }
65
66        assert!(mcp_bridge::mcp_etpao() > 0.0);
67        let accounting = mcp_receipt::mcp_accounting();
68        assert!(accounting.delivered_tokens > 0);
69    }
70
71    #[test]
72    fn schema_compression_saves_tokens() {
73        let _guard = isolated_test();
74        let schemas: Vec<SchemaEntry> = (0..10)
75            .map(|index| SchemaEntry {
76                name: format!("tool-{index}"),
77                description: "x".repeat(2000),
78                param_count: 5,
79                estimated_tokens: 600,
80                essential: false,
81            })
82            .collect();
83        let budget = SchemaBudget {
84            max_total_tokens: 3_000,
85            max_per_tool_tokens: 200,
86        };
87
88        let result = mcp_schema_opt::optimize_schemas(&schemas, &budget);
89
90        assert!(result.tokens_after < result.tokens_before);
91        assert!(result.compressed_count > 0);
92    }
93
94    #[test]
95    fn cursor_full_pipeline() {
96        let _guard = isolated_test();
97        assert_eq!(
98            mcp_coverage::detect_mcp_coverage("cursor", true, true),
99            CoverageClass::FullInline
100        );
101        assert_eq!(
102            mcp_coverage::mcp_client_profile("cursor").context_window,
103            200_000
104        );
105        assert_eq!(
106            mcp_coverage::mcp_optimization_level("cursor"),
107            OptimizationLevel::Full
108        );
109    }
110
111    #[test]
112    fn vscode_pipeline() {
113        let _guard = isolated_test();
114        assert_eq!(
115            mcp_coverage::detect_mcp_coverage("vscode", true, true),
116            CoverageClass::ContextControlled
117        );
118        assert_eq!(
119            mcp_coverage::mcp_client_profile("vscode").context_window,
120            128_000
121        );
122        assert_eq!(
123            mcp_coverage::mcp_optimization_level("vscode"),
124            OptimizationLevel::Partial
125        );
126    }
127
128    #[test]
129    fn receipt_per_tool_tracking() {
130        let _guard = isolated_test();
131        for _ in 0..5 {
132            mcp_receipt::record_receipt(receipt("ctx_read"));
133        }
134        for _ in 0..3 {
135            mcp_receipt::record_receipt(receipt("ctx_search"));
136        }
137
138        let savings = mcp_receipt::per_tool_savings();
139        assert_eq!(savings.len(), 2);
140        let read = savings
141            .iter()
142            .find(|entry| entry.tool == "ctx_read")
143            .expect("ctx_read savings must be present");
144        assert_eq!(read.calls, 5);
145    }
146
147    #[test]
148    fn etpao_tracks_mcp_calls() {
149        let _guard = isolated_test();
150        for index in 0..10 {
151            mcp_bridge::record_mcp_call(&call("ctx_read", 50 + index));
152        }
153
154        assert!(mcp_bridge::mcp_etpao() > 0.0);
155        assert_eq!(mcp_bridge::mcp_summary().total_calls, 10);
156    }
157
158    #[test]
159    fn coverage_affects_schema_budget() {
160        let _guard = isolated_test();
161        let full = mcp_schema_opt::budget_for_coverage(CoverageClass::FullInline);
162        let controlled = mcp_schema_opt::budget_for_coverage(CoverageClass::ContextControlled);
163        let observe = mcp_schema_opt::budget_for_coverage(CoverageClass::ObserveOnly);
164
165        assert!(full.max_total_tokens > observe.max_total_tokens);
166        assert_eq!(full.max_total_tokens, 12_000);
167        assert_eq!(controlled.max_total_tokens, 8_000);
168        assert_eq!(observe.max_total_tokens, 4_000);
169    }
170
171    #[test]
172    fn end_to_end_identity_to_receipt() {
173        let _guard = isolated_test();
174        let _context = mcp_bridge::process_mcp_context(&cursor());
175
176        for index in 0..5 {
177            mcp_bridge::record_mcp_call(&call("ctx_read", 100 + index));
178            mcp_receipt::record_receipt(receipt("ctx_read"));
179        }
180
181        assert_eq!(mcp_bridge::mcp_summary().total_calls, 5);
182        assert!(!mcp_receipt::per_tool_savings().is_empty());
183        assert!(mcp_receipt::total_kernel_overhead() > 0);
184    }
185}