use std::sync::Arc;
use clap::{Parser, ValueEnum};
use tokio::sync::Mutex;
use tracing_subscriber::EnvFilter;
use zendriver_mcp::server;
use zendriver_mcp::state::{SessionState, StealthProfileChoice};
#[derive(Debug, Parser)]
#[command(name = "zendriver-mcp", version, about)]
struct Cli {
#[arg(long, value_name = "ADDR")]
http: Option<String>,
#[arg(long, value_enum, default_value_t = StealthProfileArg::Auto)]
stealth_profile: StealthProfileArg,
#[arg(long, default_value = "info")]
log: String,
}
#[derive(Debug, Clone, Copy, ValueEnum)]
enum StealthProfileArg {
Auto,
Native,
SpoofMacos,
SpoofLinux,
SpoofWindows,
}
impl From<StealthProfileArg> for StealthProfileChoice {
fn from(v: StealthProfileArg) -> Self {
match v {
StealthProfileArg::Auto => Self::Auto,
StealthProfileArg::Native => Self::Native,
StealthProfileArg::SpoofMacos => Self::SpoofMacos,
StealthProfileArg::SpoofLinux => Self::SpoofLinux,
StealthProfileArg::SpoofWindows => Self::SpoofWindows,
}
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let cli = Cli::parse();
tracing_subscriber::fmt()
.with_env_filter(EnvFilter::new(&cli.log))
.with_writer(std::io::stderr)
.init();
let state = Arc::new(Mutex::new(SessionState {
stealth_profile_choice: cli.stealth_profile.into(),
..SessionState::new()
}));
match cli.http {
Some(addr_str) => {
let addr: std::net::SocketAddr = addr_str
.parse()
.map_err(|e| format!("invalid --http address `{addr_str}`: {e}"))?;
server::run_http(addr, cli.stealth_profile.into()).await?;
}
None => server::run_stdio(state).await?,
}
Ok(())
}