143 lines
4.2 KiB
Rust
143 lines
4.2 KiB
Rust
#!/usr/bin/env -S cargo run --
|
||
//! Simple Rust-native MCP Server for Provisioning
|
||
//!
|
||
//! A minimal working implementation that shows Rust feasibility
|
||
|
||
use anyhow::Result;
|
||
use clap::Parser;
|
||
use std::path::PathBuf;
|
||
use tracing::{info, error, debug};
|
||
use serde_json::json;
|
||
|
||
mod config;
|
||
mod provisioning;
|
||
mod tools;
|
||
mod errors;
|
||
|
||
use config::Config;
|
||
use provisioning::ProvisioningEngine;
|
||
use tools::ProvisioningTools;
|
||
|
||
#[derive(Parser, Debug)]
|
||
#[command(name = "provisioning-mcp-server")]
|
||
#[command(about = "Rust-native MCP server for Cloud Native Provisioning")]
|
||
#[command(version)]
|
||
struct Args {
|
||
/// Configuration file path
|
||
#[arg(short, long, env = "PROVISIONING_MCP_CONFIG")]
|
||
config: Option<PathBuf>,
|
||
|
||
/// Provisioning system path
|
||
#[arg(short, long, env = "PROVISIONING_PATH")]
|
||
provisioning_path: Option<PathBuf>,
|
||
|
||
/// Debug mode
|
||
#[arg(short, long, env = "PROVISIONING_DEBUG")]
|
||
debug: bool,
|
||
}
|
||
|
||
#[tokio::main]
|
||
async fn main() -> Result<()> {
|
||
let args = Args::parse();
|
||
|
||
// Initialize tracing
|
||
tracing_subscriber::fmt()
|
||
.with_max_level(if args.debug {
|
||
tracing::Level::DEBUG
|
||
} else {
|
||
tracing::Level::INFO
|
||
})
|
||
.init();
|
||
|
||
info!("🦀 Starting Rust-native MCP Server for Provisioning");
|
||
|
||
// Load configuration
|
||
let config = Config::load(
|
||
args.config,
|
||
args.provisioning_path,
|
||
args.debug,
|
||
)?;
|
||
|
||
info!("Configuration loaded successfully");
|
||
info!("Provisioning path: {}", config.provisioning_path.display());
|
||
info!("AI enabled: {}", config.is_ai_available());
|
||
|
||
// Initialize components
|
||
let engine = ProvisioningEngine::new(&config)?;
|
||
let tools = ProvisioningTools::new(&config);
|
||
|
||
info!("🚀 MCP Server components initialized");
|
||
|
||
// Run basic tests to verify functionality
|
||
test_components(&engine, &tools).await?;
|
||
|
||
// Run performance tests
|
||
info!("⚡ Running performance benchmarks...");
|
||
let performance_results = provisioning_mcp_server::performance_test::run_performance_tests();
|
||
println!("\n{}", performance_results);
|
||
|
||
info!("✅ Rust MCP Server validation complete");
|
||
Ok(())
|
||
}
|
||
|
||
async fn test_components(engine: &ProvisioningEngine, tools: &ProvisioningTools) -> Result<()> {
|
||
info!("🧪 Testing server components...");
|
||
|
||
// Test configuration parsing
|
||
let test_description = "Create 2 servers with 4 CPU cores for kubernetes cluster on AWS";
|
||
match tools.parse_server_description(test_description) {
|
||
Ok(server_json) => {
|
||
info!("✅ Server parsing test passed");
|
||
info!(" Parsed: {} x {} servers for {}",
|
||
server_json.get("count").and_then(|v| v.as_u64()).unwrap_or(1),
|
||
server_json.get("instance_type").and_then(|v| v.as_str()).unwrap_or("unknown"),
|
||
server_json.get("purpose").and_then(|v| v.as_str()).unwrap_or("general"));
|
||
}
|
||
Err(e) => {
|
||
error!("❌ Server parsing test failed: {}", e);
|
||
}
|
||
}
|
||
|
||
// Test AI status
|
||
let ai_status = tools.get_ai_status()?;
|
||
info!("🤖 AI Status:\n{}", ai_status);
|
||
|
||
// Test basic infrastructure status
|
||
match engine.get_status(None, false) {
|
||
Ok(status) => {
|
||
info!("✅ Infrastructure status test passed");
|
||
debug!("Status: {}", status);
|
||
}
|
||
Err(e) => {
|
||
info!("ℹ️ Infrastructure status (expected if no infrastructure exists): {}", e);
|
||
}
|
||
}
|
||
|
||
Ok(())
|
||
}
|
||
|
||
#[cfg(test)]
|
||
mod tests {
|
||
use super::*;
|
||
|
||
#[tokio::test]
|
||
async fn test_server_creation() {
|
||
let config = Config::default();
|
||
let engine = ProvisioningEngine::new(&config).expect("Failed to create engine");
|
||
let tools = ProvisioningTools::new(&config);
|
||
|
||
// Test parsing
|
||
let result = tools.parse_server_description("Create 1 server for web hosting");
|
||
assert!(result.is_ok());
|
||
|
||
let server_config = result.unwrap();
|
||
assert_eq!(server_config.count, 1);
|
||
}
|
||
|
||
#[test]
|
||
fn test_config_loading() {
|
||
let config = Config::default();
|
||
assert!(!config.debug);
|
||
assert!(config.provisioning_path.exists() || !config.provisioning_path.to_string_lossy().contains("/usr/local/provisioning"));
|
||
}
|
||
} |