Skip to main content

lean_ctx_server/tools/registered/
ctx_verify.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_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}