// Enhanced MCP Tools for Systems Provisioning // Integrates with new API server, AI agents, and dashboard capabilities use anyhow::Result; use serde_json::{json, Value}; use std::process::Command; use reqwest::Client; pub struct ProvisioningTools { client: Client, api_base_url: String, } impl ProvisioningTools { pub fn new(api_base_url: Option) -> Self { Self { client: Client::new(), api_base_url: api_base_url.unwrap_or_else(|| "http://localhost:3000".to_string()), } } /// Execute provisioning command with enhanced capabilities pub async fn execute_provisioning_command(&self, args: &[&str]) -> Result { let output = Command::new("./core/nulib/provisioning") .args(args) .output() .map_err(|e| anyhow::anyhow!("Failed to execute command: {}", e))?; let stdout = String::from_utf8_lossy(&output.stdout); let stderr = String::from_utf8_lossy(&output.stderr); if output.status.success() { Ok(json!({ "success": true, "stdout": stdout, "stderr": stderr, "exit_code": 0 })) } else { Ok(json!({ "success": false, "stdout": stdout, "stderr": stderr, "exit_code": output.status.code().unwrap_or(-1) })) } } /// Query infrastructure using AI-powered natural language pub async fn ai_query(&self, query: &str, context: Option<&str>) -> Result { let mut args = vec!["ai", "query", "--prompt", query]; if let Some(ctx) = context { args.extend(&["--context", ctx]); } let output = Command::new("./core/nulib/provisioning") .args(&args) .output() .map_err(|e| ToolError::ExecutionError(format!("AI query failed: {}", e)))?; let result = String::from_utf8_lossy(&output.stdout); // Try to parse as JSON, fallback to plain text if let Ok(parsed) = serde_json::from_str::(&result) { Ok(parsed) } else { Ok(json!({ "query": query, "response": result.trim(), "type": "natural_language_response" })) } } /// Get infrastructure status via API pub async fn get_infrastructure_status(&self) -> Result { let url = format!("{}/api/v1/query?target=infrastructure", self.api_base_url); match self.client.get(&url).send().await { Ok(response) => { if response.status().is_success() { let data = response.json::().await .map_err(|e| ToolError::ExecutionError(format!("Failed to parse response: {}", e)))?; Ok(data) } else { // Fallback to CLI command self.execute_provisioning_command(&["show", "infrastructure"]).await } } Err(_) => { // Fallback to CLI command self.execute_provisioning_command(&["show", "infrastructure"]).await } } } /// Get system metrics via API pub async fn get_system_metrics(&self, timerange: Option<&str>) -> Result { let timerange = timerange.unwrap_or("1h"); let url = format!("{}/api/v1/metrics?timerange={}", self.api_base_url, timerange); match self.client.get(&url).send().await { Ok(response) => { if response.status().is_success() { let data = response.json::().await .map_err(|e| ToolError::ExecutionError(format!("Failed to parse metrics: {}", e)))?; Ok(data) } else { // Fallback to CLI command self.execute_provisioning_command(&["query", "metrics", "--since", timerange]).await } } Err(_) => { // Fallback to CLI command self.execute_provisioning_command(&["query", "metrics", "--since", timerange]).await } } } /// Get logs with filtering via API pub async fn get_logs(&self, level: Option<&str>, since: Option<&str>) -> Result { let level = level.unwrap_or("info"); let since = since.unwrap_or("1h"); let url = format!("{}/api/v1/logs?level={}&since={}", self.api_base_url, level, since); match self.client.get(&url).send().await { Ok(response) => { if response.status().is_success() { let data = response.json::().await .map_err(|e| ToolError::ExecutionError(format!("Failed to parse logs: {}", e)))?; Ok(data) } else { // Fallback to CLI command self.execute_provisioning_command(&["logs", "--level", level, "--since", since]).await } } Err(_) => { // Fallback to CLI command self.execute_provisioning_command(&["logs", "--level", level, "--since", since]).await } } } /// Start API server pub async fn start_api_server(&self, port: Option) -> Result { let port = port.unwrap_or(3000); let port_str = port.to_string(); self.execute_provisioning_command(&["api", "start", "--port", &port_str, "--background"]).await } /// Get API server status pub async fn get_api_status(&self) -> Result { let url = format!("{}/health", self.api_base_url); match self.client.get(&url).send().await { Ok(response) => { let status = response.status(); let data = response.json::().await .unwrap_or(json!({"status": "unknown"})); Ok(json!({ "api_available": status.is_success(), "status_code": status.as_u16(), "data": data })) } Err(e) => { Ok(json!({ "api_available": false, "error": e.to_string() })) } } } /// Create and start dashboard pub async fn create_dashboard(&self, template: Option<&str>, name: Option<&str>) -> Result { let template = template.unwrap_or("full"); let name = name.unwrap_or("ai-dashboard"); self.execute_provisioning_command(&["dashboard", "create", template, name]).await } /// Start existing dashboard pub async fn start_dashboard(&self, name: &str, port: Option) -> Result { let port = port.unwrap_or(8080); let port_str = port.to_string(); self.execute_provisioning_command(&["dashboard", "start", name, &port_str]).await } /// Start AI agents pub async fn start_ai_agents(&self, agents: Option>) -> Result { let mut args = vec!["agents", "start"]; if let Some(agent_list) = agents { args.push("--agents"); args.push(&format!("[{}]", agent_list.join(", "))); } self.execute_provisioning_command(&args).await } /// Get AI agents status pub async fn get_agents_status(&self) -> Result { self.execute_provisioning_command(&["agents", "status"]).await } /// Create servers with configuration pub async fn create_servers(&self, config: &Value) -> Result { let template = config.get("template").and_then(|v| v.as_str()).unwrap_or("default"); let count = config.get("count").and_then(|v| v.as_u64()).unwrap_or(1); let provider = config.get("provider").and_then(|v| v.as_str()).unwrap_or("local"); let instance_type = config.get("instance_type").and_then(|v| v.as_str()); let mut args = vec![ "server", "create", "--template", template, "--count", &count.to_string(), "--provider", provider ]; if let Some(itype) = instance_type { args.extend(&["--instance-type", itype]); } self.execute_provisioning_command(&args).await } /// List servers pub async fn list_servers(&self, provider: Option<&str>) -> Result { let mut args = vec!["server", "list"]; if let Some(p) = provider { args.extend(&["--provider", p]); } self.execute_provisioning_command(&args).await } /// Delete servers pub async fn delete_servers(&self, server_names: &[&str]) -> Result { let mut args = vec!["server", "delete"]; args.extend(server_names); self.execute_provisioning_command(&args).await } /// Create Kubernetes cluster pub async fn create_cluster(&self, config: &Value) -> Result { let name = config.get("name").and_then(|v| v.as_str()).unwrap_or("k8s-cluster"); let nodes = config.get("nodes").and_then(|v| v.as_u64()).unwrap_or(3); let provider = config.get("provider").and_then(|v| v.as_str()).unwrap_or("local"); let args = vec![ "cluster", "create", "--name", name, "--nodes", &nodes.to_string(), "--provider", provider ]; self.execute_provisioning_command(&args).await } /// Generate infrastructure from natural language description pub async fn generate_infrastructure(&self, description: &str, output_type: Option<&str>) -> Result { let output_type = output_type.unwrap_or("server"); let args = vec![ "ai", "template", "--prompt", description, "--template-type", output_type ]; self.execute_provisioning_command(&args).await } /// Get cost optimization recommendations pub async fn get_cost_optimization(&self) -> Result { self.ai_query("How can I reduce infrastructure costs and optimize spending?", None).await } /// Get security analysis pub async fn get_security_analysis(&self) -> Result { self.ai_query("Perform a security analysis of current infrastructure and identify threats", None).await } /// Get performance analysis pub async fn get_performance_analysis(&self) -> Result { self.ai_query("Analyze system performance and identify bottlenecks", None).await } /// Predict infrastructure issues pub async fn predict_issues(&self, timeframe: Option<&str>) -> Result { let timeframe = timeframe.unwrap_or("next week"); let query = format!("Predict potential infrastructure issues for {}", timeframe); self.ai_query(&query, None).await } } // Tool definitions for MCP registration pub fn get_provisioning_tools() -> Vec { vec![ Tool { name: "execute_provisioning_command".to_string(), description: "Execute provisioning CLI commands with enhanced capabilities".to_string(), input_schema: json!({ "type": "object", "properties": { "args": { "type": "array", "items": {"type": "string"}, "description": "Command arguments to pass to provisioning CLI" } }, "required": ["args"] }) }, Tool { name: "ai_query".to_string(), description: "Query infrastructure using AI-powered natural language processing".to_string(), input_schema: json!({ "type": "object", "properties": { "query": { "type": "string", "description": "Natural language query about infrastructure" }, "context": { "type": "string", "description": "Additional context for the query (optional)" } }, "required": ["query"] }) }, Tool { name: "get_infrastructure_status".to_string(), description: "Get current infrastructure status via API or CLI".to_string(), input_schema: json!({ "type": "object", "properties": {} }) }, Tool { name: "get_system_metrics".to_string(), description: "Retrieve system metrics for specified time range".to_string(), input_schema: json!({ "type": "object", "properties": { "timerange": { "type": "string", "description": "Time range for metrics (e.g., '1h', '24h', '7d')", "default": "1h" } } }) }, Tool { name: "get_logs".to_string(), description: "Retrieve filtered logs from infrastructure".to_string(), input_schema: json!({ "type": "object", "properties": { "level": { "type": "string", "description": "Log level filter (debug, info, warn, error)", "default": "info" }, "since": { "type": "string", "description": "Time range for logs (e.g., '1h', '24h')", "default": "1h" } } }) }, Tool { name: "start_api_server".to_string(), description: "Start the provisioning API server".to_string(), input_schema: json!({ "type": "object", "properties": { "port": { "type": "integer", "description": "Port number for API server", "default": 3000 } } }) }, Tool { name: "get_api_status".to_string(), description: "Check API server availability and status".to_string(), input_schema: json!({ "type": "object", "properties": {} }) }, Tool { name: "create_dashboard".to_string(), description: "Create interactive dashboard using Marimo".to_string(), input_schema: json!({ "type": "object", "properties": { "template": { "type": "string", "description": "Dashboard template (monitoring, infrastructure, full, ai-insights)", "default": "full" }, "name": { "type": "string", "description": "Dashboard name", "default": "ai-dashboard" } } }) }, Tool { name: "start_dashboard".to_string(), description: "Start existing dashboard server".to_string(), input_schema: json!({ "type": "object", "properties": { "name": { "type": "string", "description": "Dashboard name to start" }, "port": { "type": "integer", "description": "Port number for dashboard", "default": 8080 } }, "required": ["name"] }) }, Tool { name: "start_ai_agents".to_string(), description: "Start AI agents for intelligent infrastructure monitoring".to_string(), input_schema: json!({ "type": "object", "properties": { "agents": { "type": "array", "items": {"type": "string"}, "description": "List of agents to start (pattern_detector, cost_optimizer, performance_analyzer, security_monitor, predictor, auto_healer)" } } }) }, Tool { name: "get_agents_status".to_string(), description: "Get status of all AI agents".to_string(), input_schema: json!({ "type": "object", "properties": {} }) }, Tool { name: "create_servers".to_string(), description: "Create servers with specified configuration".to_string(), input_schema: json!({ "type": "object", "properties": { "config": { "type": "object", "description": "Server configuration", "properties": { "template": {"type": "string", "default": "default"}, "count": {"type": "integer", "default": 1}, "provider": {"type": "string", "default": "local"}, "instance_type": {"type": "string"} } } }, "required": ["config"] }) }, Tool { name: "list_servers".to_string(), description: "List all servers, optionally filtered by provider".to_string(), input_schema: json!({ "type": "object", "properties": { "provider": { "type": "string", "description": "Filter by provider (aws, gcp, azure, local)" } } }) }, Tool { name: "delete_servers".to_string(), description: "Delete specified servers".to_string(), input_schema: json!({ "type": "object", "properties": { "server_names": { "type": "array", "items": {"type": "string"}, "description": "Names of servers to delete" } }, "required": ["server_names"] }) }, Tool { name: "create_cluster".to_string(), description: "Create Kubernetes cluster with specified configuration".to_string(), input_schema: json!({ "type": "object", "properties": { "config": { "type": "object", "description": "Cluster configuration", "properties": { "name": {"type": "string", "default": "k8s-cluster"}, "nodes": {"type": "integer", "default": 3}, "provider": {"type": "string", "default": "local"} } } }, "required": ["config"] }) }, Tool { name: "generate_infrastructure".to_string(), description: "Generate infrastructure configuration from natural language description".to_string(), input_schema: json!({ "type": "object", "properties": { "description": { "type": "string", "description": "Natural language description of desired infrastructure" }, "output_type": { "type": "string", "description": "Type of output (server, cluster, taskserv)", "default": "server" } }, "required": ["description"] }) }, Tool { name: "get_cost_optimization".to_string(), description: "Get AI-powered cost optimization recommendations".to_string(), input_schema: json!({ "type": "object", "properties": {} }) }, Tool { name: "get_security_analysis".to_string(), description: "Get comprehensive security analysis using AI agents".to_string(), input_schema: json!({ "type": "object", "properties": {} }) }, Tool { name: "get_performance_analysis".to_string(), description: "Get detailed performance analysis and bottleneck identification".to_string(), input_schema: json!({ "type": "object", "properties": {} }) }, Tool { name: "predict_issues".to_string(), description: "Predict potential infrastructure issues using AI".to_string(), input_schema: json!({ "type": "object", "properties": { "timeframe": { "type": "string", "description": "Prediction timeframe (e.g., 'next week', 'next month')", "default": "next week" } } }) } ] }