mcp-tools 0.1.0

Rust MCP tools library
Documentation
//! Unified MCP Tools Server Binary
//!
//! Standalone executable that combines all MCP servers into one
//! Provides Git, Code Analysis, Web, and System tools via MCP protocol

use clap::Parser;
use mcp_tools::{
    common::{McpServerBase, ServerConfig},
    servers::{CodeAnalysisServer, GitToolsServer, SystemToolsServer, WebToolsServer},
    Result,
};
use std::path::PathBuf;
use tokio::signal;
use tracing::{error, info, warn};

/// Unified MCP Tools Server
#[derive(Parser)]
#[command(name = "mcp-server")]
#[command(about = "Unified MCP Tools Server - All tools in one server")]
#[command(version = "1.0.0")]
struct Args {
    /// Server bind address
    #[arg(short, long, default_value = "127.0.0.1")]
    host: String,

    /// Server port
    #[arg(short, long, default_value = "8080")]
    port: u16,

    /// Server name
    #[arg(long, default_value = "mcp-tools-server")]
    name: String,

    /// Working directory
    #[arg(short, long)]
    working_dir: Option<PathBuf>,

    /// Enable verbose logging
    #[arg(short, long)]
    verbose: bool,

    /// Configuration file path
    #[arg(short, long)]
    config: Option<PathBuf>,

    /// Enable specific tool categories (comma-separated: git,code,web,system)
    #[arg(long, default_value = "git,code,web,system")]
    tools: String,

    /// Enable unsafe system commands (NOT RECOMMENDED)
    #[arg(long)]
    allow_unsafe: bool,
}

#[tokio::main]
async fn main() -> Result<()> {
    let args = Args::parse();

    // Initialize logging
    let log_level = if args.verbose { "debug" } else { "info" };
    tracing_subscriber::fmt().with_env_filter(log_level).init();

    info!("Starting Unified MCP Tools Server v1.0.0");
    info!("Server will bind to {}:{}", args.host, args.port);

    // Parse enabled tools
    let enabled_tools: Vec<&str> = args.tools.split(',').map(|s| s.trim()).collect();
    info!("Enabled tool categories: {:?}", enabled_tools);

    // Security warning
    if args.allow_unsafe && enabled_tools.contains(&"system") {
        warn!("⚠️  UNSAFE MODE ENABLED - Dangerous system commands are allowed!");
        warn!("⚠️  This is NOT RECOMMENDED for production use!");
    }

    // Create base server configuration
    let base_config = ServerConfig {
        name: args.name.clone(),
        description: "Unified MCP Tools Server - Git, Code Analysis, Web, and System tools"
            .to_string(),
        version: "1.0.0".to_string(),
        host: args.host.clone(),
        port: args.port,
        max_connections: 100,
        request_timeout_secs: 300,
        log_requests: args.verbose,
        server_config: std::collections::HashMap::new(),
    };

    // Initialize enabled servers
    let mut servers: Vec<Box<dyn McpServerBase + Send + Sync>> = Vec::new();
    let mut tool_count = 0;

    if enabled_tools.contains(&"git") {
        info!("Initializing Git Tools server...");
        let mut git_config = base_config.clone();
        git_config.name = format!("{}-git", args.name);
        let mut git_server = GitToolsServer::new(git_config).await?;
        git_server.initialize().await?;
        let capabilities = git_server.get_capabilities().await?;
        tool_count += capabilities.tools.len();
        info!(
            "✅ Git Tools server initialized ({} tools)",
            capabilities.tools.len()
        );
        servers.push(Box::new(git_server));
    }

    if enabled_tools.contains(&"code") {
        info!("Initializing Code Analysis server...");
        let mut code_config = base_config.clone();
        code_config.name = format!("{}-code", args.name);
        let mut code_server = CodeAnalysisServer::new(code_config).await?;
        code_server.initialize().await?;
        let capabilities = code_server.get_capabilities().await?;
        tool_count += capabilities.tools.len();
        info!(
            "✅ Code Analysis server initialized ({} tools)",
            capabilities.tools.len()
        );
        servers.push(Box::new(code_server));
    }

    if enabled_tools.contains(&"web") {
        info!("Initializing Web Tools server...");
        let mut web_config = base_config.clone();
        web_config.name = format!("{}-web", args.name);
        let mut web_server = WebToolsServer::new(web_config).await?;
        web_server.initialize().await?;
        let capabilities = web_server.get_capabilities().await?;
        tool_count += capabilities.tools.len();
        info!(
            "✅ Web Tools server initialized ({} tools)",
            capabilities.tools.len()
        );
        servers.push(Box::new(web_server));
    }

    if enabled_tools.contains(&"system") {
        info!("Initializing System Tools server...");
        let mut system_config = base_config.clone();
        system_config.name = format!("{}-system", args.name);
        let mut system_server = SystemToolsServer::new(system_config).await?;
        system_server.initialize().await?;
        let capabilities = system_server.get_capabilities().await?;
        tool_count += capabilities.tools.len();
        info!(
            "✅ System Tools server initialized ({} tools)",
            capabilities.tools.len()
        );
        servers.push(Box::new(system_server));
    }

    info!("🚀 Unified MCP Tools Server ready!");
    info!("📊 Total tools available: {}", tool_count);
    info!("🔧 Active server modules: {}", servers.len());
    info!("🌐 Server is ready to accept connections");
    info!("Press Ctrl+C to shutdown");

    // Wait for shutdown signal
    match signal::ctrl_c().await {
        Ok(()) => {
            info!("Received shutdown signal");
        }
        Err(err) => {
            error!("Unable to listen for shutdown signal: {}", err);
        }
    }

    // Shutdown all servers
    info!("Shutting down Unified MCP Tools Server...");
    for (i, mut server) in servers.into_iter().enumerate() {
        info!("Shutting down server module {}...", i + 1);
        if let Err(e) = server.shutdown().await {
            error!("Error shutting down server module {}: {}", i + 1, e);
        }
    }
    info!("Server shutdown complete");

    Ok(())
}