1/// The implementation of this tool draws heavily from Zed's
2/// See
3use std::path::PathBuf;
4
5use async_lsp::LanguageServer;
6use async_lsp::lsp_types::{
7 DocumentDiagnosticParams, DocumentDiagnosticReportResult, PartialResultParams,
8 TextDocumentIdentifier, Url, WorkDoneProgressParams,
9};
10use rmcp::ErrorData as MCPError;
11use rmcp::{handler::server::wrapper::Parameters, model::CallToolResult, schemars, serde_json};
12use tokio::io::AsyncReadExt; // for read_to_end()
13
14use crate::mcp::*;
15
16#[derive(Debug, serde::Deserialize, schemars::JsonSchema)]
17pub struct ReadToolArgs {
18 pub path: PathBuf,
19 pub range_start: usize,
20 pub range_end: usize,
21}
22
23#[derive(Debug, serde::Serialize)]
24pub struct ReadToolOutput {
25 pub content: Option<String>,
26 pub diagnostics: DocumentDiagnosticReportResult,
27}
28
29pub async fn call(
30 server: &MCPServer,
31 Parameters(args): Parameters<ReadToolArgs>,
32) -> Result<CallToolResult, MCPError> {
33 let file_path = server
34 .config
35 .path_in_project(&args.path)
36 .await
37 .map_err(|err| MCPError::invalid_request(format!("{:?}", err), None))?
38 .ok_or_else(|| {
39 MCPError::invalid_params(format!("Path not in project: {:?}", &args.path), None)
40 })?;
41
42 let file = tokio::fs::File::open(file_path.as_path())
43 .await
44 .map_err(|e| MCPError::internal_error(format!("Failed to open file: {e:?}"), None))?;
45
46 let file_buf = server.buf_pool.checkout();
47
48 Err(MCPError::internal_error("Not yet implemented", None))
49 // let content = tokio::fs::read_to_string(&file_path)
50 // .await
51 // .map_err(|e| MCPError::invalid_request(format!("Failed to read file: {e}"), None))?;
52
53 // let mut lsp_server = server.lsp_server.clone();
54
55 // let diagnostic_report = lsp_server
56 // .document_diagnostic(DocumentDiagnosticParams {
57 // text_document: TextDocumentIdentifier::new(Url::from_file_path(file_path).unwrap()),
58 // identifier: None,
59 // previous_result_id: None,
60 // work_done_progress_params: WorkDoneProgressParams {
61 // work_done_token: None,
62 // },
63 // partial_result_params: PartialResultParams {
64 // partial_result_token: None,
65 // },
66 // })
67 // .await
68 // .unwrap();
69
70 // Ok(CallToolResult {
71 // content: vec![],
72 // structured_content: Some(serde_json::json!(ReadToolOutput {
73 // content: Some(content),
74 // diagnostics: diagnostic_report
75 // })),
76 // is_error: None,
77 // meta: None,
78 // })
79}