1use std::path::PathBuf;
 2use std::sync::Arc;
 3
 4use rmcp::ErrorData as MCPError;
 5use rmcp::ServerHandler as MCPServerHandler;
 6use rmcp::handler::server::tool::ToolRouter;
 7use rmcp::handler::server::wrapper::Parameters;
 8use rmcp::model::CallToolResult;
 9use rmcp::model::{Implementation, ProtocolVersion, ServerCapabilities, ServerInfo};
10use rmcp::{tool_handler, tool_router};
11
12use async_lsp::ServerSocket as LSPServerSocket;
13
14use crate::config::Config;
15use crate::lsp::LSPClient;
16pub use crate::mcp::tools::read::*;
17
18pub struct MCPServer {
19    pub(crate) tool_router: ToolRouter<Self>,
20    pub(crate) config: Arc<Config>,
21    pub(crate) lsp_server: LSPServerSocket,
22}
23
24pub async fn setup(config: Arc<Config>) -> anyhow::Result<(MCPServer, LSPClient)> {
25    let lsp_client = LSPClient::setup(config.clone()).await?;
26
27    let server = MCPServer::new(config, lsp_client.server.clone());
28
29    Ok((server, lsp_client))
30}
31
32impl MCPServer {
33    pub fn new(config: Arc<Config>, lsp_server: LSPServerSocket) -> Self {
34        Self {
35            config,
36            lsp_server,
37            tool_router: Self::tool_router(),
38        }
39    }
40
41    pub async fn run(self, lsp_client: LSPClient) -> anyhow::Result<()> {
42        let mainloop_fut = tokio::spawn(async move {
43            lsp_client
44                .run_main_loop()
45                .await
46                .expect("Error while running main LSP loop");
47        });
48
49        let server = rmcp::ServiceExt::serve(self, rmcp::transport::stdio())
50            .await
51            .expect("Failed to start serving MCP");
52
53        let (mainloop_result, server_result) = tokio::join!(mainloop_fut, server.waiting());
54
55        mainloop_result?;
56        server_result?;
57
58        Ok(())
59    }
60}
61
62#[tool_router]
63impl MCPServer {
64    #[rmcp::tool(
65        description = "Like the 'view' tool, except it returns LSP diagnostics too. Always use this instead of 'view'"
66    )]
67    pub async fn read(
68        &self,
69        Parameters(args): Parameters<ReadToolArgs>,
70    ) -> Result<CallToolResult, MCPError> {
71        crate::mcp::tools::read::call(self, Parameters(args)).await
72    }
73}
74
75#[tool_handler]
76impl MCPServerHandler for MCPServer {
77    fn get_info(&self) -> ServerInfo {
78        ServerInfo {
79            protocol_version: ProtocolVersion::V_2024_11_05,
80            capabilities: ServerCapabilities::builder().enable_tools().build(),
81            server_info: Implementation::from_build_env(),
82            instructions: Some("This server turns standard coding agent tools like `read` and `edit` into LSP clients.".into())
83        }
84    }
85}