lean_ctx_server/tools/registered/
ctx_verify.rs1use rmcp::ErrorData;
3use rmcp::model::Tool;
4use serde_json::{Map, Value, json};
5
6use crate::server::tool_trait::{McpTool, ToolContext, ToolOutput, get_str};
7use lean_ctx::tool_defs::tool_def;
8
9pub struct CtxVerifyTool;
10
11impl McpTool for CtxVerifyTool {
12 fn name(&self) -> &'static str {
13 "ctx_verify"
14 }
15
16 fn tool_def(&self) -> Tool {
17 tool_def(
18 "ctx_verify",
19 "Verification observability — tool call statistics and claim-based verification.\n\
20 WORKFLOW: action=stats to monitor tool usage; action=proof|v2 for a ContextProofV2 of runtime-checked policy claims (PathJail per touched file).\n\
21 Actions: stats (format=summary|json|both, default summary) | proof|v2 (format=summary|json, default json).\n\
22 ANTIPATTERN: not for runtime verification during active development — use for periodic audit.",
23 json!({
24 "type": "object",
25 "properties": {
26 "action": {
27 "type": "string",
28 "enum": ["stats", "proof", "v2"],
29 "description": "stats|proof|v2"
30 },
31 "format": {
32 "type": "string",
33 "enum": ["summary", "json", "both"],
34 "description": "Output format: summary|json|both (default summary)"
35 }
36 }
37 }),
38 )
39 }
40
41 fn handle(
42 &self,
43 args: &Map<String, Value>,
44 _ctx: &ToolContext,
45 ) -> Result<ToolOutput, ErrorData> {
46 let action = get_str(args, "action").unwrap_or_else(|| "stats".to_string());
47 let format = get_str(args, "format");
48 match action.as_str() {
49 "stats" => {
50 let out = crate::tools::ctx_verify::handle_stats(format.as_deref())
51 .map_err(|e| ErrorData::invalid_params(e, None))?;
52 Ok(ToolOutput {
53 text: out,
54 original_tokens: 0,
55 saved_tokens: 0,
56 mode: Some(action),
57 path: None,
58 changed: false,
59 shell_outcome: None,
60 content_blocks: None,
61 })
62 }
63 "proof" | "v2" => {
64 let out = crate::tools::ctx_verify::handle_proof(format.as_deref())
65 .map_err(|e| ErrorData::invalid_params(e, None))?;
66 Ok(ToolOutput {
67 text: out,
68 original_tokens: 0,
69 saved_tokens: 0,
70 mode: Some(action),
71 path: None,
72 changed: false,
73 shell_outcome: None,
74 content_blocks: None,
75 })
76 }
77 _ => Err(ErrorData::invalid_params(
78 "unsupported action (expected: stats, proof, v2)",
79 None,
80 )),
81 }
82 }
83}