Detailed changes
@@ -1,5 +1,6 @@
use std::ops::ControlFlow;
use std::path::PathBuf;
+use std::sync::Arc;
use async_lsp::lsp_types::notification::{Progress, PublishDiagnostics, ShowMessage};
use async_lsp::lsp_types::{
@@ -12,7 +13,10 @@ use async_process::{Child, Command as ProcessCommand, Stdio};
use futures::channel::oneshot;
use tower::ServiceBuilder;
+use crate::config::Config;
+
pub struct LSPClientState {
+ pub config: Arc<Config>,
pub indexed_tx: Option<oneshot::Sender<()>>,
}
@@ -28,22 +32,24 @@ pub struct LSPClient {
impl LSPClient {
pub async fn setup(
- lsp_command: &str,
- lsp_args: &[String],
- project_root: &PathBuf,
+ config: Arc<Config>,
) -> anyhow::Result<Self> {
- let child = ProcessCommand::new(lsp_command)
- .args(lsp_args)
- .current_dir(project_root)
+ let child = ProcessCommand::new(&config.lsp_server_command.command)
+ .args(&config.lsp_server_command.args)
+ .current_dir(&config.project_root)
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.stderr(Stdio::inherit())
.kill_on_drop(true)
.spawn()
- .expect(format!("Failed to start lsp: {} {:?}", lsp_command, lsp_args).as_ref());
+ .expect(format!("Failed to start lsp: {} {:?}", &config.lsp_server_command.command, &config.lsp_server_command.args).as_ref());
- let (mainloop, mut server) = async_lsp::MainLoop::new_client(|_server| {
- let mut router = Router::new(LSPClientState { indexed_tx: None });
+ let config_clone = config.clone();
+ let (mainloop, mut server) = async_lsp::MainLoop::new_client(move |_server| {
+ let mut router = Router::new(LSPClientState {
+ config: config_clone,
+ indexed_tx: None
+ });
router
.notification::<Progress>(|_this, _params| ControlFlow::Continue(()))
@@ -54,7 +60,7 @@ impl LSPClient {
ServiceBuilder::new().service(router)
});
- let project_root_canonicalized = tokio::fs::canonicalize(project_root)
+ let project_root_canonicalized = tokio::fs::canonicalize(&config.project_root)
.await
.expect("Failed to canonicalize project root");
@@ -2,6 +2,7 @@ mod config;
mod lsp;
mod mcp;
+use std::sync::Arc;
use clap::Parser;
use config::{CommandLineArgs, Config};
@@ -16,7 +17,7 @@ async fn main() -> anyhow::Result<()> {
.init();
let args = CommandLineArgs::parse();
- let config = Config::load(&args.config).await?;
+ let config = Arc::new(Config::load(&args.config).await?);
let (mcp_server, lsp_client) = mcp::setup(config).await?;
mcp_server.run(lsp_client).await?;
@@ -1,4 +1,5 @@
use std::path::PathBuf;
+use std::sync::Arc;
use rmcp::ErrorData as MCPError;
use rmcp::ServerHandler as MCPServerHandler;
@@ -16,31 +17,23 @@ pub use crate::mcp::tools::read::*;
pub struct MCPServer {
pub(crate) tool_router: ToolRouter<Self>,
- pub(crate) project_root: PathBuf,
+ pub(crate) config: Arc<Config>,
pub(crate) lsp_server: LSPServerSocket,
}
-pub async fn setup(config: Config) -> anyhow::Result<(MCPServer, LSPClient)> {
- let project_root = tokio::fs::canonicalize(&config.project_root)
- .await
- .expect("Failed to canonicalize project root");
+pub async fn setup(config: Arc<Config>) -> anyhow::Result<(MCPServer, LSPClient)> {
+ let lsp_client = LSPClient::setup(config.clone())
+ .await?;
- let lsp_client = LSPClient::setup(
- &config.lsp_server_command.command,
- &config.lsp_server_command.args,
- &project_root,
- )
- .await?;
-
- let server = MCPServer::new(project_root, lsp_client.server.clone());
+ let server = MCPServer::new(config, lsp_client.server.clone());
Ok((server, lsp_client))
}
impl MCPServer {
- pub fn new(project_root: PathBuf, lsp_server: LSPServerSocket) -> Self {
+ pub fn new(config: Arc<Config>, lsp_server: LSPServerSocket) -> Self {
Self {
- project_root,
+ config,
lsp_server,
tool_router: Self::tool_router(),
}
@@ -27,36 +27,35 @@ pub async fn call(
server: &MCPServer,
Parameters(args): Parameters<ReadToolArgs>,
) -> Result<CallToolResult, MCPError> {
- let file_path = server.project_root.join(&args.path);
- let file_path = tokio::fs::canonicalize(file_path).await.unwrap();
- let content = tokio::fs::read_to_string(&file_path)
- .await
- .map_err(|e| MCPError::invalid_request(format!("Failed to read file: {e}"), None))?;
-
- let mut lsp_server = server.lsp_server.clone();
-
- let diagnostic_report = lsp_server
- .document_diagnostic(DocumentDiagnosticParams {
- text_document: TextDocumentIdentifier::new(Url::from_file_path(file_path).unwrap()),
- identifier: None,
- previous_result_id: None,
- work_done_progress_params: WorkDoneProgressParams {
- work_done_token: None,
- },
- partial_result_params: PartialResultParams {
- partial_result_token: None,
- },
- })
- .await
- .unwrap();
-
- Ok(CallToolResult {
- content: vec![],
- structured_content: Some(serde_json::json!(ReadToolOutput {
- content: Some(content),
- diagnostics: diagnostic_report
- })),
- is_error: None,
- meta: None,
- })
+ Err(MCPError::internal_error("Not yet implemented", None))
+ // let content = tokio::fs::read_to_string(&file_path)
+ // .await
+ // .map_err(|e| MCPError::invalid_request(format!("Failed to read file: {e}"), None))?;
+
+ // let mut lsp_server = server.lsp_server.clone();
+
+ // let diagnostic_report = lsp_server
+ // .document_diagnostic(DocumentDiagnosticParams {
+ // text_document: TextDocumentIdentifier::new(Url::from_file_path(file_path).unwrap()),
+ // identifier: None,
+ // previous_result_id: None,
+ // work_done_progress_params: WorkDoneProgressParams {
+ // work_done_token: None,
+ // },
+ // partial_result_params: PartialResultParams {
+ // partial_result_token: None,
+ // },
+ // })
+ // .await
+ // .unwrap();
+
+ // Ok(CallToolResult {
+ // content: vec![],
+ // structured_content: Some(serde_json::json!(ReadToolOutput {
+ // content: Some(content),
+ // diagnostics: diagnostic_report
+ // })),
+ // is_error: None,
+ // meta: None,
+ // })
}