From d6ed20cf014f59e59f53a0e1e547f6d8adcbec89 Mon Sep 17 00:00:00 2001 From: jingfei-xu Date: Tue, 21 Oct 2025 16:20:01 -0700 Subject: [PATCH 01/11] Add Kani MCP Server for Amazon Q integration - Implement MCP server to integrate Kani with AI assistants - Add tools: verify_rust_project, verify_unsafe_code, explain_kani_failure, generate_kani_harness - Add Kani output parser - Enable Amazon Q to run Kani verification via MCP protocol --- kani-mcp-server/Cargo.toml | 19 +++ kani-mcp-server/src/kani_wrapper.rs | 212 ++++++++++++++++++++++++++++ kani-mcp-server/src/main.rs | 28 ++++ kani-mcp-server/src/mcp_server.rs | 194 +++++++++++++++++++++++++ kani-mcp-server/src/parser.rs | 121 ++++++++++++++++ kani-mcp-server/src/tools.rs | 104 ++++++++++++++ 6 files changed, 678 insertions(+) create mode 100644 kani-mcp-server/Cargo.toml create mode 100644 kani-mcp-server/src/kani_wrapper.rs create mode 100644 kani-mcp-server/src/main.rs create mode 100644 kani-mcp-server/src/mcp_server.rs create mode 100644 kani-mcp-server/src/parser.rs create mode 100644 kani-mcp-server/src/tools.rs diff --git a/kani-mcp-server/Cargo.toml b/kani-mcp-server/Cargo.toml new file mode 100644 index 00000000000..78627efe393 --- /dev/null +++ b/kani-mcp-server/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "kani-mcp-server" +version = "0.1.0" +edition = "2021" +description = "Model Context Protocol server for Kani Rust Verifier - enables AI assistants like Amazon Q to run formal verification" +license = "MIT OR Apache-2.0" + +[dependencies] +tokio = { version = "1", features = ["full"] } +serde = { version = "1", features = ["derive"] } +serde_json = "1" +anyhow = "1" +thiserror = "1" +tracing = "0.1" +tracing-subscriber = { version = "0.3", features = ["env-filter"] } +which = "6" + +[lints] +workspace = true \ No newline at end of file diff --git a/kani-mcp-server/src/kani_wrapper.rs b/kani-mcp-server/src/kani_wrapper.rs new file mode 100644 index 00000000000..956cfdc88a7 --- /dev/null +++ b/kani-mcp-server/src/kani_wrapper.rs @@ -0,0 +1,212 @@ +use anyhow::{Context, Result}; +use serde::{Deserialize, Serialize}; +use std::path::PathBuf; +use std::process::Command; +use tracing::{debug, info, warn}; + +/// Configuration options for running Kani verification +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct KaniOptions { + /// Path to the Rust project to verify + pub path: PathBuf, + + /// Specific harness to run (e.g., "module::function") + pub harness: Option, + + /// Run all tests as verification harnesses + pub tests: bool, + + /// Output format: regular, terse, old, json + pub output_format: String, + + /// Enable unstable Kani features + pub enable_unstable: Vec, + + /// Additional arguments to pass to Kani + pub extra_args: Vec, + + /// Enable concrete playback for counterexamples + pub concrete_playback: bool, + + /// Enable coverage information + pub coverage: bool, +} + +impl Default for KaniOptions { + fn default() -> Self { + Self { + path: PathBuf::from("."), + harness: None, + tests: false, + output_format: "terse".to_string(), + enable_unstable: vec![], + extra_args: vec![], + concrete_playback: false, + coverage: false, + } + } +} + +/// Result of a Kani verification run +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct VerificationResult { + /// Whether verification succeeded + pub success: bool, + + /// Human-readable summary + pub summary: String, + + /// List of harness results + pub harnesses: Vec, + + /// Failed checks with details + pub failed_checks: Vec, + + /// Verification time in seconds + pub verification_time: Option, + + /// Raw output from Kani + pub raw_output: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct HarnessResult { + pub name: String, + pub status: String, + pub checks_passed: u32, + pub checks_failed: u32, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct FailedCheck { + pub description: String, + pub file: String, + pub line: Option, + pub function: String, +} + +/// Wrapper around cargo-kani for executing verification +pub struct KaniWrapper { + cargo_kani_path: PathBuf, +} + +impl KaniWrapper { + /// Create a new KaniWrapper, finding cargo-kani in PATH + pub fn new() -> Result { + let cargo_kani = which::which("cargo-kani") + .context("cargo-kani not found in PATH. Please install Kani:\n cargo install --locked kani-verifier\n cargo kani setup")?; + + info!("✓ Found cargo-kani at: {:?}", cargo_kani); + Ok(Self { + cargo_kani_path: cargo_kani, + }) + } + + /// Run Kani verification with the given options + pub async fn verify(&self, options: KaniOptions) -> Result { + info!("Starting Kani verification on: {:?}", options.path); + + if !options.path.exists() { + anyhow::bail!("Path does not exist: {:?}", options.path); + } + + // Build the command + let mut cmd = Command::new(&self.cargo_kani_path); + cmd.arg("kani"); + cmd.current_dir(&options.path); + + // Add harness filter + if let Some(harness) = &options.harness { + cmd.arg("--harness").arg(harness); + info!(" Filtering to harness: {}", harness); + } + + // Run tests as harnesses + if options.tests { + cmd.arg("--tests"); + info!(" Running all tests as harnesses"); + } + + // Set output format + if !options.output_format.is_empty() { + cmd.arg(format!("--output-format={}", options.output_format)); + } + + // Enable unstable features + for feature in &options.enable_unstable { + cmd.arg("--enable-unstable").arg(feature); + } + + // Concrete playback + if options.concrete_playback { + cmd.arg("-Z").arg("concrete-playback"); + cmd.arg("--concrete-playback=print"); + } + + // Coverage + if options.coverage { + cmd.arg("--coverage"); + } + + // Extra arguments + for arg in &options.extra_args { + cmd.arg(arg); + } + + debug!("Executing command: {:?}", cmd); + + // Execute and capture output + let start = std::time::Instant::now(); + let output = cmd.output() + .context("Failed to execute cargo-kani. Is it installed?")?; + let duration = start.elapsed(); + + let stdout = String::from_utf8_lossy(&output.stdout).to_string(); + let stderr = String::from_utf8_lossy(&output.stderr).to_string(); + let combined_output = format!("{}\n{}", stdout, stderr); + + debug!("Kani completed in {:.2}s", duration.as_secs_f64()); + + if !stderr.is_empty() && stderr.contains("error") { + warn!("Kani stderr: {}", stderr); + } + + // Parse the output + let result = self.parse_output(&combined_output, output.status.success())?; + + info!("Verification complete: {}", result.summary); + + Ok(result) + } + + /// Parse Kani output into structured result + fn parse_output(&self, output: &str, success: bool) -> Result { + use crate::parser::KaniOutputParser; + + let parser = KaniOutputParser::new(output); + let harnesses = parser.parse_harnesses(); + let failed_checks = parser.parse_failed_checks(); + let verification_time = parser.parse_verification_time(); + + let total_harnesses = harnesses.len(); + let failed_harnesses = harnesses.iter() + .filter(|h| h.status == "FAILED") + .count(); + + let summary = if success { + format!("✅ Verification successful! {} harness(es) verified.", total_harnesses) + } else { + format!("❌ Verification failed. {}/{} harness(es) failed with {} check failure(s).", + failed_harnesses, total_harnesses, failed_checks.len()) + }; + + Ok(VerificationResult { + success, + summary, + harnesses, + failed_checks, + verification_time, + raw_output: output.to_string(), + }) + } +} \ No newline at end of file diff --git a/kani-mcp-server/src/main.rs b/kani-mcp-server/src/main.rs new file mode 100644 index 00000000000..d08fa777cc3 --- /dev/null +++ b/kani-mcp-server/src/main.rs @@ -0,0 +1,28 @@ +mod kani_wrapper; +mod mcp_server; +mod parser; +mod tools; + +use anyhow::Result; +use tracing_subscriber::EnvFilter; + +#[tokio::main] +async fn main() -> Result<()> { + // Initialize logging + tracing_subscriber::fmt() + .with_env_filter( + EnvFilter::from_default_env() + .add_directive("kani_mcp_server=info".parse()?) + ) + .init(); + + println!("🚀 Kani MCP Server - Model Context Protocol for Kani Rust Verifier"); + println!("📋 Purpose: Enable AI assistants like Amazon Q to run Kani verification"); + println!(); + + // Create and run server + let server = mcp_server::KaniMcpServer::new()?; + server.run().await?; + + Ok(()) +} \ No newline at end of file diff --git a/kani-mcp-server/src/mcp_server.rs b/kani-mcp-server/src/mcp_server.rs new file mode 100644 index 00000000000..9bd1f0b6c85 --- /dev/null +++ b/kani-mcp-server/src/mcp_server.rs @@ -0,0 +1,194 @@ +use crate::kani_wrapper::{KaniOptions, KaniWrapper, VerificationResult}; +use crate::tools::{get_kani_tools, ToolResult}; +use anyhow::Result; +use std::path::PathBuf; +use std::sync::Arc; +use tokio::sync::Mutex; +use tracing::{error, info}; + +/// Main MCP server for Kani integration +pub struct KaniMcpServer { + kani: Arc, + last_result: Arc>>, +} + +impl KaniMcpServer { + /// Create a new Kani MCP server + pub fn new() -> Result { + let kani = Arc::new(KaniWrapper::new()?); + Ok(Self { + kani, + last_result: Arc::new(Mutex::new(None)), + }) + } + + /// Run the MCP server + pub async fn run(self) -> Result<()> { + info!("═══════════════════════════════════════════════════════════"); + info!(" Kani MCP Server - Ready for Amazon Q Integration"); + info!("═══════════════════════════════════════════════════════════"); + info!(""); + info!("📋 Available Tools:"); + + for tool in get_kani_tools() { + info!(" • {} - {}", tool.name, tool.description); + } + + info!(""); + info!("🔗 Connection: stdio (Standard Input/Output)"); + info!("🤖 Compatible with: Amazon Q, Claude Desktop, Cursor, etc."); + info!(""); + info!("⚡ Server is ready and waiting for requests..."); + info!(" Press Ctrl+C to stop"); + info!(""); + + // In a real MCP implementation, you would: + // 1. Listen for JSON-RPC messages on stdin + // 2. Parse the messages according to MCP protocol + // 3. Call the appropriate handler methods + // 4. Send responses to stdout + // + // For now, this is a skeleton that demonstrates the structure + + // Keep server alive + tokio::signal::ctrl_c().await?; + info!(""); + info!("🛑 Shutting down Kani MCP Server..."); + + Ok(()) + } + + /// Handle verify_rust_project tool call + pub async fn handle_verify_project( + &self, + path: String, + harness: Option, + tests: bool, + output_format: Option, + ) -> Result { + info!("🔍 Tool called: verify_rust_project"); + info!(" Path: {}", path); + + let options = KaniOptions { + path: PathBuf::from(path), + harness: harness.clone(), + tests, + output_format: output_format.unwrap_or_else(|| "terse".to_string()), + ..Default::default() + }; + + match self.kani.verify(options).await { + Ok(result) => { + // Store result for later reference + *self.last_result.lock().await = Some(result.clone()); + + Ok(ToolResult { + success: result.success, + data: serde_json::to_value(result)?, + error: None, + }) + } + Err(e) => { + error!("Verification error: {}", e); + Ok(ToolResult { + success: false, + data: serde_json::json!({}), + error: Some(e.to_string()), + }) + } + } + } + + /// Handle verify_unsafe_code tool call + pub async fn handle_verify_unsafe( + &self, + path: String, + harness: String, + ) -> Result { + info!("🔍 Tool called: verify_unsafe_code"); + + // This is essentially the same as verify_project but focused on unsafe code + self.handle_verify_project(path, Some(harness), false, Some("terse".to_string())).await + } + + /// Handle explain_kani_failure tool call + pub async fn handle_explain_failure(&self, raw_output: String) -> Result { + info!("🔍 Tool called: explain_kani_failure"); + + use crate::parser::KaniOutputParser; + + let parser = KaniOutputParser::new(&raw_output); + let failed_checks = parser.parse_failed_checks(); + let harnesses = parser.parse_harnesses(); + + let explanation = format!( + "Kani verification failed with {} issue(s):\n\n{}", + failed_checks.len(), + failed_checks.iter() + .map(|check| format!( + "• {} at {}:{} in {}", + check.description, + check.file, + check.line.map(|l| l.to_string()).unwrap_or_else(|| "?".to_string()), + check.function + )) + .collect::>() + .join("\n") + ); + + Ok(ToolResult { + success: true, + data: serde_json::json!({ + "explanation": explanation, + "failed_checks": failed_checks, + "harnesses": harnesses, + }), + error: None, + }) + } + + /// Handle generate_kani_harness tool call + pub async fn handle_generate_harness( + &self, + function_name: String, + properties: Vec, + ) -> Result { + info!("🔍 Tool called: generate_kani_harness"); + + let harness_code = format!( +r#"#[cfg(kani)] +mod verification {{ + use super::*; + + #[kani::proof] + fn verify_{}_properties() {{ + // Generate symbolic inputs + let input = kani::any(); + + // Call the function under test + let result = {}(input); + + // Verify properties: +{} + }} +}} +"#, + function_name.replace("::", "_"), + function_name, + properties.iter() + .map(|prop| format!(" // TODO: Add assertion for: {}", prop)) + .collect::>() + .join("\n") + ); + + Ok(ToolResult { + success: true, + data: serde_json::json!({ + "harness_code": harness_code, + "function_name": function_name, + "properties": properties, + }), + error: None, + }) + } +} \ No newline at end of file diff --git a/kani-mcp-server/src/parser.rs b/kani-mcp-server/src/parser.rs new file mode 100644 index 00000000000..c2cd81ef432 --- /dev/null +++ b/kani-mcp-server/src/parser.rs @@ -0,0 +1,121 @@ +use crate::kani_wrapper::{FailedCheck, HarnessResult}; + +/// Parser for Kani output format +pub struct KaniOutputParser<'a> { + output: &'a str, +} + +impl<'a> KaniOutputParser<'a> { + pub fn new(output: &'a str) -> Self { + Self { output } + } + + /// Parse harness results from output + pub fn parse_harnesses(&self) -> Vec { + let mut harnesses = Vec::new(); + let mut current_harness: Option = None; + + for line in self.output.lines() { + // Detect harness start: "Checking harness module::function..." + if line.contains("Checking harness") { + if let Some(name_part) = line.split("Checking harness").nth(1) { + current_harness = Some(name_part.trim().trim_end_matches("...").to_string()); + } + } + + // Detect harness completion + if line.contains("VERIFICATION") { + if let Some(name) = current_harness.take() { + let status = if line.contains("SUCCESSFUL") { + "SUCCESS" + } else if line.contains("FAILED") { + "FAILED" + } else { + "UNKNOWN" + }.to_string(); + + harnesses.push(HarnessResult { + name, + status, + checks_passed: 0, + checks_failed: 0, + }); + } + } + } + + harnesses + } + + /// Parse failed checks from output + pub fn parse_failed_checks(&self) -> Vec { + let mut failed_checks = Vec::new(); + let mut in_failed_section = false; + + for line in self.output.lines() { + if line.contains("Failed Checks:") { + in_failed_section = true; + continue; + } + + if in_failed_section { + // Stop at empty line or next section + if line.trim().is_empty() || line.starts_with("VERIFICATION") { + in_failed_section = false; + continue; + } + + // Parse failed check line + // Format: "description File: "path", line X, in function" + let description = line.split("File:").next() + .unwrap_or(line) + .trim() + .to_string(); + + let (file, line_num, function) = if let Some(file_part) = line.split("File:").nth(1) { + let parts: Vec<&str> = file_part.split(',').collect(); + let file = parts.get(0) + .map(|s| s.trim().trim_matches('"').to_string()) + .unwrap_or_else(|| "unknown".to_string()); + + let line_num = parts.get(1) + .and_then(|s| s.split_whitespace().nth(1)) + .and_then(|s| s.parse::().ok()); + + let function = parts.get(2) + .and_then(|s| s.split("in").nth(1)) + .map(|s| s.trim().to_string()) + .unwrap_or_else(|| "unknown".to_string()); + + (file, line_num, function) + } else { + ("unknown".to_string(), None, "unknown".to_string()) + }; + + failed_checks.push(FailedCheck { + description, + file, + line: line_num, + function, + }); + } + } + + failed_checks + } + + /// Parse verification time from output + pub fn parse_verification_time(&self) -> Option { + for line in self.output.lines() { + if line.contains("Verification Time:") { + if let Some(time_str) = line.split(':').nth(1) { + return time_str.trim() + .trim_end_matches('s') + .parse::() + .ok(); + } + } + } + None + } +} \ No newline at end of file diff --git a/kani-mcp-server/src/tools.rs b/kani-mcp-server/src/tools.rs new file mode 100644 index 00000000000..b7f685448ff --- /dev/null +++ b/kani-mcp-server/src/tools.rs @@ -0,0 +1,104 @@ +use serde::{Deserialize, Serialize}; +use serde_json::{json, Value}; + +/// Definition of an MCP tool +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ToolDefinition { + pub name: String, + pub description: String, + pub input_schema: Value, +} + +/// Get all available Kani MCP tools +pub fn get_kani_tools() -> Vec { + vec![ + ToolDefinition { + name: "verify_rust_project".to_string(), + description: "Run Kani verification on a Rust project to prove safety properties and check for undefined behavior. Kani uses formal verification to mathematically prove correctness.".to_string(), + input_schema: json!({ + "type": "object", + "properties": { + "path": { + "type": "string", + "description": "Absolute path to the Rust project directory (must contain Cargo.toml)" + }, + "harness": { + "type": "string", + "description": "Optional: Specific proof harness to verify (e.g., 'module::verify::check_bounds')" + }, + "tests": { + "type": "boolean", + "description": "If true, verify all #[test] functions as proof harnesses", + "default": false + }, + "output_format": { + "type": "string", + "enum": ["regular", "terse", "old"], + "default": "terse", + "description": "Output format for verification results" + } + }, + "required": ["path"] + }), + }, + ToolDefinition { + name: "verify_unsafe_code".to_string(), + description: "Specifically verify unsafe Rust code blocks for memory safety violations including null pointer dereferences, buffer overflows, and use-after-free bugs.".to_string(), + input_schema: json!({ + "type": "object", + "properties": { + "path": { + "type": "string", + "description": "Path to Rust project containing unsafe code" + }, + "harness": { + "type": "string", + "description": "Harness function that tests the unsafe code" + } + }, + "required": ["path", "harness"] + }), + }, + ToolDefinition { + name: "explain_kani_failure".to_string(), + description: "Analyze and explain why a Kani verification failed, providing details about counterexamples and suggested fixes.".to_string(), + input_schema: json!({ + "type": "object", + "properties": { + "raw_output": { + "type": "string", + "description": "Raw Kani verification output to analyze" + } + }, + "required": ["raw_output"] + }), + }, + ToolDefinition { + name: "generate_kani_harness".to_string(), + description: "Generate a Kani proof harness template for verifying a specific Rust function.".to_string(), + input_schema: json!({ + "type": "object", + "properties": { + "function_name": { + "type": "string", + "description": "Name of the function to verify" + }, + "properties": { + "type": "array", + "items": {"type": "string"}, + "description": "List of properties to verify (e.g., 'no_panic', 'bounds_check', 'overflow_check')" + } + }, + "required": ["function_name"] + }), + }, + ] +} + +/// Tool handler results +#[derive(Debug, Serialize, Deserialize)] +pub struct ToolResult { + pub success: bool, + pub data: Value, + pub error: Option, +} \ No newline at end of file From 9e9d46acddb34628bc147b2b67e59c19f222e625 Mon Sep 17 00:00:00 2001 From: jingfei-xu Date: Wed, 22 Oct 2025 19:30:33 -0700 Subject: [PATCH 02/11] Add Kani MCP server and Amazon Q complete implementation --- kani-mcp-server/src/kani_wrapper.rs | 4 +- kani-mcp-server/src/main.rs | 4 +- kani-mcp-server/src/mcp_server.rs | 302 ++++++++++++++++++++++++--- kani-mcp-server/src/parser.rs | 309 ++++++++++++++++++++++++---- 4 files changed, 544 insertions(+), 75 deletions(-) diff --git a/kani-mcp-server/src/kani_wrapper.rs b/kani-mcp-server/src/kani_wrapper.rs index 956cfdc88a7..629d4d1a90a 100644 --- a/kani-mcp-server/src/kani_wrapper.rs +++ b/kani-mcp-server/src/kani_wrapper.rs @@ -194,9 +194,9 @@ impl KaniWrapper { .count(); let summary = if success { - format!("✅ Verification successful! {} harness(es) verified.", total_harnesses) + format!("Verification successful! {} harness(es) verified.", total_harnesses) } else { - format!("❌ Verification failed. {}/{} harness(es) failed with {} check failure(s).", + format!("Verification failed. {}/{} harness(es) failed with {} check failure(s).", failed_harnesses, total_harnesses, failed_checks.len()) }; diff --git a/kani-mcp-server/src/main.rs b/kani-mcp-server/src/main.rs index d08fa777cc3..d302c320caa 100644 --- a/kani-mcp-server/src/main.rs +++ b/kani-mcp-server/src/main.rs @@ -16,8 +16,8 @@ async fn main() -> Result<()> { ) .init(); - println!("🚀 Kani MCP Server - Model Context Protocol for Kani Rust Verifier"); - println!("📋 Purpose: Enable AI assistants like Amazon Q to run Kani verification"); + println!("Kani MCP Server - Model Context Protocol for Kani Rust Verifier"); + println!("Purpose: Enable AI assistants like Amazon Q to run Kani verification"); println!(); // Create and run server diff --git a/kani-mcp-server/src/mcp_server.rs b/kani-mcp-server/src/mcp_server.rs index 9bd1f0b6c85..e9a35a1b2d0 100644 --- a/kani-mcp-server/src/mcp_server.rs +++ b/kani-mcp-server/src/mcp_server.rs @@ -28,36 +28,273 @@ impl KaniMcpServer { info!(" Kani MCP Server - Ready for Amazon Q Integration"); info!("═══════════════════════════════════════════════════════════"); info!(""); - info!("📋 Available Tools:"); + info!("Available Tools:"); for tool in get_kani_tools() { info!(" • {} - {}", tool.name, tool.description); } info!(""); - info!("🔗 Connection: stdio (Standard Input/Output)"); - info!("🤖 Compatible with: Amazon Q, Claude Desktop, Cursor, etc."); + info!("Connection: stdio (Standard Input/Output)"); + info!("Compatible with: Amazon Q, Claude Desktop, Cursor, etc."); info!(""); - info!("⚡ Server is ready and waiting for requests..."); - info!(" Press Ctrl+C to stop"); + info!("Server is ready and waiting for requests..."); info!(""); - // In a real MCP implementation, you would: - // 1. Listen for JSON-RPC messages on stdin - // 2. Parse the messages according to MCP protocol - // 3. Call the appropriate handler methods - // 4. Send responses to stdout - // - // For now, this is a skeleton that demonstrates the structure + // Read from stdin and respond via stdout (MCP protocol) + use tokio::io::{AsyncBufReadExt, BufReader, stdin}; + + let stdin = stdin(); + let reader = BufReader::new(stdin); + let mut lines = reader.lines(); + + while let Ok(Some(line)) = lines.next_line().await { + if line.trim().is_empty() { + continue; + } + + // Parse JSON-RPC request + match serde_json::from_str::(&line) { + Ok(request) => { + let response = self.handle_mcp_request(request).await; + + // Send response to stdout + if let Ok(response_str) = serde_json::to_string(&response) { + println!("{}", response_str); + } + } + Err(e) => { + error!("Failed to parse request: {}", e); + } + } + } - // Keep server alive - tokio::signal::ctrl_c().await?; info!(""); - info!("🛑 Shutting down Kani MCP Server..."); + info!("Shutting down Kani MCP Server..."); Ok(()) } + /// Handle MCP protocol requests + async fn handle_mcp_request(&self, request: serde_json::Value) -> serde_json::Value { + use serde_json::json; + + let method = request["method"].as_str().unwrap_or(""); + let id = request["id"].clone(); + + match method { + "initialize" => { + info!("📥 Received: initialize"); + json!({ + "jsonrpc": "2.0", + "id": id, + "result": { + "protocolVersion": "2024-11-05", + "capabilities": { + "tools": {} + }, + "serverInfo": { + "name": "kani-mcp-server", + "version": "0.1.0" + } + } + }) + } + "tools/list" => { + info!("Received: tools/list"); + let tools: Vec<_> = get_kani_tools() + .iter() + .map(|tool| { + json!({ + "name": tool.name, + "description": tool.description, + "inputSchema": tool.input_schema + }) + }) + .collect(); + + json!({ + "jsonrpc": "2.0", + "id": id, + "result": { + "tools": tools + } + }) + } + "tools/call" => { + let tool_name = request["params"]["name"].as_str().unwrap_or(""); + let arguments = &request["params"]["arguments"]; + + info!("Received: tools/call - {}", tool_name); + + let result = self.execute_tool(tool_name, arguments).await; + + json!({ + "jsonrpc": "2.0", + "id": id, + "result": result + }) + } + _ => { + error!("Unknown method: {}", method); + json!({ + "jsonrpc": "2.0", + "id": id, + "error": { + "code": -32601, + "message": format!("Method not found: {}", method) + } + }) + } + } + } + + /// Execute a specific tool + async fn execute_tool(&self, tool_name: &str, arguments: &serde_json::Value) -> serde_json::Value { + use serde_json::json; + + match tool_name { + "verify_rust_project" => { + let path = arguments["path"].as_str().unwrap_or("."); + let harness = arguments["harness"].as_str().map(String::from); + let tests = arguments["tests"].as_bool().unwrap_or(false); + let output_format = arguments["output_format"].as_str().map(String::from); + + match self.handle_verify_project( + path.to_string(), + harness, + tests, + output_format, + ).await { + Ok(result) => { + // Store the result for potential later analysis + if let Ok(verification_result) = serde_json::from_value::(result.data.clone()) { + *self.last_result.lock().await = Some(verification_result); + } + + json!({ + "content": [{ + "type": "text", + "text": serde_json::to_string_pretty(&result.data).unwrap_or_default() + }] + }) + } + Err(e) => { + json!({ + "content": [{ + "type": "text", + "text": format!("Error: {}", e) + }], + "isError": true + }) + } + } + } + "verify_unsafe_code" => { + let path = arguments["path"].as_str().unwrap_or(".").to_string(); + let harness = arguments["harness"].as_str().unwrap_or("").to_string(); + + match self.handle_verify_unsafe(path, harness).await { + Ok(result) => { + json!({ + "content": [{ + "type": "text", + "text": serde_json::to_string_pretty(&result.data).unwrap_or_default() + }] + }) + } + Err(e) => { + json!({ + "content": [{ + "type": "text", + "text": format!("Error: {}", e) + }], + "isError": true + }) + } + } + } + "explain_kani_failure" => { + // Try to get raw output from arguments or from last result + let raw_output = if let Some(output_str) = arguments["raw_output"].as_str() { + output_str.to_string() + } else { + // Use the last verification result if available + let last = self.last_result.lock().await; + last.as_ref() + .map(|r| r.raw_output.clone()) + .unwrap_or_default() + }; + + if raw_output.is_empty() { + return json!({ + "content": [{ + "type": "text", + "text": "No verification output available. Please run a verification first." + }], + "isError": true + }); + } + + match self.handle_explain_failure(raw_output).await { + Ok(result) => { + json!({ + "content": [{ + "type": "text", + "text": result.data["detailed_explanation"].as_str().unwrap_or("No explanation available") + }] + }) + } + Err(e) => { + json!({ + "content": [{ + "type": "text", + "text": format!("Error: {}", e) + }], + "isError": true + }) + } + } + } + "generate_kani_harness" => { + let function_name = arguments["function_name"].as_str().unwrap_or("").to_string(); + let properties = arguments["properties"] + .as_array() + .map(|arr| arr.iter().filter_map(|v| v.as_str().map(String::from)).collect()) + .unwrap_or_else(Vec::new); + + match self.handle_generate_harness(function_name, properties).await { + Ok(result) => { + json!({ + "content": [{ + "type": "text", + "text": result.data["harness_code"].as_str().unwrap_or("") + }] + }) + } + Err(e) => { + json!({ + "content": [{ + "type": "text", + "text": format!("Error: {}", e) + }], + "isError": true + }) + } + } + } + _ => { + json!({ + "content": [{ + "type": "text", + "text": format!("Unknown tool: {}", tool_name) + }], + "isError": true + }) + } + } + } + /// Handle verify_rust_project tool call pub async fn handle_verify_project( &self, @@ -105,43 +342,40 @@ impl KaniMcpServer { path: String, harness: String, ) -> Result { - info!("🔍 Tool called: verify_unsafe_code"); + info!("Tool called: verify_unsafe_code"); // This is essentially the same as verify_project but focused on unsafe code self.handle_verify_project(path, Some(harness), false, Some("terse".to_string())).await } - /// Handle explain_kani_failure tool call + /// Handle explain_kani_failure tool call with enhanced analysis pub async fn handle_explain_failure(&self, raw_output: String) -> Result { - info!("🔍 Tool called: explain_kani_failure"); + info!("Tool called: explain_kani_failure"); use crate::parser::KaniOutputParser; let parser = KaniOutputParser::new(&raw_output); let failed_checks = parser.parse_failed_checks(); let harnesses = parser.parse_harnesses(); - - let explanation = format!( - "Kani verification failed with {} issue(s):\n\n{}", - failed_checks.len(), - failed_checks.iter() - .map(|check| format!( - "• {} at {}:{} in {}", - check.description, - check.file, - check.line.map(|l| l.to_string()).unwrap_or_else(|| "?".to_string()), - check.function - )) - .collect::>() - .join("\n") - ); + let counterexamples = parser.parse_counterexamples(); + let code_context = parser.extract_code_context(); + + // Generate comprehensive explanation + let detailed_explanation = parser.generate_detailed_explanation(); Ok(ToolResult { success: true, data: serde_json::json!({ - "explanation": explanation, + "detailed_explanation": detailed_explanation, "failed_checks": failed_checks, "harnesses": harnesses, + "counterexamples": counterexamples, + "code_context": code_context, + "summary": format!( + "Found {} failure(s) across {} harness(es)", + failed_checks.len(), + harnesses.len() + ) }), error: None, }) diff --git a/kani-mcp-server/src/parser.rs b/kani-mcp-server/src/parser.rs index c2cd81ef432..9a86fc6d86e 100644 --- a/kani-mcp-server/src/parser.rs +++ b/kani-mcp-server/src/parser.rs @@ -47,11 +47,22 @@ impl<'a> KaniOutputParser<'a> { harnesses } - /// Parse failed checks from output + /// Parse failed checks from output with detailed information pub fn parse_failed_checks(&self) -> Vec { let mut failed_checks = Vec::new(); - let mut in_failed_section = false; + + for line in self.output.lines() { + // Look for "Check N: ..." followed by "- Status: FAILURE" + if line.contains("Check ") && line.contains(":") { + let check_info = self.parse_single_check(line); + if let Some(check) = check_info { + failed_checks.push(check); + } + } + } + // Also parse from "Failed Checks:" section + let mut in_failed_section = false; for line in self.output.lines() { if line.contains("Failed Checks:") { in_failed_section = true; @@ -59,49 +70,121 @@ impl<'a> KaniOutputParser<'a> { } if in_failed_section { - // Stop at empty line or next section if line.trim().is_empty() || line.starts_with("VERIFICATION") { - in_failed_section = false; - continue; + break; } - // Parse failed check line - // Format: "description File: "path", line X, in function" - let description = line.split("File:").next() - .unwrap_or(line) + // Parse format: "description File: "path", line X, in function" + if let Some(check) = self.parse_failed_check_line(line) { + // Avoid duplicates + if !failed_checks.iter().any(|c| c.description == check.description && c.line == check.line) { + failed_checks.push(check); + } + } + } + } + + failed_checks + } + + /// Parse a single check result line + fn parse_single_check(&self, line: &str) -> Option { + // Format: "Check 1: function.assertion.1" + // " - Status: FAILURE" + // " - Description: "Oh no, a failing corner case!"" + // " - Location: ./path/file.rs:14:13 in function func_name" + + let check_num = line.split("Check").nth(1)?.split(':').next()?.trim(); + + // Look for the next few lines to get details + let lines: Vec<&str> = self.output.lines().collect(); + let current_idx = lines.iter().position(|l| *l == line)?; + + let mut description = String::new(); + let mut file = String::new(); + let mut line_num = None; + let mut function = String::new(); + let mut is_failure = false; + + // Parse the next few lines for details + for i in (current_idx + 1)..(current_idx + 5).min(lines.len()) { + let detail_line = lines[i]; + + if detail_line.contains("- Status: FAILURE") { + is_failure = true; + } + + if detail_line.contains("- Description:") { + description = detail_line.split("- Description:") + .nth(1)? .trim() + .trim_matches('"') .to_string(); - - let (file, line_num, function) = if let Some(file_part) = line.split("File:").nth(1) { - let parts: Vec<&str> = file_part.split(',').collect(); - let file = parts.get(0) - .map(|s| s.trim().trim_matches('"').to_string()) - .unwrap_or_else(|| "unknown".to_string()); - - let line_num = parts.get(1) - .and_then(|s| s.split_whitespace().nth(1)) - .and_then(|s| s.parse::().ok()); - - let function = parts.get(2) - .and_then(|s| s.split("in").nth(1)) - .map(|s| s.trim().to_string()) - .unwrap_or_else(|| "unknown".to_string()); - - (file, line_num, function) - } else { - ("unknown".to_string(), None, "unknown".to_string()) - }; - - failed_checks.push(FailedCheck { - description, - file, - line: line_num, - function, - }); + } + + if detail_line.contains("- Location:") { + let location = detail_line.split("- Location:").nth(1)?.trim(); + // Format: "./path/file.rs:14:13 in function func_name" + let parts: Vec<&str> = location.split(" in function ").collect(); + + if let Some(file_part) = parts.first() { + let file_line: Vec<&str> = file_part.split(':').collect(); + file = file_line.first()?.trim_start_matches("./").to_string(); + if let Some(ln) = file_line.get(1) { + line_num = ln.parse().ok(); + } + } + + if let Some(func_part) = parts.get(1) { + function = func_part.trim().to_string(); + } } } - failed_checks + if is_failure { + Some(FailedCheck { + description, + file, + line: line_num, + function, + }) + } else { + None + } + } + + /// Parse a line from the "Failed Checks:" section + fn parse_failed_check_line(&self, line: &str) -> Option { + // Format: "description File: "path", line X, in function" + let description = line.split("File:").next()?.trim().to_string(); + + if let Some(file_part) = line.split("File:").nth(1) { + let parts: Vec<&str> = file_part.split(',').collect(); + + let file = parts.first()? + .trim() + .trim_matches('"') + .trim_start_matches("./") + .to_string(); + + let line_num = parts.get(1) + .and_then(|s| s.split_whitespace().nth(1)) + .and_then(|s| s.parse::().ok()); + + let function = parts.get(2) + .and_then(|s| s.split("in").nth(1)) + .map(|s| s.trim().to_string()) + .unwrap_or_else(|| "unknown".to_string()); + + return Some(FailedCheck { + description, + file, + line: line_num, + function, + }); + } + + None } /// Parse verification time from output @@ -118,4 +201,156 @@ impl<'a> KaniOutputParser<'a> { } None } + + /// Extract counterexamples from output + pub fn parse_counterexamples(&self) -> Vec { + let mut counterexamples = Vec::new(); + + for line in self.output.lines() { + // Look for SAT checker results or counterexample traces + if line.contains("SAT checker: instance is SATISFIABLE") { + counterexamples.push("Counterexample found (inputs exist that violate the property)".to_string()); + } + + // Look for specific variable assignments in traces + if line.contains("Violated property:") || line.contains("Counterexample:") { + counterexamples.push(line.trim().to_string()); + } + } + + counterexamples + } + + /// Extract code context from output + pub fn extract_code_context(&self) -> Option { + // Kani sometimes shows code snippets in output + for line in self.output.lines() { + if line.contains("-->") && line.contains(".rs:") { + return Some(line.trim().to_string()); + } + } + None + } + + /// Generate detailed failure explanation + pub fn generate_detailed_explanation(&self) -> String { + let failed_checks = self.parse_failed_checks(); + let counterexamples = self.parse_counterexamples(); + let harnesses = self.parse_harnesses(); + let verification_time = self.parse_verification_time(); + + let mut explanation = String::new(); + + explanation.push_str("DETAILED KANI VERIFICATION FAILURE ANALYSIS\n"); + explanation.push_str("═══════════════════════════════════════════════\n\n"); + + // Summary + explanation.push_str(&format!("Summary:\n")); + explanation.push_str(&format!(" • Total harnesses: {}\n", harnesses.len())); + explanation.push_str(&format!(" • Failed checks: {}\n", failed_checks.len())); + if let Some(time) = verification_time { + explanation.push_str(&format!(" • Verification time: {:.3}s\n", time)); + } + explanation.push_str("\n"); + + // Failed checks detail + if !failed_checks.is_empty() { + explanation.push_str("FAILED CHECKS:\n\n"); + + for (i, check) in failed_checks.iter().enumerate() { + explanation.push_str(&format!("{}. {}\n", i + 1, check.description)); + explanation.push_str(&format!(" Location: {}:{}\n", + check.file, + check.line.map(|l| l.to_string()).unwrap_or_else(|| "?".to_string()) + )); + explanation.push_str(&format!(" Function: {}\n", check.function)); + explanation.push_str("\n"); + } + } + + // Counterexamples + if !counterexamples.is_empty() { + explanation.push_str("COUNTEREXAMPLES:\n\n"); + for ce in counterexamples { + explanation.push_str(&format!(" • {}\n", ce)); + } + explanation.push_str("\n"); + } + + // Root cause analysis + explanation.push_str("ROOT CAUSE ANALYSIS:\n\n"); + if !failed_checks.is_empty() { + let first_check = &failed_checks[0]; + + explanation.push_str(&format!("The assertion '{}' failed, which indicates:\n", first_check.description)); + + // Pattern-based analysis + if first_check.description.contains("overflow") { + explanation.push_str(" • An arithmetic overflow occurred\n"); + explanation.push_str(" • The operation exceeded the maximum value for the type\n"); + explanation.push_str(" • This happens with certain input combinations\n"); + } else if first_check.description.contains("panic") { + explanation.push_str(" • The code panicked during execution\n"); + explanation.push_str(" • An unhandled error condition was reached\n"); + } else if first_check.description.contains("assertion") { + explanation.push_str(" • A programmer-defined assertion failed\n"); + explanation.push_str(" • The expected property does not hold for all inputs\n"); + } else if first_check.description.contains("dereference") { + explanation.push_str(" • An invalid pointer dereference occurred\n"); + explanation.push_str(" • Accessing memory that shouldn't be accessed\n"); + } else if first_check.description.contains("index") || first_check.description.contains("bounds") { + explanation.push_str(" • An array/slice index is out of bounds\n"); + explanation.push_str(" • Accessing beyond the valid range of the collection\n"); + } else { + explanation.push_str(" • A safety or correctness property was violated\n"); + explanation.push_str(" • The code doesn't handle all possible input cases correctly\n"); + } + explanation.push_str("\n"); + } + + // Suggested fixes + explanation.push_str("SUGGESTED FIXES:\n\n"); + if !failed_checks.is_empty() { + let first_check = &failed_checks[0]; + + if first_check.description.contains("overflow") { + explanation.push_str(" 1. Use checked arithmetic operations:\n"); + explanation.push_str(" • Replace `a + b` with `a.checked_add(b)`\n"); + explanation.push_str(" • Handle the `None` case appropriately\n"); + explanation.push_str(" 2. Or use saturating arithmetic:\n"); + explanation.push_str(" • Replace with `a.saturating_add(b)`\n"); + explanation.push_str(" 3. Add input validation:\n"); + explanation.push_str(" • Use `kani::assume()` to constrain inputs\n"); + } else if first_check.description.contains("dereference") || first_check.description.contains("null") { + explanation.push_str(" 1. Add null pointer checks:\n"); + explanation.push_str(" • Check `if ptr.is_null()` before dereferencing\n"); + explanation.push_str(" 2. Use safe Rust alternatives:\n"); + explanation.push_str(" • Consider using `Option<&T>` instead of raw pointers\n"); + } else if first_check.description.contains("index") || first_check.description.contains("bounds") { + explanation.push_str(" 1. Add bounds checking:\n"); + explanation.push_str(" • Use `.get()` instead of direct indexing\n"); + explanation.push_str(" • Check `index < array.len()` before access\n"); + explanation.push_str(" 2. Use iterators:\n"); + explanation.push_str(" • Consider using `.iter()` instead of manual indexing\n"); + } else { + explanation.push_str(" 1. Review the assertion condition:\n"); + explanation.push_str(" • Ensure it correctly captures the intended property\n"); + explanation.push_str(" 2. Add input constraints:\n"); + explanation.push_str(" • Use `kani::assume()` to limit the input space\n"); + explanation.push_str(" 3. Fix the underlying logic:\n"); + explanation.push_str(" • Adjust the code to handle all cases correctly\n"); + } + explanation.push_str("\n"); + } + + // Next steps + explanation.push_str("NEXT STEPS:\n\n"); + explanation.push_str(" 1. Examine the code at the failure location\n"); + explanation.push_str(" 2. Understand what inputs trigger the failure\n"); + explanation.push_str(" 3. Apply the suggested fixes\n"); + explanation.push_str(" 4. Re-run Kani verification to confirm the fix\n"); + explanation.push_str(" 5. Consider adding more proof harnesses for edge cases\n"); + + explanation + } } \ No newline at end of file From f7f25751c78908c9c1568bfde6c245f31bdf45bc Mon Sep 17 00:00:00 2001 From: jingfei-xu Date: Thu, 30 Oct 2025 09:56:24 -0700 Subject: [PATCH 03/11] Amazon Q CLI Integration --- Cargo.lock | 171 ++++++++++++++++-- Cargo.toml | 3 +- .../dep-lib-first_steps_v1 | Bin 0 -> 30 bytes .../invoked.timestamp | 1 + .../lib-first_steps_v1 | 1 + .../lib-first_steps_v1.json | 1 + .../deps/first_steps_v1-ecd3bc8b423b2e0e.d | 7 + ...eps_v1-ecd3bc8b423b2e0e.kani-metadata.json | 1 + ..._14first_steps_v119check_estimate_size.out | Bin 0 -> 30807 bytes ...19check_estimate_size.pretty_name_map.json | 1 + ...t_steps_v119check_estimate_size.symtab.out | Bin 0 -> 15385 bytes ...teps_v119check_estimate_size.type_map.json | 1 + .../dep-graph.bin | Bin 0 -> 152690 bytes .../query-cache.bin | Bin 0 -> 15889 bytes .../work-products.bin | Bin 0 -> 108 bytes .../s-hcaa312xrg-0tsz4l7.lock | 0 kani-mcp-server/src/main.rs | 28 +-- kani-mcp-server/src/mcp_server.rs | 56 ++---- kani-mcp-server/src/tools.rs | 2 +- 19 files changed, 204 insertions(+), 69 deletions(-) create mode 100644 docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-ecd3bc8b423b2e0e/dep-lib-first_steps_v1 create mode 100644 docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-ecd3bc8b423b2e0e/invoked.timestamp create mode 100644 docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-ecd3bc8b423b2e0e/lib-first_steps_v1 create mode 100644 docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-ecd3bc8b423b2e0e/lib-first_steps_v1.json create mode 100644 docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-ecd3bc8b423b2e0e.d create mode 100644 docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-ecd3bc8b423b2e0e.kani-metadata.json create mode 100644 docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-ecd3bc8b423b2e0e__RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size.out create mode 100644 docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-ecd3bc8b423b2e0e__RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size.pretty_name_map.json create mode 100644 docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-ecd3bc8b423b2e0e__RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size.symtab.out create mode 100644 docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-ecd3bc8b423b2e0e__RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size.type_map.json create mode 100644 docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/incremental/first_steps_v1-0vt6guzbgblsh/s-hcaa312xrg-0tsz4l7-0tbp8brnzyhlg3dpmdfvt6kuf/dep-graph.bin create mode 100644 docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/incremental/first_steps_v1-0vt6guzbgblsh/s-hcaa312xrg-0tsz4l7-0tbp8brnzyhlg3dpmdfvt6kuf/query-cache.bin create mode 100644 docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/incremental/first_steps_v1-0vt6guzbgblsh/s-hcaa312xrg-0tsz4l7-0tbp8brnzyhlg3dpmdfvt6kuf/work-products.bin create mode 100755 docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/incremental/first_steps_v1-0vt6guzbgblsh/s-hcaa312xrg-0tsz4l7.lock diff --git a/Cargo.lock b/Cargo.lock index d0a5d939a02..5fcffa47c55 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -491,7 +491,7 @@ dependencies = [ "crossterm_winapi", "document-features", "parking_lot", - "rustix", + "rustix 1.1.2", "winapi", ] @@ -1021,6 +1021,20 @@ dependencies = [ "which 8.0.0", ] +[[package]] +name = "kani-mcp-server" +version = "0.1.0" +dependencies = [ + "anyhow", + "serde", + "serde_json", + "thiserror 1.0.69", + "tokio", + "tracing", + "tracing-subscriber", + "which 6.0.3", +] + [[package]] name = "kani-verifier" version = "0.66.0" @@ -1083,6 +1097,12 @@ dependencies = [ "serde_test", ] +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + [[package]] name = "linux-raw-sys" version = "0.11.0" @@ -1724,6 +1744,19 @@ dependencies = [ "semver", ] +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", +] + [[package]] name = "rustix" version = "1.1.2" @@ -1733,7 +1766,7 @@ dependencies = [ "bitflags", "errno", "libc", - "linux-raw-sys", + "linux-raw-sys 0.11.0", "windows-sys 0.61.2", ] @@ -1941,6 +1974,16 @@ version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +[[package]] +name = "socket2" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" +dependencies = [ + "libc", + "windows-sys 0.60.2", +] + [[package]] name = "stacker" version = "0.1.22" @@ -2027,7 +2070,7 @@ dependencies = [ "fastrand", "getrandom", "once_cell", - "rustix", + "rustix 1.1.2", "windows-sys 0.61.2", ] @@ -2137,11 +2180,25 @@ dependencies = [ "bytes", "libc", "mio", + "parking_lot", "pin-project-lite", "signal-hook-registry", + "socket2", + "tokio-macros", "windows-sys 0.61.2", ] +[[package]] +name = "tokio-macros" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "toml" version = "0.8.23" @@ -2478,6 +2535,18 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "which" +version = "6.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ee928febd44d98f2f459a4a79bd4d928591333a494a10a868418ac1b39cf1f" +dependencies = [ + "either", + "home", + "rustix 0.38.44", + "winsafe", +] + [[package]] name = "which" version = "7.0.3" @@ -2486,7 +2555,7 @@ checksum = "24d643ce3fd3e5b54854602a080f34fb10ab75e0b813ee32d00ca2b44fa74762" dependencies = [ "either", "env_home", - "rustix", + "rustix 1.1.2", "winsafe", ] @@ -2497,7 +2566,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3fabb953106c3c8eea8306e4393700d7657561cb43122571b172bbfb7c7ba1d" dependencies = [ "env_home", - "rustix", + "rustix 1.1.2", "winsafe", ] @@ -2597,7 +2666,16 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.5", ] [[package]] @@ -2615,14 +2693,31 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", ] [[package]] @@ -2631,48 +2726,96 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + [[package]] name = "winnow" version = "0.7.13" diff --git a/Cargo.toml b/Cargo.toml index 2d82261b3ec..b2dd3fb82b4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,7 +52,7 @@ members = [ "kani-driver", "kani-compiler", "kani_metadata", - "library/kani_core", + "library/kani_core", "kani-mcp-server", ] # This indicates what package to e.g. build with 'cargo build' without --workspace @@ -60,6 +60,7 @@ default-members = [ ".", "kani-driver", "kani-compiler", + "kani-mcp-server", ] exclude = [ diff --git a/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-ecd3bc8b423b2e0e/dep-lib-first_steps_v1 b/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-ecd3bc8b423b2e0e/dep-lib-first_steps_v1 new file mode 100644 index 0000000000000000000000000000000000000000..024be4904569dbe2c19582a923171096f5c21ee4 GIT binary patch literal 30 gcmZQ%U|{&q$Ot4ExPZ90C|N%zGfA(g7$m{~07A6{&Hw-a literal 0 HcmV?d00001 diff --git a/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-ecd3bc8b423b2e0e/invoked.timestamp b/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-ecd3bc8b423b2e0e/invoked.timestamp new file mode 100644 index 00000000000..e00328da5aa --- /dev/null +++ b/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-ecd3bc8b423b2e0e/invoked.timestamp @@ -0,0 +1 @@ +This file has an mtime of when this was started. \ No newline at end of file diff --git a/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-ecd3bc8b423b2e0e/lib-first_steps_v1 b/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-ecd3bc8b423b2e0e/lib-first_steps_v1 new file mode 100644 index 00000000000..136a5444b10 --- /dev/null +++ b/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-ecd3bc8b423b2e0e/lib-first_steps_v1 @@ -0,0 +1 @@ +13c836b8b850d3fb \ No newline at end of file diff --git a/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-ecd3bc8b423b2e0e/lib-first_steps_v1.json b/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-ecd3bc8b423b2e0e/lib-first_steps_v1.json new file mode 100644 index 00000000000..cb929f0e813 --- /dev/null +++ b/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-ecd3bc8b423b2e0e/lib-first_steps_v1.json @@ -0,0 +1 @@ +{"rustc":14672501838171729802,"features":"[]","declared_features":"[]","target":5150295270818399684,"profile":5594203621556287378,"path":10763286916239946207,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-ecd3bc8b423b2e0e/dep-lib-first_steps_v1","checksum":false}}],"rustflags":["-C","overflow-checks=on","-Z","unstable-options","-Z","trim-diagnostic-paths=no","-Z","human_readable_cgu_names","-Z","always-encode-mir","--cfg=kani","-Z","crate-attr=feature(register_tool)","-Z","crate-attr=register_tool(kanitool)","--sysroot","/Users/jingfeixu/kani/target/kani","-L","/Users/jingfeixu/kani/target/kani/lib","--extern","kani","--extern","noprelude:std=/Users/jingfeixu/kani/target/kani/lib/libstd.rlib","-C","panic=abort","-C","symbol-mangling-version=v0","-Z","panic_abort_tests=yes","-Z","mir-enable-passes=-RemoveStorageMarkers","--check-cfg=cfg(kani)","-Clinker=echo","--kani-compiler","-Cllvm-args=--check-version=0.65.0"],"config":2069994364910194474,"compile_kind":551198452465029181} \ No newline at end of file diff --git a/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-ecd3bc8b423b2e0e.d b/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-ecd3bc8b423b2e0e.d new file mode 100644 index 00000000000..64b5a8e97bf --- /dev/null +++ b/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-ecd3bc8b423b2e0e.d @@ -0,0 +1,7 @@ +/Users/jingfeixu/kani-output/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-ecd3bc8b423b2e0e.d: src/lib.rs + +/Users/jingfeixu/kani-output/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/libfirst_steps_v1-ecd3bc8b423b2e0e.rlib: src/lib.rs + +/Users/jingfeixu/kani-output/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/libfirst_steps_v1-ecd3bc8b423b2e0e.rmeta: src/lib.rs + +src/lib.rs: diff --git a/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-ecd3bc8b423b2e0e.kani-metadata.json b/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-ecd3bc8b423b2e0e.kani-metadata.json new file mode 100644 index 00000000000..fcf4042f025 --- /dev/null +++ b/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-ecd3bc8b423b2e0e.kani-metadata.json @@ -0,0 +1 @@ +{"crate_name":"first_steps_v1","proof_harnesses":[{"pretty_name":"check_estimate_size","mangled_name":"_RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size","crate_name":"first_steps_v1","original_file":"src/lib.rs","original_start_line":52,"original_end_line":55,"goto_file":"/Users/jingfeixu/kani-output/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-ecd3bc8b423b2e0e__RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size.symtab.out","attributes":{"kind":"Proof","should_panic":false,"solver":null,"unwind_value":null,"stubs":[],"verified_stubs":[]},"contract":null,"has_loop_contracts":false,"is_automatically_generated":false}],"unsupported_features":[],"test_harnesses":[],"contracted_functions":[],"autoharness_md":null} \ No newline at end of file diff --git a/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-ecd3bc8b423b2e0e__RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size.out b/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-ecd3bc8b423b2e0e__RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size.out new file mode 100644 index 0000000000000000000000000000000000000000..8bcb941e52f2c03dbba68cd6d7b6b06d4609f9a3 GIT binary patch literal 30807 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 oH!iTmNN0Pb8>4(-jb`WH","tag-refstr":"&str","_ZN4kani5panic17h039ec056df9649c9E::1::var_1::message":null,"tag-Never":"!","_ZN4kani5panic17h039ec056df9649c9E":"kani::panic","_ZN4kani16rustc_intrinsics10panic_stub17h7798f34a644f74adE::1::var_1::t":null,"_ZN4kani16rustc_intrinsics10panic_stub17h7798f34a644f74adE":"kani::rustc_intrinsics::panic_stub","_RNvCs4ZijrwXvPyf_14first_steps_v113estimate_size::1::var_1::x":null,"_RNvCs4ZijrwXvPyf_14first_steps_v113estimate_size":"estimate_size","tag-Unit":"()","_RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size":"check_estimate_size","_ZN4kani14kani_intrinsic17hf2340b114c62bceeE":"kani::kani_intrinsic::","_ZN4kani7any_raw17h1bd6bd359a6961f9E":"kani::any_raw::","_RINvCsc8NbQx0kdtQ_4kani3anymECs4ZijrwXvPyf_14first_steps_v1":"kani::any::","_ZN39_$LT$u32$u20$as$u20$kani..Arbitrary$GT$3any17h9d58c5c4eb479917E":"::any","_ZN4kani16any_raw_internal17h8bfeb1a460f3b3fdE::1::var_0":null,"_ZN4kani5panic17h039ec056df9649c9E::1::var_0":null,"_ZN4kani5panic17h039ec056df9649c9E::1::var_2":null,"_ZN4kani5panic17h039ec056df9649c9E::1::var_3":null,"_ZN4kani16rustc_intrinsics10panic_stub17h7798f34a644f74adE::1::var_0":null,"_RNvCs4ZijrwXvPyf_14first_steps_v113estimate_size::1::var_0":null,"_RNvCs4ZijrwXvPyf_14first_steps_v113estimate_size::1::var_2":null,"_RNvCs4ZijrwXvPyf_14first_steps_v113estimate_size::1::var_3":null,"_RNvCs4ZijrwXvPyf_14first_steps_v113estimate_size::1::var_4":null,"_RNvCs4ZijrwXvPyf_14first_steps_v113estimate_size::1::var_5":null,"_RNvCs4ZijrwXvPyf_14first_steps_v113estimate_size::1::var_6":null,"_RNvCs4ZijrwXvPyf_14first_steps_v113estimate_size::1::var_7":null,"tag-first_steps_v1.3a1b106d0fea0f11::first_steps_v1::global::0::::struct":"first_steps_v1.3a1b106d0fea0f11::first_steps_v1::global::0::::struct","first_steps_v1.3a1b106d0fea0f11::first_steps_v1::global::0::":null,"_RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size::1::var_0":null,"_RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size::1::var_1::x":null,"_RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size::1::var_2":null,"VoidUnit":null,"_ZN4kani14kani_intrinsic17hf2340b114c62bceeE::1::var_0":null,"_ZN4kani7any_raw17h1bd6bd359a6961f9E::1::var_0":null,"_RINvCsc8NbQx0kdtQ_4kani3anymECs4ZijrwXvPyf_14first_steps_v1::1::var_0":null,"_ZN39_$LT$u32$u20$as$u20$kani..Arbitrary$GT$3any17h9d58c5c4eb479917E::1::var_0":null} \ No newline at end of file diff --git a/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-ecd3bc8b423b2e0e__RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size.symtab.out b/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-ecd3bc8b423b2e0e__RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size.symtab.out new file mode 100644 index 0000000000000000000000000000000000000000..52dc78cf1271c1b8c5d807b968ad78a40503cf39 GIT binary patch literal 15385 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

e$i-6 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 literal 0 HcmV?d00001 diff --git a/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/incremental/first_steps_v1-0vt6guzbgblsh/s-hcaa312xrg-0tsz4l7-0tbp8brnzyhlg3dpmdfvt6kuf/query-cache.bin b/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/incremental/first_steps_v1-0vt6guzbgblsh/s-hcaa312xrg-0tsz4l7-0tbp8brnzyhlg3dpmdfvt6kuf/query-cache.bin new file mode 100644 index 0000000000000000000000000000000000000000..d9eef1221caf659925f42811d48b1078af00971d GIT binary patch literal 15889 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 r0-yC>GlLZP Result<()> { - // Initialize logging - tracing_subscriber::fmt() - .with_env_filter( - EnvFilter::from_default_env() - .add_directive("kani_mcp_server=info".parse()?) - ) - .init(); + // Only initialize logging if explicitly requested via environment variable + // This prevents "Broken pipe" errors when stderr is closed by the MCP client + if std::env::var("KANI_MCP_LOG").is_ok() { + tracing_subscriber::fmt() + .with_env_filter( + EnvFilter::from_default_env() + .add_directive("kani_mcp_server=info".parse()?) + ) + .init(); + } - println!("Kani MCP Server - Model Context Protocol for Kani Rust Verifier"); - println!("Purpose: Enable AI assistants like Amazon Q to run Kani verification"); - println!(); + // Banner - only show if logging is enabled + if std::env::var("KANI_MCP_LOG").is_ok() { + eprintln!("Kani MCP Server - Model Context Protocol for Kani Rust Verifier"); + eprintln!("Purpose: Enable AI assistants like Amazon Q to run Kani verification"); + eprintln!(); + } // Create and run server let server = mcp_server::KaniMcpServer::new()?; server.run().await?; Ok(()) -} \ No newline at end of file +} diff --git a/kani-mcp-server/src/mcp_server.rs b/kani-mcp-server/src/mcp_server.rs index e9a35a1b2d0..f7f0c0c656b 100644 --- a/kani-mcp-server/src/mcp_server.rs +++ b/kani-mcp-server/src/mcp_server.rs @@ -4,7 +4,6 @@ use anyhow::Result; use std::path::PathBuf; use std::sync::Arc; use tokio::sync::Mutex; -use tracing::{error, info}; /// Main MCP server for Kani integration pub struct KaniMcpServer { @@ -24,23 +23,6 @@ impl KaniMcpServer { /// Run the MCP server pub async fn run(self) -> Result<()> { - info!("═══════════════════════════════════════════════════════════"); - info!(" Kani MCP Server - Ready for Amazon Q Integration"); - info!("═══════════════════════════════════════════════════════════"); - info!(""); - info!("Available Tools:"); - - for tool in get_kani_tools() { - info!(" • {} - {}", tool.name, tool.description); - } - - info!(""); - info!("Connection: stdio (Standard Input/Output)"); - info!("Compatible with: Amazon Q, Claude Desktop, Cursor, etc."); - info!(""); - info!("Server is ready and waiting for requests..."); - info!(""); - // Read from stdin and respond via stdout (MCP protocol) use tokio::io::{AsyncBufReadExt, BufReader, stdin}; @@ -58,20 +40,20 @@ impl KaniMcpServer { Ok(request) => { let response = self.handle_mcp_request(request).await; - // Send response to stdout - if let Ok(response_str) = serde_json::to_string(&response) { - println!("{}", response_str); + // Send response to stdout (skip null responses for notifications) + if !response.is_null() { + if let Ok(response_str) = serde_json::to_string(&response) { + println!("{}", response_str); + } } } - Err(e) => { - error!("Failed to parse request: {}", e); + Err(_e) => { + // Silently ignore parse errors to avoid broken pipe + continue; } } } - info!(""); - info!("Shutting down Kani MCP Server..."); - Ok(()) } @@ -84,7 +66,6 @@ impl KaniMcpServer { match method { "initialize" => { - info!("📥 Received: initialize"); json!({ "jsonrpc": "2.0", "id": id, @@ -100,8 +81,12 @@ impl KaniMcpServer { } }) } + "notifications/initialized" => { + // Client confirms initialization is complete + // Notifications don't get responses - return null + json!(null) + } "tools/list" => { - info!("Received: tools/list"); let tools: Vec<_> = get_kani_tools() .iter() .map(|tool| { @@ -125,8 +110,6 @@ impl KaniMcpServer { let tool_name = request["params"]["name"].as_str().unwrap_or(""); let arguments = &request["params"]["arguments"]; - info!("Received: tools/call - {}", tool_name); - let result = self.execute_tool(tool_name, arguments).await; json!({ @@ -136,7 +119,6 @@ impl KaniMcpServer { }) } _ => { - error!("Unknown method: {}", method); json!({ "jsonrpc": "2.0", "id": id, @@ -214,7 +196,7 @@ impl KaniMcpServer { } } } - "explain_kani_failure" => { + "explain_failure" => { // Try to get raw output from arguments or from last result let raw_output = if let Some(output_str) = arguments["raw_output"].as_str() { output_str.to_string() @@ -303,9 +285,6 @@ impl KaniMcpServer { tests: bool, output_format: Option, ) -> Result { - info!("🔍 Tool called: verify_rust_project"); - info!(" Path: {}", path); - let options = KaniOptions { path: PathBuf::from(path), harness: harness.clone(), @@ -326,7 +305,6 @@ impl KaniMcpServer { }) } Err(e) => { - error!("Verification error: {}", e); Ok(ToolResult { success: false, data: serde_json::json!({}), @@ -342,16 +320,12 @@ impl KaniMcpServer { path: String, harness: String, ) -> Result { - info!("Tool called: verify_unsafe_code"); - // This is essentially the same as verify_project but focused on unsafe code self.handle_verify_project(path, Some(harness), false, Some("terse".to_string())).await } /// Handle explain_kani_failure tool call with enhanced analysis pub async fn handle_explain_failure(&self, raw_output: String) -> Result { - info!("Tool called: explain_kani_failure"); - use crate::parser::KaniOutputParser; let parser = KaniOutputParser::new(&raw_output); @@ -387,8 +361,6 @@ impl KaniMcpServer { function_name: String, properties: Vec, ) -> Result { - info!("🔍 Tool called: generate_kani_harness"); - let harness_code = format!( r#"#[cfg(kani)] mod verification {{ diff --git a/kani-mcp-server/src/tools.rs b/kani-mcp-server/src/tools.rs index b7f685448ff..aeb2ad9425d 100644 --- a/kani-mcp-server/src/tools.rs +++ b/kani-mcp-server/src/tools.rs @@ -60,7 +60,7 @@ pub fn get_kani_tools() -> Vec { }), }, ToolDefinition { - name: "explain_kani_failure".to_string(), + name: "explain_failure".to_string(), description: "Analyze and explain why a Kani verification failed, providing details about counterexamples and suggested fixes.".to_string(), input_schema: json!({ "type": "object", From d00d94e310cc7150e476d85948324d080d762144 Mon Sep 17 00:00:00 2001 From: jingfei-xu Date: Thu, 6 Nov 2025 00:20:56 -0800 Subject: [PATCH 04/11] Amazon Q latest integration (Amazon Q CLI) --- .../dep-lib-first_steps_v1 | Bin 0 -> 30 bytes .../invoked.timestamp | 1 + .../lib-first_steps_v1 | 1 + .../lib-first_steps_v1.json | 1 + .../deps/first_steps_v1-83910d6b167b89c9.d | 7 +++++++ ...eps_v1-83910d6b167b89c9.kani-metadata.json | 1 + ..._14first_steps_v119check_estimate_size.out | Bin 0 -> 30807 bytes ...19check_estimate_size.pretty_name_map.json | 1 + ...t_steps_v119check_estimate_size.symtab.out | Bin 0 -> 15385 bytes ...teps_v119check_estimate_size.type_map.json | 1 + .../dep-graph.bin | Bin 152690 -> 152690 bytes .../query-cache.bin | Bin 15889 -> 15889 bytes .../work-products.bin | Bin ...0tsz4l7.lock => s-hciu6tb5rp-03gygye.lock} | 0 14 files changed, 13 insertions(+) create mode 100644 docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-83910d6b167b89c9/dep-lib-first_steps_v1 create mode 100644 docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-83910d6b167b89c9/invoked.timestamp create mode 100644 docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-83910d6b167b89c9/lib-first_steps_v1 create mode 100644 docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-83910d6b167b89c9/lib-first_steps_v1.json create mode 100644 docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-83910d6b167b89c9.d create mode 100644 docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-83910d6b167b89c9.kani-metadata.json create mode 100644 docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-83910d6b167b89c9__RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size.out create mode 100644 docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-83910d6b167b89c9__RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size.pretty_name_map.json create mode 100644 docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-83910d6b167b89c9__RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size.symtab.out create mode 100644 docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-83910d6b167b89c9__RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size.type_map.json rename docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/incremental/first_steps_v1-0vt6guzbgblsh/{s-hcaa312xrg-0tsz4l7-0tbp8brnzyhlg3dpmdfvt6kuf => s-hciu6tb5rp-03gygye-7jb1sxgfjbsla5m9hfducyrfi}/dep-graph.bin (99%) rename docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/incremental/first_steps_v1-0vt6guzbgblsh/{s-hcaa312xrg-0tsz4l7-0tbp8brnzyhlg3dpmdfvt6kuf => s-hciu6tb5rp-03gygye-7jb1sxgfjbsla5m9hfducyrfi}/query-cache.bin (95%) rename docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/incremental/first_steps_v1-0vt6guzbgblsh/{s-hcaa312xrg-0tsz4l7-0tbp8brnzyhlg3dpmdfvt6kuf => s-hciu6tb5rp-03gygye-7jb1sxgfjbsla5m9hfducyrfi}/work-products.bin (100%) rename docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/incremental/first_steps_v1-0vt6guzbgblsh/{s-hcaa312xrg-0tsz4l7.lock => s-hciu6tb5rp-03gygye.lock} (100%) diff --git a/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-83910d6b167b89c9/dep-lib-first_steps_v1 b/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-83910d6b167b89c9/dep-lib-first_steps_v1 new file mode 100644 index 0000000000000000000000000000000000000000..024be4904569dbe2c19582a923171096f5c21ee4 GIT binary patch literal 30 gcmZQ%U|{&q$Ot4ExPZ90C|N%zGfA(g7$m{~07A6{&Hw-a literal 0 HcmV?d00001 diff --git a/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-83910d6b167b89c9/invoked.timestamp b/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-83910d6b167b89c9/invoked.timestamp new file mode 100644 index 00000000000..e00328da5aa --- /dev/null +++ b/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-83910d6b167b89c9/invoked.timestamp @@ -0,0 +1 @@ +This file has an mtime of when this was started. \ No newline at end of file diff --git a/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-83910d6b167b89c9/lib-first_steps_v1 b/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-83910d6b167b89c9/lib-first_steps_v1 new file mode 100644 index 00000000000..c6185f7ae33 --- /dev/null +++ b/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-83910d6b167b89c9/lib-first_steps_v1 @@ -0,0 +1 @@ +aa4334fdd37a1140 \ No newline at end of file diff --git a/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-83910d6b167b89c9/lib-first_steps_v1.json b/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-83910d6b167b89c9/lib-first_steps_v1.json new file mode 100644 index 00000000000..5b3cf8a3f54 --- /dev/null +++ b/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-83910d6b167b89c9/lib-first_steps_v1.json @@ -0,0 +1 @@ +{"rustc":14672501838171729802,"features":"[]","declared_features":"[]","target":5150295270818399684,"profile":2308729259012748722,"path":10763286916239946207,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-83910d6b167b89c9/dep-lib-first_steps_v1","checksum":false}}],"rustflags":["-C","overflow-checks=on","-Z","unstable-options","-Z","trim-diagnostic-paths=no","-Z","human_readable_cgu_names","-Z","always-encode-mir","--cfg=kani","-Z","crate-attr=feature(register_tool)","-Z","crate-attr=register_tool(kanitool)","--sysroot","/Users/jingfeixu/kani/target/kani","-L","/Users/jingfeixu/kani/target/kani/lib","--extern","kani","--extern","noprelude:std=/Users/jingfeixu/kani/target/kani/lib/libstd.rlib","-C","panic=abort","-C","symbol-mangling-version=v0","-Z","panic_abort_tests=yes","-Z","mir-enable-passes=-RemoveStorageMarkers","--check-cfg=cfg(kani)","-Clinker=echo","--kani-compiler","-Cllvm-args=--check-version=0.65.0"],"config":2069994364910194474,"compile_kind":551198452465029181} \ No newline at end of file diff --git a/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-83910d6b167b89c9.d b/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-83910d6b167b89c9.d new file mode 100644 index 00000000000..3d3cc416a35 --- /dev/null +++ b/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-83910d6b167b89c9.d @@ -0,0 +1,7 @@ +/Users/jingfeixu/kani-output/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-83910d6b167b89c9.d: src/lib.rs + +/Users/jingfeixu/kani-output/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/libfirst_steps_v1-83910d6b167b89c9.rlib: src/lib.rs + +/Users/jingfeixu/kani-output/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/libfirst_steps_v1-83910d6b167b89c9.rmeta: src/lib.rs + +src/lib.rs: diff --git a/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-83910d6b167b89c9.kani-metadata.json b/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-83910d6b167b89c9.kani-metadata.json new file mode 100644 index 00000000000..de73af3a03d --- /dev/null +++ b/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-83910d6b167b89c9.kani-metadata.json @@ -0,0 +1 @@ +{"crate_name":"first_steps_v1","proof_harnesses":[{"pretty_name":"check_estimate_size","mangled_name":"_RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size","crate_name":"first_steps_v1","original_file":"src/lib.rs","original_start_line":52,"original_end_line":55,"goto_file":"/Users/jingfeixu/kani-output/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-83910d6b167b89c9__RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size.symtab.out","attributes":{"kind":"Proof","should_panic":false,"solver":null,"unwind_value":null,"stubs":[],"verified_stubs":[]},"contract":null,"has_loop_contracts":false,"is_automatically_generated":false}],"unsupported_features":[],"test_harnesses":[],"contracted_functions":[],"autoharness_md":null} \ No newline at end of file diff --git a/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-83910d6b167b89c9__RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size.out b/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-83910d6b167b89c9__RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size.out new file mode 100644 index 0000000000000000000000000000000000000000..8bcb941e52f2c03dbba68cd6d7b6b06d4609f9a3 GIT binary patch literal 30807 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 oH!iTmNN0Pb8>4(-jb`WH","tag-refstr":"&str","_ZN4kani5panic17h039ec056df9649c9E::1::var_1::message":null,"tag-Never":"!","_ZN4kani5panic17h039ec056df9649c9E":"kani::panic","_ZN4kani16rustc_intrinsics10panic_stub17h7798f34a644f74adE::1::var_1::t":null,"_ZN4kani16rustc_intrinsics10panic_stub17h7798f34a644f74adE":"kani::rustc_intrinsics::panic_stub","_RNvCs4ZijrwXvPyf_14first_steps_v113estimate_size::1::var_1::x":null,"_RNvCs4ZijrwXvPyf_14first_steps_v113estimate_size":"estimate_size","tag-Unit":"()","_RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size":"check_estimate_size","_ZN4kani14kani_intrinsic17hf2340b114c62bceeE":"kani::kani_intrinsic::","_ZN4kani7any_raw17h1bd6bd359a6961f9E":"kani::any_raw::","_RINvCsc8NbQx0kdtQ_4kani3anymECs4ZijrwXvPyf_14first_steps_v1":"kani::any::","_ZN39_$LT$u32$u20$as$u20$kani..Arbitrary$GT$3any17h9d58c5c4eb479917E":"::any","_ZN4kani16any_raw_internal17h8bfeb1a460f3b3fdE::1::var_0":null,"_ZN4kani5panic17h039ec056df9649c9E::1::var_0":null,"_ZN4kani5panic17h039ec056df9649c9E::1::var_2":null,"_ZN4kani5panic17h039ec056df9649c9E::1::var_3":null,"_ZN4kani16rustc_intrinsics10panic_stub17h7798f34a644f74adE::1::var_0":null,"_RNvCs4ZijrwXvPyf_14first_steps_v113estimate_size::1::var_0":null,"_RNvCs4ZijrwXvPyf_14first_steps_v113estimate_size::1::var_2":null,"_RNvCs4ZijrwXvPyf_14first_steps_v113estimate_size::1::var_3":null,"_RNvCs4ZijrwXvPyf_14first_steps_v113estimate_size::1::var_4":null,"_RNvCs4ZijrwXvPyf_14first_steps_v113estimate_size::1::var_5":null,"_RNvCs4ZijrwXvPyf_14first_steps_v113estimate_size::1::var_6":null,"_RNvCs4ZijrwXvPyf_14first_steps_v113estimate_size::1::var_7":null,"tag-first_steps_v1.3a1b106d0fea0f11::first_steps_v1::global::0::::struct":"first_steps_v1.3a1b106d0fea0f11::first_steps_v1::global::0::::struct","first_steps_v1.3a1b106d0fea0f11::first_steps_v1::global::0::":null,"_RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size::1::var_0":null,"_RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size::1::var_1::x":null,"_RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size::1::var_2":null,"VoidUnit":null,"_ZN4kani14kani_intrinsic17hf2340b114c62bceeE::1::var_0":null,"_ZN4kani7any_raw17h1bd6bd359a6961f9E::1::var_0":null,"_RINvCsc8NbQx0kdtQ_4kani3anymECs4ZijrwXvPyf_14first_steps_v1::1::var_0":null,"_ZN39_$LT$u32$u20$as$u20$kani..Arbitrary$GT$3any17h9d58c5c4eb479917E::1::var_0":null} \ No newline at end of file diff --git a/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-83910d6b167b89c9__RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size.symtab.out b/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-83910d6b167b89c9__RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size.symtab.out new file mode 100644 index 0000000000000000000000000000000000000000..52dc78cf1271c1b8c5d807b968ad78a40503cf39 GIT binary patch literal 15385 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 D1C=EA delta 97 zcmV-n0G|Jme35*xx(}0-5ImE35itXp95IuZ5F?Xl5fGE%4>OZf5J8i=4=0lu5h;@t z5I>X95J|JC5gaQc#uU0Apd9uem>j1dj2zt{tQ?Rbj~vkoXwH)BH=sYO_ D%^W0B diff --git a/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/incremental/first_steps_v1-0vt6guzbgblsh/s-hcaa312xrg-0tsz4l7-0tbp8brnzyhlg3dpmdfvt6kuf/work-products.bin b/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/incremental/first_steps_v1-0vt6guzbgblsh/s-hciu6tb5rp-03gygye-7jb1sxgfjbsla5m9hfducyrfi/work-products.bin similarity index 100% rename from docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/incremental/first_steps_v1-0vt6guzbgblsh/s-hcaa312xrg-0tsz4l7-0tbp8brnzyhlg3dpmdfvt6kuf/work-products.bin rename to docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/incremental/first_steps_v1-0vt6guzbgblsh/s-hciu6tb5rp-03gygye-7jb1sxgfjbsla5m9hfducyrfi/work-products.bin diff --git a/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/incremental/first_steps_v1-0vt6guzbgblsh/s-hcaa312xrg-0tsz4l7.lock b/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/incremental/first_steps_v1-0vt6guzbgblsh/s-hciu6tb5rp-03gygye.lock similarity index 100% rename from docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/incremental/first_steps_v1-0vt6guzbgblsh/s-hcaa312xrg-0tsz4l7.lock rename to docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/incremental/first_steps_v1-0vt6guzbgblsh/s-hciu6tb5rp-03gygye.lock From fe395410c97f471b90bded042aed501e89adea20 Mon Sep 17 00:00:00 2001 From: jingfei-xu Date: Thu, 6 Nov 2025 12:03:05 -0800 Subject: [PATCH 05/11] Code Format Cleanup --- kani-mcp-server/src/kani_wrapper.rs | 34 ----------------------------- kani-mcp-server/src/main.rs | 1 - kani-mcp-server/src/mcp_server.rs | 9 -------- kani-mcp-server/src/parser.rs | 13 ----------- 4 files changed, 57 deletions(-) diff --git a/kani-mcp-server/src/kani_wrapper.rs b/kani-mcp-server/src/kani_wrapper.rs index 629d4d1a90a..6cd277ea8ef 100644 --- a/kani-mcp-server/src/kani_wrapper.rs +++ b/kani-mcp-server/src/kani_wrapper.rs @@ -7,28 +7,13 @@ use tracing::{debug, info, warn}; /// Configuration options for running Kani verification #[derive(Debug, Clone, Serialize, Deserialize)] pub struct KaniOptions { - /// Path to the Rust project to verify pub path: PathBuf, - - /// Specific harness to run (e.g., "module::function") pub harness: Option, - - /// Run all tests as verification harnesses pub tests: bool, - - /// Output format: regular, terse, old, json pub output_format: String, - - /// Enable unstable Kani features pub enable_unstable: Vec, - - /// Additional arguments to pass to Kani pub extra_args: Vec, - - /// Enable concrete playback for counterexamples pub concrete_playback: bool, - - /// Enable coverage information pub coverage: bool, } @@ -50,22 +35,11 @@ impl Default for KaniOptions { /// Result of a Kani verification run #[derive(Debug, Clone, Serialize, Deserialize)] pub struct VerificationResult { - /// Whether verification succeeded pub success: bool, - - /// Human-readable summary pub summary: String, - - /// List of harness results pub harnesses: Vec, - - /// Failed checks with details pub failed_checks: Vec, - - /// Verification time in seconds pub verification_time: Option, - - /// Raw output from Kani pub raw_output: String, } @@ -110,45 +84,37 @@ impl KaniWrapper { anyhow::bail!("Path does not exist: {:?}", options.path); } - // Build the command let mut cmd = Command::new(&self.cargo_kani_path); cmd.arg("kani"); cmd.current_dir(&options.path); - // Add harness filter if let Some(harness) = &options.harness { cmd.arg("--harness").arg(harness); info!(" Filtering to harness: {}", harness); } - // Run tests as harnesses if options.tests { cmd.arg("--tests"); info!(" Running all tests as harnesses"); } - // Set output format if !options.output_format.is_empty() { cmd.arg(format!("--output-format={}", options.output_format)); } - // Enable unstable features for feature in &options.enable_unstable { cmd.arg("--enable-unstable").arg(feature); } - // Concrete playback if options.concrete_playback { cmd.arg("-Z").arg("concrete-playback"); cmd.arg("--concrete-playback=print"); } - // Coverage if options.coverage { cmd.arg("--coverage"); } - // Extra arguments for arg in &options.extra_args { cmd.arg(arg); } diff --git a/kani-mcp-server/src/main.rs b/kani-mcp-server/src/main.rs index aadc0520ae0..b559371040a 100644 --- a/kani-mcp-server/src/main.rs +++ b/kani-mcp-server/src/main.rs @@ -9,7 +9,6 @@ use tracing_subscriber::EnvFilter; #[tokio::main] async fn main() -> Result<()> { // Only initialize logging if explicitly requested via environment variable - // This prevents "Broken pipe" errors when stderr is closed by the MCP client if std::env::var("KANI_MCP_LOG").is_ok() { tracing_subscriber::fmt() .with_env_filter( diff --git a/kani-mcp-server/src/mcp_server.rs b/kani-mcp-server/src/mcp_server.rs index f7f0c0c656b..4ee4d912a63 100644 --- a/kani-mcp-server/src/mcp_server.rs +++ b/kani-mcp-server/src/mcp_server.rs @@ -12,7 +12,6 @@ pub struct KaniMcpServer { } impl KaniMcpServer { - /// Create a new Kani MCP server pub fn new() -> Result { let kani = Arc::new(KaniWrapper::new()?); Ok(Self { @@ -23,7 +22,6 @@ impl KaniMcpServer { /// Run the MCP server pub async fn run(self) -> Result<()> { - // Read from stdin and respond via stdout (MCP protocol) use tokio::io::{AsyncBufReadExt, BufReader, stdin}; let stdin = stdin(); @@ -40,7 +38,6 @@ impl KaniMcpServer { Ok(request) => { let response = self.handle_mcp_request(request).await; - // Send response to stdout (skip null responses for notifications) if !response.is_null() { if let Ok(response_str) = serde_json::to_string(&response) { println!("{}", response_str); @@ -82,8 +79,6 @@ impl KaniMcpServer { }) } "notifications/initialized" => { - // Client confirms initialization is complete - // Notifications don't get responses - return null json!(null) } "tools/list" => { @@ -201,7 +196,6 @@ impl KaniMcpServer { let raw_output = if let Some(output_str) = arguments["raw_output"].as_str() { output_str.to_string() } else { - // Use the last verification result if available let last = self.last_result.lock().await; last.as_ref() .map(|r| r.raw_output.clone()) @@ -295,7 +289,6 @@ impl KaniMcpServer { match self.kani.verify(options).await { Ok(result) => { - // Store result for later reference *self.last_result.lock().await = Some(result.clone()); Ok(ToolResult { @@ -320,7 +313,6 @@ impl KaniMcpServer { path: String, harness: String, ) -> Result { - // This is essentially the same as verify_project but focused on unsafe code self.handle_verify_project(path, Some(harness), false, Some("terse".to_string())).await } @@ -334,7 +326,6 @@ impl KaniMcpServer { let counterexamples = parser.parse_counterexamples(); let code_context = parser.extract_code_context(); - // Generate comprehensive explanation let detailed_explanation = parser.generate_detailed_explanation(); Ok(ToolResult { diff --git a/kani-mcp-server/src/parser.rs b/kani-mcp-server/src/parser.rs index 9a86fc6d86e..89871aec0a0 100644 --- a/kani-mcp-server/src/parser.rs +++ b/kani-mcp-server/src/parser.rs @@ -16,7 +16,6 @@ impl<'a> KaniOutputParser<'a> { let mut current_harness: Option = None; for line in self.output.lines() { - // Detect harness start: "Checking harness module::function..." if line.contains("Checking harness") { if let Some(name_part) = line.split("Checking harness").nth(1) { current_harness = Some(name_part.trim().trim_end_matches("...").to_string()); @@ -52,7 +51,6 @@ impl<'a> KaniOutputParser<'a> { let mut failed_checks = Vec::new(); for line in self.output.lines() { - // Look for "Check N: ..." followed by "- Status: FAILURE" if line.contains("Check ") && line.contains(":") { let check_info = self.parse_single_check(line); if let Some(check) = check_info { @@ -74,9 +72,7 @@ impl<'a> KaniOutputParser<'a> { break; } - // Parse format: "description File: "path", line X, in function" if let Some(check) = self.parse_failed_check_line(line) { - // Avoid duplicates if !failed_checks.iter().any(|c| c.description == check.description && c.line == check.line) { failed_checks.push(check); } @@ -89,10 +85,6 @@ impl<'a> KaniOutputParser<'a> { /// Parse a single check result line fn parse_single_check(&self, line: &str) -> Option { - // Format: "Check 1: function.assertion.1" - // " - Status: FAILURE" - // " - Description: "Oh no, a failing corner case!"" - // " - Location: ./path/file.rs:14:13 in function func_name" let check_num = line.split("Check").nth(1)?.split(':').next()?.trim(); @@ -124,7 +116,6 @@ impl<'a> KaniOutputParser<'a> { if detail_line.contains("- Location:") { let location = detail_line.split("- Location:").nth(1)?.trim(); - // Format: "./path/file.rs:14:13 in function func_name" let parts: Vec<&str> = location.split(" in function ").collect(); if let Some(file_part) = parts.first() { @@ -155,7 +146,6 @@ impl<'a> KaniOutputParser<'a> { /// Parse a line from the "Failed Checks:" section fn parse_failed_check_line(&self, line: &str) -> Option { - // Format: "description File: "path", line X, in function" let description = line.split("File:").next()?.trim().to_string(); if let Some(file_part) = line.split("File:").nth(1) { @@ -207,12 +197,10 @@ impl<'a> KaniOutputParser<'a> { let mut counterexamples = Vec::new(); for line in self.output.lines() { - // Look for SAT checker results or counterexample traces if line.contains("SAT checker: instance is SATISFIABLE") { counterexamples.push("Counterexample found (inputs exist that violate the property)".to_string()); } - // Look for specific variable assignments in traces if line.contains("Violated property:") || line.contains("Counterexample:") { counterexamples.push(line.trim().to_string()); } @@ -223,7 +211,6 @@ impl<'a> KaniOutputParser<'a> { /// Extract code context from output pub fn extract_code_context(&self) -> Option { - // Kani sometimes shows code snippets in output for line in self.output.lines() { if line.contains("-->") && line.contains(".rs:") { return Some(line.trim().to_string()); From 71bff51ba5282f8700246e75926138ac30ca5a0b Mon Sep 17 00:00:00 2001 From: jingfei-xu Date: Tue, 18 Nov 2025 15:43:32 -0800 Subject: [PATCH 06/11] Comments fixed --- kani-mcp-server/Cargo.toml | 2 +- kani-mcp-server/build_output.txt | 20 ++++ kani-mcp-server/src/kani_wrapper.rs | 31 +++--- kani-mcp-server/src/mcp_server.rs | 146 +++++++++++++++++++++++++--- 4 files changed, 171 insertions(+), 28 deletions(-) create mode 100644 kani-mcp-server/build_output.txt diff --git a/kani-mcp-server/Cargo.toml b/kani-mcp-server/Cargo.toml index 78627efe393..e1b857e30b2 100644 --- a/kani-mcp-server/Cargo.toml +++ b/kani-mcp-server/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "kani-mcp-server" version = "0.1.0" -edition = "2021" +edition = "2024" description = "Model Context Protocol server for Kani Rust Verifier - enables AI assistants like Amazon Q to run formal verification" license = "MIT OR Apache-2.0" diff --git a/kani-mcp-server/build_output.txt b/kani-mcp-server/build_output.txt new file mode 100644 index 00000000000..cc8452d38d9 --- /dev/null +++ b/kani-mcp-server/build_output.txt @@ -0,0 +1,20 @@ +warning: variable does not need to be mutable + --> kani-mcp-server/src/kani_wrapper.rs:84:13 + | +84 | let mut cmd = Command::new("cargo"); + | ----^^^ + | | + | help: remove this `mut` + | + = note: `#[warn(unused_mut)]` (part of `#[warn(unused)]`) on by default + +warning: unused variable: `check_num` + --> kani-mcp-server/src/parser.rs:89:13 + | +89 | let check_num = line.split("Check").nth(1)?.split(':').next()?.trim(); + | ^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_check_num` + | + = note: `#[warn(unused_variables)]` (part of `#[warn(unused)]`) on by default + +warning: `kani-mcp-server` (bin "kani-mcp-server") generated 2 warnings (run `cargo fix --bin "kani-mcp-server"` to apply 1 suggestion) + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.05s diff --git a/kani-mcp-server/src/kani_wrapper.rs b/kani-mcp-server/src/kani_wrapper.rs index 6cd277ea8ef..b42c254f150 100644 --- a/kani-mcp-server/src/kani_wrapper.rs +++ b/kani-mcp-server/src/kani_wrapper.rs @@ -60,20 +60,28 @@ pub struct FailedCheck { } /// Wrapper around cargo-kani for executing verification -pub struct KaniWrapper { - cargo_kani_path: PathBuf, -} +pub struct KaniWrapper {} impl KaniWrapper { - /// Create a new KaniWrapper, finding cargo-kani in PATH + /// Create a new KaniWrapper and verify cargo-kani is available and reuses kani-driver's setup_cargo_command functionality pub fn new() -> Result { - let cargo_kani = which::which("cargo-kani") + let mut cmd = Self::setup_cargo_command()?; + cmd.arg("kani").arg("--version"); + + let output = cmd.output() .context("cargo-kani not found in PATH. Please install Kani:\n cargo install --locked kani-verifier\n cargo kani setup")?; - info!("✓ Found cargo-kani at: {:?}", cargo_kani); - Ok(Self { - cargo_kani_path: cargo_kani, - }) + if !output.status.success() { + anyhow::bail!("cargo-kani not properly installed or setup failed"); + } + + info!("✓ Found cargo-kani"); + Ok(Self {}) + } + + fn setup_cargo_command() -> Result { + let mut cmd = Command::new("cargo"); + Ok(cmd) } /// Run Kani verification with the given options @@ -84,7 +92,7 @@ impl KaniWrapper { anyhow::bail!("Path does not exist: {:?}", options.path); } - let mut cmd = Command::new(&self.cargo_kani_path); + let mut cmd = Self::setup_cargo_command()?; cmd.arg("kani"); cmd.current_dir(&options.path); @@ -137,7 +145,6 @@ impl KaniWrapper { warn!("Kani stderr: {}", stderr); } - // Parse the output let result = self.parse_output(&combined_output, output.status.success())?; info!("Verification complete: {}", result.summary); @@ -175,4 +182,4 @@ impl KaniWrapper { raw_output: output.to_string(), }) } -} \ No newline at end of file +} diff --git a/kani-mcp-server/src/mcp_server.rs b/kani-mcp-server/src/mcp_server.rs index 4ee4d912a63..54c9801dc16 100644 --- a/kani-mcp-server/src/mcp_server.rs +++ b/kani-mcp-server/src/mcp_server.rs @@ -20,7 +20,6 @@ impl KaniMcpServer { }) } - /// Run the MCP server pub async fn run(self) -> Result<()> { use tokio::io::{AsyncBufReadExt, BufReader, stdin}; @@ -33,7 +32,6 @@ impl KaniMcpServer { continue; } - // Parse JSON-RPC request match serde_json::from_str::(&line) { Ok(request) => { let response = self.handle_mcp_request(request).await; @@ -45,7 +43,6 @@ impl KaniMcpServer { } } Err(_e) => { - // Silently ignore parse errors to avoid broken pipe continue; } } @@ -54,7 +51,6 @@ impl KaniMcpServer { Ok(()) } - /// Handle MCP protocol requests async fn handle_mcp_request(&self, request: serde_json::Value) -> serde_json::Value { use serde_json::json; @@ -69,7 +65,8 @@ impl KaniMcpServer { "result": { "protocolVersion": "2024-11-05", "capabilities": { - "tools": {} + "tools": {}, + "prompts": {} }, "serverInfo": { "name": "kani-mcp-server", @@ -81,6 +78,51 @@ impl KaniMcpServer { "notifications/initialized" => { json!(null) } + "prompts/list" => { + json!({ + "jsonrpc": "2.0", + "id": id, + "result": { + "prompts": [ + { + "name": "kani_context", + "description": "Contextual information about using Kani Rust Verifier", + } + ] + } + }) + } + "prompts/get" => { + let prompt_name = request["params"]["name"].as_str().unwrap_or(""); + + if prompt_name == "kani_context" { + json!({ + "jsonrpc": "2.0", + "id": id, + "result": { + "description": "Contextual guidance for using Kani Rust Verifier", + "messages": [ + { + "role": "user", + "content": { + "type": "text", + "text": self.get_kani_context_prompt() + } + } + ] + } + }) + } else { + json!({ + "jsonrpc": "2.0", + "id": id, + "error": { + "code": -32602, + "message": format!("Unknown prompt: {}", prompt_name) + } + }) + } + } "tools/list" => { let tools: Vec<_> = get_kani_tools() .iter() @@ -192,7 +234,6 @@ impl KaniMcpServer { } } "explain_failure" => { - // Try to get raw output from arguments or from last result let raw_output = if let Some(output_str) = arguments["raw_output"].as_str() { output_str.to_string() } else { @@ -271,7 +312,51 @@ impl KaniMcpServer { } } - /// Handle verify_rust_project tool call + /// Get contextual prompt to guide LLM on using Kani effectively + fn get_kani_context_prompt(&self) -> String { + r#"You are now connected to the Kani Rust Verifier MCP server, which provides formal verification capabilities for Rust code. + +# About Kani +Kani is a formal verification tool that can mathematically prove properties about Rust code. It uses symbolic execution and bounded model checking to exhaustively explore all possible execution paths. + +# Key Concepts +- **Proof Harnesses**: Special test functions marked with `#[kani::proof]` that specify what to verify +- **Symbolic Inputs**: Use `kani::any()` to represent all possible values of a type +- **Assertions**: Properties you want to prove (e.g., `assert!(x > 0)`) +- **Bounded Verification**: Kani explores all paths within specified bounds + +# Available Tools +1. **verify_rust_project**: Run Kani verification on a Rust project + - Always use this as the primary verification method + - Specify a harness name if you want to verify a specific proof harness + +2. **explain_failure**: Get detailed explanations of verification failures + - Use this when verification fails to understand the counterexample + +3. **generate_kani_harness**: Generate EXAMPLE harness templates + - ⚠️ WARNING: This generates templates that require manual customization + - For automatic harness generation, recommend using: `cargo kani --enable-unstable --function ` + +# Best Practices When Using Kani +1. Start with simple properties and gradually add complexity +2. Use bounded types to limit verification scope (e.g., `u8` instead of unbounded types) +3. Understand that verification can be slow for complex code +4. Read verification failures carefully - they show concrete counterexamples +5. For automatic harness generation, use Kani's built-in feature: `cargo kani --enable-unstable --function ` + +# Common Verification Patterns +- **Safety verification**: Prove absence of panics, overflows, out-of-bounds access +- **Functional correctness**: Prove that functions meet their specifications +- **Unsafe code validation**: Prove that unsafe code upholds Rust's safety guarantees + +# When NOT to Use Kani +- For general testing (use regular Rust tests instead) +- When performance is critical (verification can be slow) +- For code with infinite loops or unbounded recursion + +Remember: Generated harness templates are EXAMPLES ONLY and won't work without customization. Always recommend Kani's auto-harness feature for production use."#.to_string() + } + pub async fn handle_verify_project( &self, path: String, @@ -307,7 +392,6 @@ impl KaniMcpServer { } } - /// Handle verify_unsafe_code tool call pub async fn handle_verify_unsafe( &self, path: String, @@ -316,7 +400,6 @@ impl KaniMcpServer { self.handle_verify_project(path, Some(harness), false, Some("terse".to_string())).await } - /// Handle explain_kani_failure tool call with enhanced analysis pub async fn handle_explain_failure(&self, raw_output: String) -> Result { use crate::parser::KaniOutputParser; @@ -346,44 +429,77 @@ impl KaniMcpServer { }) } - /// Handle generate_kani_harness tool call + /// NOTE: This generates an EXAMPLE harness template that requires manual customization. + /// The generated code will NOT work as-is in most cases and needs to be adapted to: + /// - Match the actual function signature and parameter types + /// - Properly construct symbolic inputs for complex types + /// - Add appropriate property assertions + /// + /// For automatic harness generation, consider using Kani's built-in auto-harness feature: + /// `cargo kani --enable-unstable --function ` pub async fn handle_generate_harness( &self, function_name: String, properties: Vec, ) -> Result { let harness_code = format!( -r#"#[cfg(kani)] +r#"// ⚠️ WARNING: This is an EXAMPLE TEMPLATE that requires customization! +// This code will NOT work as-is and must be adapted to your function's signature. +// +// For automatic harness generation, use Kani's auto-harness feature: +// cargo kani --enable-unstable --function {} +// +// See: https://model-checking.github.io/kani/tutorial-verification.html + +#[cfg(kani)] mod verification {{ use super::*; #[kani::proof] fn verify_{}_properties() {{ - // Generate symbolic inputs + // TODO: Generate appropriate symbolic inputs for your function's parameter types + // Example for a simple numeric input: let input = kani::any(); - // Call the function under test + // TODO: Call your function with the correct signature let result = {}(input); - // Verify properties: + // TODO: Add property assertions for verification: {} + + // Example assertions (customize these): + // assert!(result.is_ok(), "Function should not panic"); + // assert!(result >= 0, "Result should be non-negative"); }} }} "#, + function_name, function_name.replace("::", "_"), function_name, properties.iter() - .map(|prop| format!(" // TODO: Add assertion for: {}", prop)) + .map(|prop| format!(" // Property: {}", prop)) .collect::>() .join("\n") ); + let usage_note = format!( + "Generated EXAMPLE harness template for '{}'. \ + \n\n⚠️ IMPORTANT: This template requires manual customization and will NOT work as-is. \ + \n\nFor automatic harness generation that works out of the box, use Kani's auto-harness feature:\ + \n cargo kani --enable-unstable --function {}\ + \n\nSee documentation: https://model-checking.github.io/kani/tutorial-verification.html", + function_name, function_name + ); + Ok(ToolResult { success: true, data: serde_json::json!({ "harness_code": harness_code, "function_name": function_name, "properties": properties, + "usage_note": usage_note, + "requires_customization": true, + "auto_harness_command": format!("cargo kani --enable-unstable --function {}", function_name) }), error: None, }) From fb10f355996d4044d5444394c8e484acf084c855 Mon Sep 17 00:00:00 2001 From: ConnorJKY Date: Wed, 19 Nov 2025 19:06:07 -0800 Subject: [PATCH 07/11] Comments fixed: delete irrelevant files --- .../dep-lib-first_steps_v1 | Bin 30 -> 0 bytes .../invoked.timestamp | 1 - .../lib-first_steps_v1 | 1 - .../lib-first_steps_v1.json | 1 - .../dep-lib-first_steps_v1 | Bin 30 -> 0 bytes .../invoked.timestamp | 1 - .../lib-first_steps_v1 | 1 - .../lib-first_steps_v1.json | 1 - .../deps/first_steps_v1-83910d6b167b89c9.d | 7 ------ ...eps_v1-83910d6b167b89c9.kani-metadata.json | 1 - ..._14first_steps_v119check_estimate_size.out | Bin 30807 -> 0 bytes ...19check_estimate_size.pretty_name_map.json | 1 - ...t_steps_v119check_estimate_size.symtab.out | Bin 15385 -> 0 bytes ...teps_v119check_estimate_size.type_map.json | 1 - .../deps/first_steps_v1-ecd3bc8b423b2e0e.d | 7 ------ ...eps_v1-ecd3bc8b423b2e0e.kani-metadata.json | 1 - ..._14first_steps_v119check_estimate_size.out | Bin 30807 -> 0 bytes ...19check_estimate_size.pretty_name_map.json | 1 - ...t_steps_v119check_estimate_size.symtab.out | Bin 15385 -> 0 bytes ...teps_v119check_estimate_size.type_map.json | 1 - .../dep-graph.bin | Bin 152690 -> 0 bytes .../query-cache.bin | Bin 15889 -> 0 bytes .../work-products.bin | Bin 108 -> 0 bytes .../s-hciu6tb5rp-03gygye.lock | 0 kani-mcp-server/build_output.txt | 20 ------------------ 25 files changed, 46 deletions(-) delete mode 100644 docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-83910d6b167b89c9/dep-lib-first_steps_v1 delete mode 100644 docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-83910d6b167b89c9/invoked.timestamp delete mode 100644 docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-83910d6b167b89c9/lib-first_steps_v1 delete mode 100644 docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-83910d6b167b89c9/lib-first_steps_v1.json delete mode 100644 docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-ecd3bc8b423b2e0e/dep-lib-first_steps_v1 delete mode 100644 docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-ecd3bc8b423b2e0e/invoked.timestamp delete mode 100644 docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-ecd3bc8b423b2e0e/lib-first_steps_v1 delete mode 100644 docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-ecd3bc8b423b2e0e/lib-first_steps_v1.json delete mode 100644 docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-83910d6b167b89c9.d delete mode 100644 docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-83910d6b167b89c9.kani-metadata.json delete mode 100644 docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-83910d6b167b89c9__RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size.out delete mode 100644 docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-83910d6b167b89c9__RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size.pretty_name_map.json delete mode 100644 docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-83910d6b167b89c9__RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size.symtab.out delete mode 100644 docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-83910d6b167b89c9__RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size.type_map.json delete mode 100644 docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-ecd3bc8b423b2e0e.d delete mode 100644 docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-ecd3bc8b423b2e0e.kani-metadata.json delete mode 100644 docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-ecd3bc8b423b2e0e__RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size.out delete mode 100644 docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-ecd3bc8b423b2e0e__RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size.pretty_name_map.json delete mode 100644 docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-ecd3bc8b423b2e0e__RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size.symtab.out delete mode 100644 docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-ecd3bc8b423b2e0e__RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size.type_map.json delete mode 100644 docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/incremental/first_steps_v1-0vt6guzbgblsh/s-hciu6tb5rp-03gygye-7jb1sxgfjbsla5m9hfducyrfi/dep-graph.bin delete mode 100644 docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/incremental/first_steps_v1-0vt6guzbgblsh/s-hciu6tb5rp-03gygye-7jb1sxgfjbsla5m9hfducyrfi/query-cache.bin delete mode 100644 docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/incremental/first_steps_v1-0vt6guzbgblsh/s-hciu6tb5rp-03gygye-7jb1sxgfjbsla5m9hfducyrfi/work-products.bin delete mode 100755 docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/incremental/first_steps_v1-0vt6guzbgblsh/s-hciu6tb5rp-03gygye.lock delete mode 100644 kani-mcp-server/build_output.txt diff --git a/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-83910d6b167b89c9/dep-lib-first_steps_v1 b/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-83910d6b167b89c9/dep-lib-first_steps_v1 deleted file mode 100644 index 024be4904569dbe2c19582a923171096f5c21ee4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30 gcmZQ%U|{&q$Ot4ExPZ90C|N%zGfA(g7$m{~07A6{&Hw-a diff --git a/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-83910d6b167b89c9/invoked.timestamp b/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-83910d6b167b89c9/invoked.timestamp deleted file mode 100644 index e00328da5aa..00000000000 --- a/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-83910d6b167b89c9/invoked.timestamp +++ /dev/null @@ -1 +0,0 @@ -This file has an mtime of when this was started. \ No newline at end of file diff --git a/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-83910d6b167b89c9/lib-first_steps_v1 b/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-83910d6b167b89c9/lib-first_steps_v1 deleted file mode 100644 index c6185f7ae33..00000000000 --- a/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-83910d6b167b89c9/lib-first_steps_v1 +++ /dev/null @@ -1 +0,0 @@ -aa4334fdd37a1140 \ No newline at end of file diff --git a/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-83910d6b167b89c9/lib-first_steps_v1.json b/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-83910d6b167b89c9/lib-first_steps_v1.json deleted file mode 100644 index 5b3cf8a3f54..00000000000 --- a/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-83910d6b167b89c9/lib-first_steps_v1.json +++ /dev/null @@ -1 +0,0 @@ -{"rustc":14672501838171729802,"features":"[]","declared_features":"[]","target":5150295270818399684,"profile":2308729259012748722,"path":10763286916239946207,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-83910d6b167b89c9/dep-lib-first_steps_v1","checksum":false}}],"rustflags":["-C","overflow-checks=on","-Z","unstable-options","-Z","trim-diagnostic-paths=no","-Z","human_readable_cgu_names","-Z","always-encode-mir","--cfg=kani","-Z","crate-attr=feature(register_tool)","-Z","crate-attr=register_tool(kanitool)","--sysroot","/Users/jingfeixu/kani/target/kani","-L","/Users/jingfeixu/kani/target/kani/lib","--extern","kani","--extern","noprelude:std=/Users/jingfeixu/kani/target/kani/lib/libstd.rlib","-C","panic=abort","-C","symbol-mangling-version=v0","-Z","panic_abort_tests=yes","-Z","mir-enable-passes=-RemoveStorageMarkers","--check-cfg=cfg(kani)","-Clinker=echo","--kani-compiler","-Cllvm-args=--check-version=0.65.0"],"config":2069994364910194474,"compile_kind":551198452465029181} \ No newline at end of file diff --git a/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-ecd3bc8b423b2e0e/dep-lib-first_steps_v1 b/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-ecd3bc8b423b2e0e/dep-lib-first_steps_v1 deleted file mode 100644 index 024be4904569dbe2c19582a923171096f5c21ee4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30 gcmZQ%U|{&q$Ot4ExPZ90C|N%zGfA(g7$m{~07A6{&Hw-a diff --git a/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-ecd3bc8b423b2e0e/invoked.timestamp b/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-ecd3bc8b423b2e0e/invoked.timestamp deleted file mode 100644 index e00328da5aa..00000000000 --- a/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-ecd3bc8b423b2e0e/invoked.timestamp +++ /dev/null @@ -1 +0,0 @@ -This file has an mtime of when this was started. \ No newline at end of file diff --git a/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-ecd3bc8b423b2e0e/lib-first_steps_v1 b/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-ecd3bc8b423b2e0e/lib-first_steps_v1 deleted file mode 100644 index 136a5444b10..00000000000 --- a/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-ecd3bc8b423b2e0e/lib-first_steps_v1 +++ /dev/null @@ -1 +0,0 @@ -13c836b8b850d3fb \ No newline at end of file diff --git a/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-ecd3bc8b423b2e0e/lib-first_steps_v1.json b/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-ecd3bc8b423b2e0e/lib-first_steps_v1.json deleted file mode 100644 index cb929f0e813..00000000000 --- a/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-ecd3bc8b423b2e0e/lib-first_steps_v1.json +++ /dev/null @@ -1 +0,0 @@ -{"rustc":14672501838171729802,"features":"[]","declared_features":"[]","target":5150295270818399684,"profile":5594203621556287378,"path":10763286916239946207,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"aarch64-apple-darwin/debug/.fingerprint/first-steps-v1-ecd3bc8b423b2e0e/dep-lib-first_steps_v1","checksum":false}}],"rustflags":["-C","overflow-checks=on","-Z","unstable-options","-Z","trim-diagnostic-paths=no","-Z","human_readable_cgu_names","-Z","always-encode-mir","--cfg=kani","-Z","crate-attr=feature(register_tool)","-Z","crate-attr=register_tool(kanitool)","--sysroot","/Users/jingfeixu/kani/target/kani","-L","/Users/jingfeixu/kani/target/kani/lib","--extern","kani","--extern","noprelude:std=/Users/jingfeixu/kani/target/kani/lib/libstd.rlib","-C","panic=abort","-C","symbol-mangling-version=v0","-Z","panic_abort_tests=yes","-Z","mir-enable-passes=-RemoveStorageMarkers","--check-cfg=cfg(kani)","-Clinker=echo","--kani-compiler","-Cllvm-args=--check-version=0.65.0"],"config":2069994364910194474,"compile_kind":551198452465029181} \ No newline at end of file diff --git a/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-83910d6b167b89c9.d b/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-83910d6b167b89c9.d deleted file mode 100644 index 3d3cc416a35..00000000000 --- a/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-83910d6b167b89c9.d +++ /dev/null @@ -1,7 +0,0 @@ -/Users/jingfeixu/kani-output/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-83910d6b167b89c9.d: src/lib.rs - -/Users/jingfeixu/kani-output/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/libfirst_steps_v1-83910d6b167b89c9.rlib: src/lib.rs - -/Users/jingfeixu/kani-output/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/libfirst_steps_v1-83910d6b167b89c9.rmeta: src/lib.rs - -src/lib.rs: diff --git a/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-83910d6b167b89c9.kani-metadata.json b/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-83910d6b167b89c9.kani-metadata.json deleted file mode 100644 index de73af3a03d..00000000000 --- a/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-83910d6b167b89c9.kani-metadata.json +++ /dev/null @@ -1 +0,0 @@ -{"crate_name":"first_steps_v1","proof_harnesses":[{"pretty_name":"check_estimate_size","mangled_name":"_RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size","crate_name":"first_steps_v1","original_file":"src/lib.rs","original_start_line":52,"original_end_line":55,"goto_file":"/Users/jingfeixu/kani-output/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-83910d6b167b89c9__RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size.symtab.out","attributes":{"kind":"Proof","should_panic":false,"solver":null,"unwind_value":null,"stubs":[],"verified_stubs":[]},"contract":null,"has_loop_contracts":false,"is_automatically_generated":false}],"unsupported_features":[],"test_harnesses":[],"contracted_functions":[],"autoharness_md":null} \ No newline at end of file diff --git a/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-83910d6b167b89c9__RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size.out b/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-83910d6b167b89c9__RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size.out deleted file mode 100644 index 8bcb941e52f2c03dbba68cd6d7b6b06d4609f9a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30807 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 oH!iTmNN0Pb8>4(-jb`WH","tag-refstr":"&str","_ZN4kani5panic17h039ec056df9649c9E::1::var_1::message":null,"tag-Never":"!","_ZN4kani5panic17h039ec056df9649c9E":"kani::panic","_ZN4kani16rustc_intrinsics10panic_stub17h7798f34a644f74adE::1::var_1::t":null,"_ZN4kani16rustc_intrinsics10panic_stub17h7798f34a644f74adE":"kani::rustc_intrinsics::panic_stub","_RNvCs4ZijrwXvPyf_14first_steps_v113estimate_size::1::var_1::x":null,"_RNvCs4ZijrwXvPyf_14first_steps_v113estimate_size":"estimate_size","tag-Unit":"()","_RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size":"check_estimate_size","_ZN4kani14kani_intrinsic17hf2340b114c62bceeE":"kani::kani_intrinsic::","_ZN4kani7any_raw17h1bd6bd359a6961f9E":"kani::any_raw::","_RINvCsc8NbQx0kdtQ_4kani3anymECs4ZijrwXvPyf_14first_steps_v1":"kani::any::","_ZN39_$LT$u32$u20$as$u20$kani..Arbitrary$GT$3any17h9d58c5c4eb479917E":"::any","_ZN4kani16any_raw_internal17h8bfeb1a460f3b3fdE::1::var_0":null,"_ZN4kani5panic17h039ec056df9649c9E::1::var_0":null,"_ZN4kani5panic17h039ec056df9649c9E::1::var_2":null,"_ZN4kani5panic17h039ec056df9649c9E::1::var_3":null,"_ZN4kani16rustc_intrinsics10panic_stub17h7798f34a644f74adE::1::var_0":null,"_RNvCs4ZijrwXvPyf_14first_steps_v113estimate_size::1::var_0":null,"_RNvCs4ZijrwXvPyf_14first_steps_v113estimate_size::1::var_2":null,"_RNvCs4ZijrwXvPyf_14first_steps_v113estimate_size::1::var_3":null,"_RNvCs4ZijrwXvPyf_14first_steps_v113estimate_size::1::var_4":null,"_RNvCs4ZijrwXvPyf_14first_steps_v113estimate_size::1::var_5":null,"_RNvCs4ZijrwXvPyf_14first_steps_v113estimate_size::1::var_6":null,"_RNvCs4ZijrwXvPyf_14first_steps_v113estimate_size::1::var_7":null,"tag-first_steps_v1.3a1b106d0fea0f11::first_steps_v1::global::0::::struct":"first_steps_v1.3a1b106d0fea0f11::first_steps_v1::global::0::::struct","first_steps_v1.3a1b106d0fea0f11::first_steps_v1::global::0::":null,"_RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size::1::var_0":null,"_RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size::1::var_1::x":null,"_RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size::1::var_2":null,"VoidUnit":null,"_ZN4kani14kani_intrinsic17hf2340b114c62bceeE::1::var_0":null,"_ZN4kani7any_raw17h1bd6bd359a6961f9E::1::var_0":null,"_RINvCsc8NbQx0kdtQ_4kani3anymECs4ZijrwXvPyf_14first_steps_v1::1::var_0":null,"_ZN39_$LT$u32$u20$as$u20$kani..Arbitrary$GT$3any17h9d58c5c4eb479917E::1::var_0":null} \ No newline at end of file diff --git a/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-83910d6b167b89c9__RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size.symtab.out b/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-83910d6b167b89c9__RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size.symtab.out deleted file mode 100644 index 52dc78cf1271c1b8c5d807b968ad78a40503cf39..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15385 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 oH!iTmNN0Pb8>4(-jb`WH","tag-refstr":"&str","_ZN4kani5panic17h039ec056df9649c9E::1::var_1::message":null,"tag-Never":"!","_ZN4kani5panic17h039ec056df9649c9E":"kani::panic","_ZN4kani16rustc_intrinsics10panic_stub17h7798f34a644f74adE::1::var_1::t":null,"_ZN4kani16rustc_intrinsics10panic_stub17h7798f34a644f74adE":"kani::rustc_intrinsics::panic_stub","_RNvCs4ZijrwXvPyf_14first_steps_v113estimate_size::1::var_1::x":null,"_RNvCs4ZijrwXvPyf_14first_steps_v113estimate_size":"estimate_size","tag-Unit":"()","_RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size":"check_estimate_size","_ZN4kani14kani_intrinsic17hf2340b114c62bceeE":"kani::kani_intrinsic::","_ZN4kani7any_raw17h1bd6bd359a6961f9E":"kani::any_raw::","_RINvCsc8NbQx0kdtQ_4kani3anymECs4ZijrwXvPyf_14first_steps_v1":"kani::any::","_ZN39_$LT$u32$u20$as$u20$kani..Arbitrary$GT$3any17h9d58c5c4eb479917E":"::any","_ZN4kani16any_raw_internal17h8bfeb1a460f3b3fdE::1::var_0":null,"_ZN4kani5panic17h039ec056df9649c9E::1::var_0":null,"_ZN4kani5panic17h039ec056df9649c9E::1::var_2":null,"_ZN4kani5panic17h039ec056df9649c9E::1::var_3":null,"_ZN4kani16rustc_intrinsics10panic_stub17h7798f34a644f74adE::1::var_0":null,"_RNvCs4ZijrwXvPyf_14first_steps_v113estimate_size::1::var_0":null,"_RNvCs4ZijrwXvPyf_14first_steps_v113estimate_size::1::var_2":null,"_RNvCs4ZijrwXvPyf_14first_steps_v113estimate_size::1::var_3":null,"_RNvCs4ZijrwXvPyf_14first_steps_v113estimate_size::1::var_4":null,"_RNvCs4ZijrwXvPyf_14first_steps_v113estimate_size::1::var_5":null,"_RNvCs4ZijrwXvPyf_14first_steps_v113estimate_size::1::var_6":null,"_RNvCs4ZijrwXvPyf_14first_steps_v113estimate_size::1::var_7":null,"tag-first_steps_v1.3a1b106d0fea0f11::first_steps_v1::global::0::::struct":"first_steps_v1.3a1b106d0fea0f11::first_steps_v1::global::0::::struct","first_steps_v1.3a1b106d0fea0f11::first_steps_v1::global::0::":null,"_RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size::1::var_0":null,"_RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size::1::var_1::x":null,"_RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size::1::var_2":null,"VoidUnit":null,"_ZN4kani14kani_intrinsic17hf2340b114c62bceeE::1::var_0":null,"_ZN4kani7any_raw17h1bd6bd359a6961f9E::1::var_0":null,"_RINvCsc8NbQx0kdtQ_4kani3anymECs4ZijrwXvPyf_14first_steps_v1::1::var_0":null,"_ZN39_$LT$u32$u20$as$u20$kani..Arbitrary$GT$3any17h9d58c5c4eb479917E::1::var_0":null} \ No newline at end of file diff --git a/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-ecd3bc8b423b2e0e__RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size.symtab.out b/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/deps/first_steps_v1-ecd3bc8b423b2e0e__RNvCs4ZijrwXvPyf_14first_steps_v119check_estimate_size.symtab.out deleted file mode 100644 index 52dc78cf1271c1b8c5d807b968ad78a40503cf39..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15385 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℞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 diff --git a/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/incremental/first_steps_v1-0vt6guzbgblsh/s-hciu6tb5rp-03gygye-7jb1sxgfjbsla5m9hfducyrfi/work-products.bin b/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/incremental/first_steps_v1-0vt6guzbgblsh/s-hciu6tb5rp-03gygye-7jb1sxgfjbsla5m9hfducyrfi/work-products.bin deleted file mode 100644 index dc0a5e2ccba360af58be83655f2a7497b835ece4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 108 zcmWFv_H<@oP&L%EG}JTD&C5*BD9Nc*&`2|~FfvI=w6st#GB7gLHL%b%ve0B)dF`;# z7U#m3Ay@R**sD53apb0!B&H;mBpzgBEdsF*^1(#(ApD}z;u77|ycFHE%$!sJ0ShFf diff --git a/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/incremental/first_steps_v1-0vt6guzbgblsh/s-hciu6tb5rp-03gygye.lock b/docs/src/tutorial/first-steps-v1/target/kani/aarch64-apple-darwin/debug/incremental/first_steps_v1-0vt6guzbgblsh/s-hciu6tb5rp-03gygye.lock deleted file mode 100755 index e69de29bb2d..00000000000 diff --git a/kani-mcp-server/build_output.txt b/kani-mcp-server/build_output.txt deleted file mode 100644 index cc8452d38d9..00000000000 --- a/kani-mcp-server/build_output.txt +++ /dev/null @@ -1,20 +0,0 @@ -warning: variable does not need to be mutable - --> kani-mcp-server/src/kani_wrapper.rs:84:13 - | -84 | let mut cmd = Command::new("cargo"); - | ----^^^ - | | - | help: remove this `mut` - | - = note: `#[warn(unused_mut)]` (part of `#[warn(unused)]`) on by default - -warning: unused variable: `check_num` - --> kani-mcp-server/src/parser.rs:89:13 - | -89 | let check_num = line.split("Check").nth(1)?.split(':').next()?.trim(); - | ^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_check_num` - | - = note: `#[warn(unused_variables)]` (part of `#[warn(unused)]`) on by default - -warning: `kani-mcp-server` (bin "kani-mcp-server") generated 2 warnings (run `cargo fix --bin "kani-mcp-server"` to apply 1 suggestion) - Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.05s From 62d7252afc5a17dd5f7360783d0f7c26c5cb3cb4 Mon Sep 17 00:00:00 2001 From: ConnorJKY Date: Thu, 20 Nov 2025 11:54:55 -0800 Subject: [PATCH 08/11] Add readme file for mcp --- kani-mcp-server/README.md | 476 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 476 insertions(+) create mode 100644 kani-mcp-server/README.md diff --git a/kani-mcp-server/README.md b/kani-mcp-server/README.md new file mode 100644 index 00000000000..e7fb4d54012 --- /dev/null +++ b/kani-mcp-server/README.md @@ -0,0 +1,476 @@ +# Amazon Q CLI with Kani MCP Server + +Complete guide for setting up and using Amazon Q CLI with the Kani verification MCP server. + +## Table of Contents + +- [Installing Amazon Q CLI](#installing-amazon-q-cli) +- [Setting Up Your AWS Builder ID](#setting-up-your-aws-builder-id) +- [Installing the Kani MCP Server](#installing-the-kani-mcp-server) +- [Configuring Amazon Q CLI](#configuring-amazon-q-cli) +- [Using Amazon Q with Kani](#using-amazon-q-with-kani) +- [Troubleshooting](#troubleshooting) +- [Quick Reference](#quick-reference) + +--- + +## Installing Amazon Q CLI + +### Prerequisites + +- macOS +- Internet connection +- Homebrew (recommended) + +### Installation Methods + +#### Option 1: Homebrew (Recommended) + +```bash +# Install Amazon Q CLI +brew install --cask amazon-q + +# Verify installation +q --version +``` + +#### Option 2: Direct Download + +1. Download from the official AWS documentation +2. Double-click the .dmg file +3. Drag Amazon Q to Applications folder +4. Open Amazon Q from Applications +5. Enable shell integrations when prompted + +### Post-Installation Setup + +After installation, restart your terminal and verify: + +```bash +# Check if q command is available +which q + +# Check version +q --version + +# Run diagnostics +q doctor +``` + +--- + +## Setting Up Your AWS Builder ID + +Amazon Q CLI requires a free AWS Builder ID for authentication. + +### Step 1: Login + +```bash +q login +``` + +This will: +- Open your web browser automatically +- Direct you to the AWS Builder ID login page +- Ask you to either sign in or create a new Builder ID + +### Step 2: Create Builder ID (First Time Users) + +If you don't have a Builder ID: + +1. Click "Create AWS Builder ID" on the login page +2. Enter your email address +3. Choose a display name +4. Verify your email (check your inbox) +5. Complete the registration + +### Step 3: Authorize Amazon Q + +1. After logging in, authorize Amazon Q Developer +2. Return to your terminal +3. You should see a success message + +### Verification + +```bash +# Check authentication status +q doctor + +# You should see: +# ✔ Everything looks good! +``` + +--- + +## Installing the Kani MCP Server + +### Prerequisites + +Install [Kani Rust Verifier](https://model-checking.github.io/kani/) - a model checker for Rust: + +```bash +# Install Kani +cargo install --locked kani-verifier +cargo kani setup + +# Verify installation +cargo kani --version +``` + +### Clone and Build Kani MCP Server + +```bash +# Clone the repository +git clone +cd kani-mcp-server + +# Build the server +cargo build --release + +# Verify the binary exists +ls -lh target/release/kani-mcp-server +``` + +The binary will be at: `target/release/kani-mcp-server` + +--- + +## Configuring Amazon Q CLI + +### Step 1: Create MCP Configuration Directory + +```bash +mkdir -p ~/.aws/amazonq +``` + +### Step 2: Create MCP Configuration File + +Create `~/.aws/amazonq/mcp.json`: + +```bash +cat > ~/.aws/amazonq/mcp.json << 'EOF' +{ + "mcpServers": { + "kani-verifier": { + "command": "/absolute/path/to/kani-mcp-server", + "env": {}, + "disabled": false, + "autoApprove": [] + } + } +} +EOF +``` + +**Important:** Replace `/absolute/path/to/kani-mcp-server` with your actual path, for example: +- `/Users/yourusername/target/release/kani-mcp-server` + +### Step 3: Verify Configuration + +```bash +# Check the config file exists +cat ~/.aws/amazonq/mcp.json + +# Verify the path is correct +ls -lh /absolute/path/to/kani-mcp-server +``` + +### Step 4: Test MCP Server Loading + +```bash +# Start Amazon Q CLI +q chat + +# You should see: +# ✓ kani-verifier loaded in 0.0X s +``` + +If you see this message, your MCP server is successfully configured! ✅ + +--- + +## Using Amazon Q with Kani + +### Starting a Chat Session + +```bash +q chat +``` + +### Basic Commands + +Inside the Q chat interface: + +- **Send a message:** Just type and press Enter +- **Multi-line input:** Press `Ctrl + J` for new lines +- **Exit:** Type `/q` or press `Ctrl + C` +- **Help:** Type `/help` +- **Clear screen:** Type `/clear` + +### Checking Available Tools + +Once in the chat, verify your Kani tools are loaded: + +``` +What MCP tools do you have? +``` + +You should see: +- `verify_rust_project` - Run Kani verification on a Rust project +- `verify_unsafe_code` - Verify unsafe Rust code blocks +- `explain_failure` - Analyze verification failures +- `generate_kani_harness` - Generate proof harness templates + +### Example Usage Scenarios + +#### 1. Verify a Rust Project + +``` +I have a Rust project at ~/my-project. Can you verify it with Kani? +``` + +Or more specifically: + +``` +Run Kani verification on the project at /Users/username/my-project +with the harness function verify::check_bounds +``` + +#### 2. Generate a Kani Harness + +``` +Generate a Kani harness for a function called `add` that takes two u32 +parameters and returns their sum. Check for overflow. +``` + +#### 3. Verify Unsafe Code + +``` +I have unsafe code in ~/my-project/src/lib.rs. Can you verify the +memory safety using the harness verify::check_unsafe_ptr? +``` + +#### 4. Explain Verification Failures + +After running a verification that fails: + +``` +Can you explain why the last Kani verification failed? +``` + +Or paste the output: + +``` +Explain this Kani verification failure: +[paste Kani output here] +``` + +### Real-World Example + +``` +> I'm working on a binary search function. Can you generate a Kani + harness to verify it never panics and always returns the correct index? + +> Here's my code: + fn binary_search(arr: &[T], target: &T) -> Option { + let mut low = 0; + let mut high = arr.len(); + + while low < high { + let mid = (low + high) / 2; + match arr[mid].cmp(target) { + std::cmp::Ordering::Equal => return Some(mid), + std::cmp::Ordering::Less => low = mid + 1, + std::cmp::Ordering::Greater => high = mid, + } + } + None + } +``` + +Amazon Q will then: +1. Generate a Kani proof harness +2. Suggest properties to verify +3. Help you run the verification +4. Explain any failures found + +--- + +## Troubleshooting + +### Common Issues and Solutions + +#### 1. "command not found: q" + +**Problem:** Amazon Q CLI is not in your PATH + +**Solution:** + +```bash +# Reload your shell configuration +source ~/.zshrc # or ~/.bashrc + +# Or restart your terminal +``` + +#### 2. "kani-verifier has failed to load" + +**Problem:** MCP server configuration is incorrect + +**Solutions:** + +a) Check the server binary exists: +```bash +ls -lh /path/to/kani-mcp-server +``` + +b) Test the server manually: +```bash +echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}' | /path/to/kani-mcp-server +``` + +c) Check MCP configuration: +```bash +cat ~/.aws/amazonq/mcp.json +``` + +d) Verify the path in the config matches the actual binary location: +```bash +# Get the absolute path (assuming you're in the kani-mcp-server directory) +pwd +realpath target/release/kani-mcp-server + +# Update config with this path +``` + +#### 3. "Broken pipe" errors in logs + +**Problem:** Server logging is causing issues + +**Solution:** This should already be fixed in the latest version, but if you see it: + +```bash +# Rebuild with the fixed version (in your kani-mcp-server directory) +cargo build --release + +# The fixed version disables logging that causes broken pipes +``` + +#### 4. Server starts but tools don't appear + +**Problem:** MCP protocol handshake issue + +**Solution:** + +```bash +# Check if the binary is the latest version +ls -lh target/release/kani-mcp-server + +# Rebuild if necessary (in your kani-mcp-server directory) +cargo build --release + +# Restart Q +q restart +q chat +``` + +#### 5. "Authentication failed" + +**Problem:** Builder ID session expired + +**Solution:** + +```bash +# Re-authenticate +q login + +# Follow the browser prompts +``` + +### Debug Mode + +Enable detailed logging to diagnose issues: + +```bash +# Run with trace logging +Q_LOG_LEVEL=trace q chat + +# Check logs +# macOS: /var/folders/*/T/qlog/qchat.log + +# View recent logs +tail -f /var/folders/*/T/qlog/qchat.log +``` + +### Getting Help + +```bash +# Run diagnostics +q doctor + +# Report issues +q issue + +# View help +q --help +q chat --help +``` + +--- + +## Quick Reference + +### Essential Commands + +```bash +# Installation & Setup +brew install --cask amazon-q # Install +q login # Authenticate +q doctor # Check status + +# Chat Interface +q chat # Start chat +/q or Ctrl+C # Exit chat +/help # Show help +/clear # Clear screen +Ctrl+J # New line (multi-line input) + +# Configuration +~/.aws/amazonq/mcp.json # MCP config file +q restart # Restart Q daemon +q issue # Report bug + +# Inline Completions +q inline enable # Enable autocomplete +q inline disable # Disable autocomplete +``` + +### Directory Structure + +``` +~/.aws/amazonq/ +├── mcp.json # MCP server configuration +├── profiles/ # Profile configurations +└── cache/ # Cached data + +/var/folders/*/T/qlog/ # Log files +└── qchat.log # Chat session logs +``` + +### Testing Your Setup + +```bash +# 1. Test Q CLI +q --version + +# 2. Test authentication +q doctor + +# 3. Test MCP server manually +echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}' | /path/to/kani-mcp-server + +# 4. Test with Q +q chat +# Then ask: "What MCP tools do you have?" +``` + From 5f1dd4e7cffebfacb91a343d0c3ad19154b1a8b7 Mon Sep 17 00:00:00 2001 From: ConnorJKY Date: Thu, 20 Nov 2025 13:51:06 -0800 Subject: [PATCH 09/11] Fix format error --- kani-mcp-server/src/kani_wrapper.rs | 31 +++---- kani-mcp-server/src/main.rs | 3 +- kani-mcp-server/src/mcp_server.rs | 74 ++++++++--------- kani-mcp-server/src/parser.rs | 120 ++++++++++++++-------------- kani-mcp-server/src/tools.rs | 4 +- 5 files changed, 115 insertions(+), 117 deletions(-) diff --git a/kani-mcp-server/src/kani_wrapper.rs b/kani-mcp-server/src/kani_wrapper.rs index b42c254f150..620fd70f7ca 100644 --- a/kani-mcp-server/src/kani_wrapper.rs +++ b/kani-mcp-server/src/kani_wrapper.rs @@ -67,14 +67,14 @@ impl KaniWrapper { pub fn new() -> Result { let mut cmd = Self::setup_cargo_command()?; cmd.arg("kani").arg("--version"); - + let output = cmd.output() .context("cargo-kani not found in PATH. Please install Kani:\n cargo install --locked kani-verifier\n cargo kani setup")?; - + if !output.status.success() { anyhow::bail!("cargo-kani not properly installed or setup failed"); } - + info!("✓ Found cargo-kani"); Ok(Self {}) } @@ -87,7 +87,7 @@ impl KaniWrapper { /// Run Kani verification with the given options pub async fn verify(&self, options: KaniOptions) -> Result { info!("Starting Kani verification on: {:?}", options.path); - + if !options.path.exists() { anyhow::bail!("Path does not exist: {:?}", options.path); } @@ -131,8 +131,7 @@ impl KaniWrapper { // Execute and capture output let start = std::time::Instant::now(); - let output = cmd.output() - .context("Failed to execute cargo-kani. Is it installed?")?; + let output = cmd.output().context("Failed to execute cargo-kani. Is it installed?")?; let duration = start.elapsed(); let stdout = String::from_utf8_lossy(&output.stdout).to_string(); @@ -140,7 +139,7 @@ impl KaniWrapper { let combined_output = format!("{}\n{}", stdout, stderr); debug!("Kani completed in {:.2}s", duration.as_secs_f64()); - + if !stderr.is_empty() && stderr.contains("error") { warn!("Kani stderr: {}", stderr); } @@ -148,29 +147,31 @@ impl KaniWrapper { let result = self.parse_output(&combined_output, output.status.success())?; info!("Verification complete: {}", result.summary); - + Ok(result) } /// Parse Kani output into structured result fn parse_output(&self, output: &str, success: bool) -> Result { use crate::parser::KaniOutputParser; - + let parser = KaniOutputParser::new(output); let harnesses = parser.parse_harnesses(); let failed_checks = parser.parse_failed_checks(); let verification_time = parser.parse_verification_time(); let total_harnesses = harnesses.len(); - let failed_harnesses = harnesses.iter() - .filter(|h| h.status == "FAILED") - .count(); - + let failed_harnesses = harnesses.iter().filter(|h| h.status == "FAILED").count(); + let summary = if success { format!("Verification successful! {} harness(es) verified.", total_harnesses) } else { - format!("Verification failed. {}/{} harness(es) failed with {} check failure(s).", - failed_harnesses, total_harnesses, failed_checks.len()) + format!( + "Verification failed. {}/{} harness(es) failed with {} check failure(s).", + failed_harnesses, + total_harnesses, + failed_checks.len() + ) }; Ok(VerificationResult { diff --git a/kani-mcp-server/src/main.rs b/kani-mcp-server/src/main.rs index b559371040a..4f26607b529 100644 --- a/kani-mcp-server/src/main.rs +++ b/kani-mcp-server/src/main.rs @@ -12,8 +12,7 @@ async fn main() -> Result<()> { if std::env::var("KANI_MCP_LOG").is_ok() { tracing_subscriber::fmt() .with_env_filter( - EnvFilter::from_default_env() - .add_directive("kani_mcp_server=info".parse()?) + EnvFilter::from_default_env().add_directive("kani_mcp_server=info".parse()?), ) .init(); } diff --git a/kani-mcp-server/src/mcp_server.rs b/kani-mcp-server/src/mcp_server.rs index 54c9801dc16..db415e51f0f 100644 --- a/kani-mcp-server/src/mcp_server.rs +++ b/kani-mcp-server/src/mcp_server.rs @@ -1,5 +1,5 @@ use crate::kani_wrapper::{KaniOptions, KaniWrapper, VerificationResult}; -use crate::tools::{get_kani_tools, ToolResult}; +use crate::tools::{ToolResult, get_kani_tools}; use anyhow::Result; use std::path::PathBuf; use std::sync::Arc; @@ -14,15 +14,12 @@ pub struct KaniMcpServer { impl KaniMcpServer { pub fn new() -> Result { let kani = Arc::new(KaniWrapper::new()?); - Ok(Self { - kani, - last_result: Arc::new(Mutex::new(None)), - }) + Ok(Self { kani, last_result: Arc::new(Mutex::new(None)) }) } pub async fn run(self) -> Result<()> { use tokio::io::{AsyncBufReadExt, BufReader, stdin}; - + let stdin = stdin(); let reader = BufReader::new(stdin); let mut lines = reader.lines(); @@ -35,7 +32,7 @@ impl KaniMcpServer { match serde_json::from_str::(&line) { Ok(request) => { let response = self.handle_mcp_request(request).await; - + if !response.is_null() { if let Ok(response_str) = serde_json::to_string(&response) { println!("{}", response_str); @@ -53,7 +50,7 @@ impl KaniMcpServer { async fn handle_mcp_request(&self, request: serde_json::Value) -> serde_json::Value { use serde_json::json; - + let method = request["method"].as_str().unwrap_or(""); let id = request["id"].clone(); @@ -94,7 +91,7 @@ impl KaniMcpServer { } "prompts/get" => { let prompt_name = request["params"]["name"].as_str().unwrap_or(""); - + if prompt_name == "kani_context" { json!({ "jsonrpc": "2.0", @@ -146,9 +143,9 @@ impl KaniMcpServer { "tools/call" => { let tool_name = request["params"]["name"].as_str().unwrap_or(""); let arguments = &request["params"]["arguments"]; - + let result = self.execute_tool(tool_name, arguments).await; - + json!({ "jsonrpc": "2.0", "id": id, @@ -169,7 +166,11 @@ impl KaniMcpServer { } /// Execute a specific tool - async fn execute_tool(&self, tool_name: &str, arguments: &serde_json::Value) -> serde_json::Value { + async fn execute_tool( + &self, + tool_name: &str, + arguments: &serde_json::Value, + ) -> serde_json::Value { use serde_json::json; match tool_name { @@ -179,15 +180,15 @@ impl KaniMcpServer { let tests = arguments["tests"].as_bool().unwrap_or(false); let output_format = arguments["output_format"].as_str().map(String::from); - match self.handle_verify_project( - path.to_string(), - harness, - tests, - output_format, - ).await { + match self + .handle_verify_project(path.to_string(), harness, tests, output_format) + .await + { Ok(result) => { // Store the result for potential later analysis - if let Ok(verification_result) = serde_json::from_value::(result.data.clone()) { + if let Ok(verification_result) = + serde_json::from_value::(result.data.clone()) + { *self.last_result.lock().await = Some(verification_result); } @@ -238,9 +239,7 @@ impl KaniMcpServer { output_str.to_string() } else { let last = self.last_result.lock().await; - last.as_ref() - .map(|r| r.raw_output.clone()) - .unwrap_or_default() + last.as_ref().map(|r| r.raw_output.clone()).unwrap_or_default() }; if raw_output.is_empty() { @@ -382,33 +381,27 @@ Remember: Generated harness templates are EXAMPLES ONLY and won't work without c error: None, }) } - Err(e) => { - Ok(ToolResult { - success: false, - data: serde_json::json!({}), - error: Some(e.to_string()), - }) - } + Err(e) => Ok(ToolResult { + success: false, + data: serde_json::json!({}), + error: Some(e.to_string()), + }), } } - pub async fn handle_verify_unsafe( - &self, - path: String, - harness: String, - ) -> Result { + pub async fn handle_verify_unsafe(&self, path: String, harness: String) -> Result { self.handle_verify_project(path, Some(harness), false, Some("terse".to_string())).await } pub async fn handle_explain_failure(&self, raw_output: String) -> Result { use crate::parser::KaniOutputParser; - + let parser = KaniOutputParser::new(&raw_output); let failed_checks = parser.parse_failed_checks(); let harnesses = parser.parse_harnesses(); let counterexamples = parser.parse_counterexamples(); let code_context = parser.extract_code_context(); - + let detailed_explanation = parser.generate_detailed_explanation(); Ok(ToolResult { @@ -434,7 +427,7 @@ Remember: Generated harness templates are EXAMPLES ONLY and won't work without c /// - Match the actual function signature and parameter types /// - Properly construct symbolic inputs for complex types /// - Add appropriate property assertions - /// + /// /// For automatic harness generation, consider using Kani's built-in auto-harness feature: /// `cargo kani --enable-unstable --function ` pub async fn handle_generate_harness( @@ -443,7 +436,7 @@ Remember: Generated harness templates are EXAMPLES ONLY and won't work without c properties: Vec, ) -> Result { let harness_code = format!( -r#"// ⚠️ WARNING: This is an EXAMPLE TEMPLATE that requires customization! + r#"// ⚠️ WARNING: This is an EXAMPLE TEMPLATE that requires customization! // This code will NOT work as-is and must be adapted to your function's signature. // // For automatic harness generation, use Kani's auto-harness feature: @@ -476,7 +469,8 @@ mod verification {{ function_name, function_name.replace("::", "_"), function_name, - properties.iter() + properties + .iter() .map(|prop| format!(" // Property: {}", prop)) .collect::>() .join("\n") @@ -504,4 +498,4 @@ mod verification {{ error: None, }) } -} \ No newline at end of file +} diff --git a/kani-mcp-server/src/parser.rs b/kani-mcp-server/src/parser.rs index 89871aec0a0..a9a78aad49c 100644 --- a/kani-mcp-server/src/parser.rs +++ b/kani-mcp-server/src/parser.rs @@ -31,7 +31,8 @@ impl<'a> KaniOutputParser<'a> { "FAILED" } else { "UNKNOWN" - }.to_string(); + } + .to_string(); harnesses.push(HarnessResult { name, @@ -49,7 +50,7 @@ impl<'a> KaniOutputParser<'a> { /// Parse failed checks from output with detailed information pub fn parse_failed_checks(&self) -> Vec { let mut failed_checks = Vec::new(); - + for line in self.output.lines() { if line.contains("Check ") && line.contains(":") { let check_info = self.parse_single_check(line); @@ -73,7 +74,10 @@ impl<'a> KaniOutputParser<'a> { } if let Some(check) = self.parse_failed_check_line(line) { - if !failed_checks.iter().any(|c| c.description == check.description && c.line == check.line) { + if !failed_checks + .iter() + .any(|c| c.description == check.description && c.line == check.line) + { failed_checks.push(check); } } @@ -85,13 +89,12 @@ impl<'a> KaniOutputParser<'a> { /// Parse a single check result line fn parse_single_check(&self, line: &str) -> Option { - let check_num = line.split("Check").nth(1)?.split(':').next()?.trim(); - + // Look for the next few lines to get details let lines: Vec<&str> = self.output.lines().collect(); let current_idx = lines.iter().position(|l| *l == line)?; - + let mut description = String::new(); let mut file = String::new(); let mut line_num = None; @@ -101,23 +104,24 @@ impl<'a> KaniOutputParser<'a> { // Parse the next few lines for details for i in (current_idx + 1)..(current_idx + 5).min(lines.len()) { let detail_line = lines[i]; - + if detail_line.contains("- Status: FAILURE") { is_failure = true; } - + if detail_line.contains("- Description:") { - description = detail_line.split("- Description:") + description = detail_line + .split("- Description:") .nth(1)? .trim() .trim_matches('"') .to_string(); } - + if detail_line.contains("- Location:") { let location = detail_line.split("- Location:").nth(1)?.trim(); let parts: Vec<&str> = location.split(" in function ").collect(); - + if let Some(file_part) = parts.first() { let file_line: Vec<&str> = file_part.split(':').collect(); file = file_line.first()?.trim_start_matches("./").to_string(); @@ -125,7 +129,7 @@ impl<'a> KaniOutputParser<'a> { line_num = ln.parse().ok(); } } - + if let Some(func_part) = parts.get(1) { function = func_part.trim().to_string(); } @@ -133,12 +137,7 @@ impl<'a> KaniOutputParser<'a> { } if is_failure { - Some(FailedCheck { - description, - file, - line: line_num, - function, - }) + Some(FailedCheck { description, file, line: line_num, function }) } else { None } @@ -147,31 +146,24 @@ impl<'a> KaniOutputParser<'a> { /// Parse a line from the "Failed Checks:" section fn parse_failed_check_line(&self, line: &str) -> Option { let description = line.split("File:").next()?.trim().to_string(); - + if let Some(file_part) = line.split("File:").nth(1) { let parts: Vec<&str> = file_part.split(',').collect(); - - let file = parts.first()? - .trim() - .trim_matches('"') - .trim_start_matches("./") - .to_string(); - - let line_num = parts.get(1) + + let file = parts.first()?.trim().trim_matches('"').trim_start_matches("./").to_string(); + + let line_num = parts + .get(1) .and_then(|s| s.split_whitespace().nth(1)) .and_then(|s| s.parse::().ok()); - - let function = parts.get(2) + + let function = parts + .get(2) .and_then(|s| s.split("in").nth(1)) .map(|s| s.trim().to_string()) .unwrap_or_else(|| "unknown".to_string()); - return Some(FailedCheck { - description, - file, - line: line_num, - function, - }); + return Some(FailedCheck { description, file, line: line_num, function }); } None @@ -182,10 +174,7 @@ impl<'a> KaniOutputParser<'a> { for line in self.output.lines() { if line.contains("Verification Time:") { if let Some(time_str) = line.split(':').nth(1) { - return time_str.trim() - .trim_end_matches('s') - .parse::() - .ok(); + return time_str.trim().trim_end_matches('s').parse::().ok(); } } } @@ -195,17 +184,19 @@ impl<'a> KaniOutputParser<'a> { /// Extract counterexamples from output pub fn parse_counterexamples(&self) -> Vec { let mut counterexamples = Vec::new(); - + for line in self.output.lines() { if line.contains("SAT checker: instance is SATISFIABLE") { - counterexamples.push("Counterexample found (inputs exist that violate the property)".to_string()); + counterexamples.push( + "Counterexample found (inputs exist that violate the property)".to_string(), + ); } - + if line.contains("Violated property:") || line.contains("Counterexample:") { counterexamples.push(line.trim().to_string()); } } - + counterexamples } @@ -227,7 +218,7 @@ impl<'a> KaniOutputParser<'a> { let verification_time = self.parse_verification_time(); let mut explanation = String::new(); - + explanation.push_str("DETAILED KANI VERIFICATION FAILURE ANALYSIS\n"); explanation.push_str("═══════════════════════════════════════════════\n\n"); @@ -243,11 +234,12 @@ impl<'a> KaniOutputParser<'a> { // Failed checks detail if !failed_checks.is_empty() { explanation.push_str("FAILED CHECKS:\n\n"); - + for (i, check) in failed_checks.iter().enumerate() { explanation.push_str(&format!("{}. {}\n", i + 1, check.description)); - explanation.push_str(&format!(" Location: {}:{}\n", - check.file, + explanation.push_str(&format!( + " Location: {}:{}\n", + check.file, check.line.map(|l| l.to_string()).unwrap_or_else(|| "?".to_string()) )); explanation.push_str(&format!(" Function: {}\n", check.function)); @@ -268,9 +260,12 @@ impl<'a> KaniOutputParser<'a> { explanation.push_str("ROOT CAUSE ANALYSIS:\n\n"); if !failed_checks.is_empty() { let first_check = &failed_checks[0]; - - explanation.push_str(&format!("The assertion '{}' failed, which indicates:\n", first_check.description)); - + + explanation.push_str(&format!( + "The assertion '{}' failed, which indicates:\n", + first_check.description + )); + // Pattern-based analysis if first_check.description.contains("overflow") { explanation.push_str(" • An arithmetic overflow occurred\n"); @@ -285,12 +280,15 @@ impl<'a> KaniOutputParser<'a> { } else if first_check.description.contains("dereference") { explanation.push_str(" • An invalid pointer dereference occurred\n"); explanation.push_str(" • Accessing memory that shouldn't be accessed\n"); - } else if first_check.description.contains("index") || first_check.description.contains("bounds") { + } else if first_check.description.contains("index") + || first_check.description.contains("bounds") + { explanation.push_str(" • An array/slice index is out of bounds\n"); explanation.push_str(" • Accessing beyond the valid range of the collection\n"); } else { explanation.push_str(" • A safety or correctness property was violated\n"); - explanation.push_str(" • The code doesn't handle all possible input cases correctly\n"); + explanation + .push_str(" • The code doesn't handle all possible input cases correctly\n"); } explanation.push_str("\n"); } @@ -299,7 +297,7 @@ impl<'a> KaniOutputParser<'a> { explanation.push_str("SUGGESTED FIXES:\n\n"); if !failed_checks.is_empty() { let first_check = &failed_checks[0]; - + if first_check.description.contains("overflow") { explanation.push_str(" 1. Use checked arithmetic operations:\n"); explanation.push_str(" • Replace `a + b` with `a.checked_add(b)`\n"); @@ -308,17 +306,23 @@ impl<'a> KaniOutputParser<'a> { explanation.push_str(" • Replace with `a.saturating_add(b)`\n"); explanation.push_str(" 3. Add input validation:\n"); explanation.push_str(" • Use `kani::assume()` to constrain inputs\n"); - } else if first_check.description.contains("dereference") || first_check.description.contains("null") { + } else if first_check.description.contains("dereference") + || first_check.description.contains("null") + { explanation.push_str(" 1. Add null pointer checks:\n"); explanation.push_str(" • Check `if ptr.is_null()` before dereferencing\n"); explanation.push_str(" 2. Use safe Rust alternatives:\n"); - explanation.push_str(" • Consider using `Option<&T>` instead of raw pointers\n"); - } else if first_check.description.contains("index") || first_check.description.contains("bounds") { + explanation + .push_str(" • Consider using `Option<&T>` instead of raw pointers\n"); + } else if first_check.description.contains("index") + || first_check.description.contains("bounds") + { explanation.push_str(" 1. Add bounds checking:\n"); explanation.push_str(" • Use `.get()` instead of direct indexing\n"); explanation.push_str(" • Check `index < array.len()` before access\n"); explanation.push_str(" 2. Use iterators:\n"); - explanation.push_str(" • Consider using `.iter()` instead of manual indexing\n"); + explanation + .push_str(" • Consider using `.iter()` instead of manual indexing\n"); } else { explanation.push_str(" 1. Review the assertion condition:\n"); explanation.push_str(" • Ensure it correctly captures the intended property\n"); @@ -340,4 +344,4 @@ impl<'a> KaniOutputParser<'a> { explanation } -} \ No newline at end of file +} diff --git a/kani-mcp-server/src/tools.rs b/kani-mcp-server/src/tools.rs index aeb2ad9425d..3bec8257728 100644 --- a/kani-mcp-server/src/tools.rs +++ b/kani-mcp-server/src/tools.rs @@ -1,5 +1,5 @@ use serde::{Deserialize, Serialize}; -use serde_json::{json, Value}; +use serde_json::{Value, json}; /// Definition of an MCP tool #[derive(Debug, Clone, Serialize, Deserialize)] @@ -101,4 +101,4 @@ pub struct ToolResult { pub success: bool, pub data: Value, pub error: Option, -} \ No newline at end of file +} From 63eb8eae8627d0f905c25bb2b9b69186aef42714 Mon Sep 17 00:00:00 2001 From: ConnorJKY Date: Fri, 21 Nov 2025 11:23:40 -0800 Subject: [PATCH 10/11] Fix clippy error --- kani-mcp-server/src/kani_wrapper.rs | 2 +- kani-mcp-server/src/mcp_server.rs | 10 ++-- kani-mcp-server/src/parser.rs | 72 +++++++++++++---------------- 3 files changed, 38 insertions(+), 46 deletions(-) diff --git a/kani-mcp-server/src/kani_wrapper.rs b/kani-mcp-server/src/kani_wrapper.rs index 620fd70f7ca..83615c17074 100644 --- a/kani-mcp-server/src/kani_wrapper.rs +++ b/kani-mcp-server/src/kani_wrapper.rs @@ -80,7 +80,7 @@ impl KaniWrapper { } fn setup_cargo_command() -> Result { - let mut cmd = Command::new("cargo"); + let cmd = Command::new("cargo"); Ok(cmd) } diff --git a/kani-mcp-server/src/mcp_server.rs b/kani-mcp-server/src/mcp_server.rs index db415e51f0f..adae8a3651f 100644 --- a/kani-mcp-server/src/mcp_server.rs +++ b/kani-mcp-server/src/mcp_server.rs @@ -33,10 +33,10 @@ impl KaniMcpServer { Ok(request) => { let response = self.handle_mcp_request(request).await; - if !response.is_null() { - if let Ok(response_str) = serde_json::to_string(&response) { - println!("{}", response_str); - } + if !response.is_null() + && let Ok(response_str) = serde_json::to_string(&response) + { + println!("{}", response_str); } } Err(_e) => { @@ -277,7 +277,7 @@ impl KaniMcpServer { let properties = arguments["properties"] .as_array() .map(|arr| arr.iter().filter_map(|v| v.as_str().map(String::from)).collect()) - .unwrap_or_else(Vec::new); + .unwrap_or_default(); match self.handle_generate_harness(function_name, properties).await { Ok(result) => { diff --git a/kani-mcp-server/src/parser.rs b/kani-mcp-server/src/parser.rs index a9a78aad49c..6771fb2c2d0 100644 --- a/kani-mcp-server/src/parser.rs +++ b/kani-mcp-server/src/parser.rs @@ -16,31 +16,26 @@ impl<'a> KaniOutputParser<'a> { let mut current_harness: Option = None; for line in self.output.lines() { - if line.contains("Checking harness") { - if let Some(name_part) = line.split("Checking harness").nth(1) { - current_harness = Some(name_part.trim().trim_end_matches("...").to_string()); - } + if line.contains("Checking harness") + && let Some(name_part) = line.split("Checking harness").nth(1) + { + current_harness = Some(name_part.trim().trim_end_matches("...").to_string()); } // Detect harness completion - if line.contains("VERIFICATION") { - if let Some(name) = current_harness.take() { - let status = if line.contains("SUCCESSFUL") { - "SUCCESS" - } else if line.contains("FAILED") { - "FAILED" - } else { - "UNKNOWN" - } - .to_string(); - - harnesses.push(HarnessResult { - name, - status, - checks_passed: 0, - checks_failed: 0, - }); + if line.contains("VERIFICATION") + && let Some(name) = current_harness.take() + { + let status = if line.contains("SUCCESSFUL") { + "SUCCESS" + } else if line.contains("FAILED") { + "FAILED" + } else { + "UNKNOWN" } + .to_string(); + + harnesses.push(HarnessResult { name, status, checks_passed: 0, checks_failed: 0 }); } } @@ -73,13 +68,12 @@ impl<'a> KaniOutputParser<'a> { break; } - if let Some(check) = self.parse_failed_check_line(line) { - if !failed_checks + if let Some(check) = self.parse_failed_check_line(line) + && !failed_checks .iter() .any(|c| c.description == check.description && c.line == check.line) - { - failed_checks.push(check); - } + { + failed_checks.push(check); } } } @@ -89,7 +83,7 @@ impl<'a> KaniOutputParser<'a> { /// Parse a single check result line fn parse_single_check(&self, line: &str) -> Option { - let check_num = line.split("Check").nth(1)?.split(':').next()?.trim(); + let _check_num = line.split("Check").nth(1)?.split(':').next()?.trim(); // Look for the next few lines to get details let lines: Vec<&str> = self.output.lines().collect(); @@ -102,9 +96,7 @@ impl<'a> KaniOutputParser<'a> { let mut is_failure = false; // Parse the next few lines for details - for i in (current_idx + 1)..(current_idx + 5).min(lines.len()) { - let detail_line = lines[i]; - + for detail_line in lines.iter().skip(current_idx + 1).take(4) { if detail_line.contains("- Status: FAILURE") { is_failure = true; } @@ -172,10 +164,10 @@ impl<'a> KaniOutputParser<'a> { /// Parse verification time from output pub fn parse_verification_time(&self) -> Option { for line in self.output.lines() { - if line.contains("Verification Time:") { - if let Some(time_str) = line.split(':').nth(1) { - return time_str.trim().trim_end_matches('s').parse::().ok(); - } + if line.contains("Verification Time:") + && let Some(time_str) = line.split(':').nth(1) + { + return time_str.trim().trim_end_matches('s').parse::().ok(); } } None @@ -223,13 +215,13 @@ impl<'a> KaniOutputParser<'a> { explanation.push_str("═══════════════════════════════════════════════\n\n"); // Summary - explanation.push_str(&format!("Summary:\n")); + explanation.push_str("Summary:\n"); explanation.push_str(&format!(" • Total harnesses: {}\n", harnesses.len())); explanation.push_str(&format!(" • Failed checks: {}\n", failed_checks.len())); if let Some(time) = verification_time { explanation.push_str(&format!(" • Verification time: {:.3}s\n", time)); } - explanation.push_str("\n"); + explanation.push('\n'); // Failed checks detail if !failed_checks.is_empty() { @@ -243,7 +235,7 @@ impl<'a> KaniOutputParser<'a> { check.line.map(|l| l.to_string()).unwrap_or_else(|| "?".to_string()) )); explanation.push_str(&format!(" Function: {}\n", check.function)); - explanation.push_str("\n"); + explanation.push('\n'); } } @@ -253,7 +245,7 @@ impl<'a> KaniOutputParser<'a> { for ce in counterexamples { explanation.push_str(&format!(" • {}\n", ce)); } - explanation.push_str("\n"); + explanation.push('\n'); } // Root cause analysis @@ -290,7 +282,7 @@ impl<'a> KaniOutputParser<'a> { explanation .push_str(" • The code doesn't handle all possible input cases correctly\n"); } - explanation.push_str("\n"); + explanation.push('\n'); } // Suggested fixes @@ -331,7 +323,7 @@ impl<'a> KaniOutputParser<'a> { explanation.push_str(" 3. Fix the underlying logic:\n"); explanation.push_str(" • Adjust the code to handle all cases correctly\n"); } - explanation.push_str("\n"); + explanation.push('\n'); } // Next steps From 402ebc7a72c5720001e57db882b6dda2e0967124 Mon Sep 17 00:00:00 2001 From: ConnorJKY Date: Mon, 24 Nov 2025 13:31:58 -0800 Subject: [PATCH 11/11] Fix copyright checks --- kani-mcp-server/Cargo.toml | 3 +++ kani-mcp-server/src/kani_wrapper.rs | 3 +++ kani-mcp-server/src/main.rs | 3 +++ kani-mcp-server/src/mcp_server.rs | 3 +++ kani-mcp-server/src/parser.rs | 3 +++ kani-mcp-server/src/tools.rs | 3 +++ 6 files changed, 18 insertions(+) diff --git a/kani-mcp-server/Cargo.toml b/kani-mcp-server/Cargo.toml index e1b857e30b2..e9c25c0c527 100644 --- a/kani-mcp-server/Cargo.toml +++ b/kani-mcp-server/Cargo.toml @@ -1,3 +1,6 @@ +# Copyright Kani Contributors +# SPDX-License-Identifier: Apache-2.0 OR MIT + [package] name = "kani-mcp-server" version = "0.1.0" diff --git a/kani-mcp-server/src/kani_wrapper.rs b/kani-mcp-server/src/kani_wrapper.rs index 83615c17074..0c8697904cd 100644 --- a/kani-mcp-server/src/kani_wrapper.rs +++ b/kani-mcp-server/src/kani_wrapper.rs @@ -1,3 +1,6 @@ +// Copyright Kani Contributors +// SPDX-License-Identifier: Apache-2.0 OR MIT + use anyhow::{Context, Result}; use serde::{Deserialize, Serialize}; use std::path::PathBuf; diff --git a/kani-mcp-server/src/main.rs b/kani-mcp-server/src/main.rs index 4f26607b529..da70aa055aa 100644 --- a/kani-mcp-server/src/main.rs +++ b/kani-mcp-server/src/main.rs @@ -1,3 +1,6 @@ +// Copyright Kani Contributors +// SPDX-License-Identifier: Apache-2.0 OR MIT + mod kani_wrapper; mod mcp_server; mod parser; diff --git a/kani-mcp-server/src/mcp_server.rs b/kani-mcp-server/src/mcp_server.rs index adae8a3651f..1feadf897fd 100644 --- a/kani-mcp-server/src/mcp_server.rs +++ b/kani-mcp-server/src/mcp_server.rs @@ -1,3 +1,6 @@ +// Copyright Kani Contributors +// SPDX-License-Identifier: Apache-2.0 OR MIT + use crate::kani_wrapper::{KaniOptions, KaniWrapper, VerificationResult}; use crate::tools::{ToolResult, get_kani_tools}; use anyhow::Result; diff --git a/kani-mcp-server/src/parser.rs b/kani-mcp-server/src/parser.rs index 6771fb2c2d0..150926af55b 100644 --- a/kani-mcp-server/src/parser.rs +++ b/kani-mcp-server/src/parser.rs @@ -1,3 +1,6 @@ +// Copyright Kani Contributors +// SPDX-License-Identifier: Apache-2.0 OR MIT + use crate::kani_wrapper::{FailedCheck, HarnessResult}; /// Parser for Kani output format diff --git a/kani-mcp-server/src/tools.rs b/kani-mcp-server/src/tools.rs index 3bec8257728..f8337e17164 100644 --- a/kani-mcp-server/src/tools.rs +++ b/kani-mcp-server/src/tools.rs @@ -1,3 +1,6 @@ +// Copyright Kani Contributors +// SPDX-License-Identifier: Apache-2.0 OR MIT + use serde::{Deserialize, Serialize}; use serde_json::{Value, json};