use anyhow::Result;
use async_trait::async_trait;
use serde_json::{json, Value};
use std::sync::Arc;
use tokio::sync::Mutex;
use crate::mcp::types::VibeToolHandler;
use crate::workspace::WorkspaceManager;
pub struct ValidateMcpInterfaceTool;
#[async_trait]
impl VibeToolHandler for ValidateMcpInterfaceTool {
fn tool_name(&self) -> &str {
"validate_mcp_interface"
}
fn tool_description(&self) -> &str {
"Tests all MCP tools for consistency with CLI interface"
}
fn input_schema(&self) -> Value {
json!({
"type": "object",
"properties": {
"verbose": {
"type": "boolean",
"description": "Show detailed validation output",
"default": false
}
},
"required": []
})
}
async fn handle_call(
&self,
args: Value,
_workspace: Arc<Mutex<WorkspaceManager>>,
) -> Result<Value> {
let verbose = args
.get("verbose")
.and_then(|v| v.as_bool())
.unwrap_or(false);
let tool_mappings = vec![
("init_workspace", "vibe init"),
("show_config", "vibe config show"),
("init_config", "vibe config init"),
("validate_config", "vibe config validate"),
("reset_config", "vibe config reset"),
("backup_config", "vibe config backup"),
("restore_config", "vibe config restore"),
("configure_app", "vibe apps configure"),
("show_apps", "vibe apps show"),
("list_app_templates", "vibe apps template list"),
("create_app_template", "vibe apps template create"),
("delete_app_template", "vibe apps template delete"),
(
"update_default_templates",
"vibe apps template update-defaults",
),
("launch_repo", "vibe launch"),
("open_repo", "vibe open"),
("clone", "vibe clone"),
("vibe_git_status", "vibe git status"),
("scan_repos", "vibe git scan"),
("sync_repos", "vibe git sync"),
("clone_repo", "vibe git clone"),
("exec_git_command", "vibe git exec"),
("reset_git_config", "vibe git reset"),
];
let mut validation_results = Vec::new();
let mut all_valid = true;
use crate::mcp::handlers;
use crate::mcp::registry::ToolRegistryBuilder;
let registry = ToolRegistryBuilder::new()
.with_tool(Arc::new(handlers::InitWorkspaceTool))
.with_tool(Arc::new(handlers::ShowConfigTool))
.with_tool(Arc::new(handlers::InitConfigTool))
.with_tool(Arc::new(handlers::ValidateConfigTool))
.with_tool(Arc::new(handlers::ResetConfigTool))
.with_tool(Arc::new(handlers::BackupConfigTool))
.with_tool(Arc::new(handlers::RestoreConfigTool))
.with_tool(Arc::new(handlers::ConfigureAppTool))
.with_tool(Arc::new(handlers::ShowAppsTool))
.with_tool(Arc::new(handlers::ListAppTemplatesTool))
.with_tool(Arc::new(handlers::CreateAppTemplateTool))
.with_tool(Arc::new(handlers::DeleteAppTemplateTool))
.with_tool(Arc::new(handlers::UpdateDefaultTemplatesTool))
.with_tool(Arc::new(handlers::LaunchRepoTool))
.with_tool(Arc::new(handlers::OpenRepoTool))
.with_tool(Arc::new(handlers::CloneTool))
.with_tool(Arc::new(handlers::GitStatusTool))
.with_tool(Arc::new(handlers::ScanReposTool))
.with_tool(Arc::new(handlers::SyncReposTool))
.with_tool(Arc::new(handlers::CloneRepoTool))
.with_tool(Arc::new(handlers::ExecGitCommandTool))
.with_tool(Arc::new(handlers::ResetGitConfigTool))
.build();
let available_tools = registry.list_tools();
let tool_names: Vec<String> = available_tools
.iter()
.map(|(name, _, _)| name.clone())
.collect();
for (mcp_tool, cli_command) in &tool_mappings {
let exists = tool_names.contains(&mcp_tool.to_string());
if !exists {
all_valid = false;
}
let result = json!({
"mcp_tool": mcp_tool,
"cli_command": cli_command,
"exists": exists,
"status": if exists { "✓" } else { "✗" }
});
validation_results.push(result);
}
let mapped_tools: Vec<&str> = tool_mappings.iter().map(|(tool, _)| *tool).collect();
let unmapped_tools: Vec<String> = tool_names
.into_iter()
.filter(|name| !mapped_tools.contains(&name.as_str()))
.collect();
let total_expected = tool_mappings.len();
let total_found = validation_results
.iter()
.filter(|r| r["exists"].as_bool().unwrap_or(false))
.count();
let total_missing = total_expected - total_found;
let response = json!({
"valid": all_valid,
"summary": {
"total_expected": total_expected,
"total_found": total_found,
"total_missing": total_missing,
"unmapped_tools": unmapped_tools,
},
"results": if verbose { Value::Array(validation_results) } else { Value::Null }
});
Ok(response)
}
}