1mod config;
2mod lsp;
3mod mcp;
4
5use clap::Parser;
6use futures::join;
7use rmcp::ServiceExt;
8
9use config::{CommandLineArgs, Config};
10use lsp::setup_lsp_client;
11use mcp::{MCPServer, MCPServerConfig};
12
13#[tokio::main]
14async fn main() -> Result<(), Box<dyn std::error::Error>> {
15 let args = CommandLineArgs::parse();
16 let config = Config::load(&args.config).await?;
17
18 let (mainloop_fut, lsp_server) = setup_lsp_client(
19 &config.lsp_server_command.command,
20 &config.lsp_server_command.args,
21 &config.project_root,
22 )
23 .await?;
24
25 let project_root_canonicalized = tokio::fs::canonicalize(config.project_root)
26 .await
27 .expect("Failed to canonicalize project root");
28
29 let mcp_service = MCPServer::new(
30 MCPServerConfig {
31 project_root: project_root_canonicalized,
32 },
33 lsp_server,
34 );
35
36 let server = mcp_service
37 .serve(rmcp::transport::stdio())
38 .await
39 .expect("Failed to starting serving MCP");
40 let (r1, r2) = join!(mainloop_fut, server.waiting());
41 r1.expect("R1 failed");
42
43 r2.expect("R2 failed");
44
45 Ok(())
46}