| mod indexer; |
| mod mcp; |
| mod parser; |
|
|
| use clap::Parser; |
| use indexer::TantivyEngine; |
| use mcp::McpServer; |
| use std::path::PathBuf; |
| use std::sync::Arc; |
| use tracing::info; |
|
|
| #[derive(Parser, Debug)] |
| #[command(name = "rust-mcp-search")] |
| #[command(about = "Ultra-high-performance Tantivy-backed Model Context Protocol server", long_about = None)] |
| struct Args { |
| |
| #[arg(short, long, env = "MCP_TRANSPORT", default_value = "stdio")] |
| transport: String, |
|
|
| |
| #[arg(long, env = "HOST", default_value = "0.0.0.0")] |
| host: String, |
|
|
| |
| #[arg(short, long, env = "PORT", default_value = "7860")] |
| port: u16, |
|
|
| |
| #[arg(short, long, env = "DATA_DIR", default_value = "./data/index")] |
| index_dir: PathBuf, |
|
|
| |
| #[arg(long, env = "RAYON_NUM_THREADS", default_value = "0")] |
| threads: usize, |
| } |
|
|
| #[tokio::main] |
| async fn main() -> anyhow::Result<()> { |
| let args = Args::parse(); |
|
|
| |
| tracing_subscriber::fmt() |
| .with_writer(std::io::stderr) |
| .with_env_filter( |
| tracing_subscriber::EnvFilter::from_default_env() |
| .add_directive(tracing::Level::INFO.into()), |
| ) |
| .init(); |
|
|
| if args.threads > 0 { |
| rayon::ThreadPoolBuilder::new() |
| .num_threads(args.threads) |
| .build_global()?; |
| info!("Configured Rayon thread pool with {} threads", args.threads); |
| } |
|
|
| info!("Initializing Tantivy index engine at: {:?}", args.index_dir); |
| let engine = Arc::new(TantivyEngine::new(&args.index_dir)?); |
| let server = Arc::new(McpServer::new(engine)); |
|
|
| match args.transport.to_lowercase().as_str() { |
| "http" | "sse" => { |
| info!("Starting MCP HTTP/SSE transport..."); |
| server.run_http(&args.host, args.port).await?; |
| } |
| "stdio" => { |
| info!("Starting MCP STDIO transport..."); |
| server.run_stdio().await?; |
| } |
| other => { |
| eprintln!("Unknown transport '{}'. Expected 'stdio' or 'http'.", other); |
| std::process::exit(1); |
| } |
| } |
|
|
| Ok(()) |
| } |