Skip to content

Commit ac46dde

Browse files
tdlr didn't work with stdio
1 parent 948a515 commit ac46dde

File tree

5 files changed

+41
-42
lines changed

5 files changed

+41
-42
lines changed

README.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,16 @@ cargo run --bin cratedocs http --debug
4141

4242
### Directly Testing Documentation Tools
4343

44-
# Enumerate crate items
45-
cargo run --bin cratedocs test --tool list_crate_items --crate-name serde --version 1.0.0 --item-type struct
46-
cargo run --bin cratedocs test --tool list_crate_items --crate-name tokio --version 1.28.0 --visibility pub --module tokio::sync
4744
You can directly test the documentation tools from the command line without starting a server:
4845

4946
```bash
5047
# Get help for the test command
5148
cargo run --bin cratedocs test --tool help
5249

50+
# Enumerate crate items (step by step)
51+
cargo run --bin cratedocs test --tool list_crate_items --crate-name serde --version 1.0.0 --item-type struct
52+
cargo run --bin cratedocs test --tool list_crate_items --crate-name tokio --version 1.28.0 --visibility pub --module tokio::sync
53+
5354
# Look up crate documentation
5455
cargo run --bin cratedocs test --tool lookup_crate --crate-name tokio
5556

@@ -74,6 +75,9 @@ cargo run --bin cratedocs test --tool lookup_crate --crate-name tokio --output t
7475

7576
# Summarize output by stripping LICENSE and VERSION sections, limits to xxxxx tokens (uses huggingface tokenizer)
7677
cargo run --bin cratedocs test --tool lookup_crate --crate-name tokio --tldr --max_tokens 48000
78+
79+
80+
7781
```
7882

7983
By default, the HTTP server will listen on `http://127.0.0.1:8080/sse`.

src/bin/cratedocs.rs

Lines changed: 12 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use std::net::SocketAddr;
99
use tokio::io::{stdin, stdout};
1010
use tracing_appender::rolling::{RollingFileAppender, Rotation};
1111
use tracing_subscriber::{self, EnvFilter, layer::SubscriberExt, util::SubscriberInitExt};
12-
use regex::Regex;
12+
use cratedocs_mcp::tools::tldr;
1313

1414
#[derive(Parser)]
1515
#[command(author, version = "0.2.0", about, long_about = None)]
@@ -29,6 +29,9 @@ enum Commands {
2929
/// Enable debug logging
3030
#[arg(short, long)]
3131
debug: bool,
32+
/// Summarize output by stripping LICENSE and VERSION sections (TL;DR mode)
33+
#[arg(long)]
34+
tldr: bool,
3235
},
3336
/// Run the server with HTTP/SSE interface
3437
Http {
@@ -109,7 +112,7 @@ async fn main() -> Result<()> {
109112
println!("{}", env!("CARGO_PKG_VERSION"));
110113
Ok(())
111114
},
112-
Commands::Stdio { debug } => run_stdio_server(debug).await,
115+
Commands::Stdio { debug, tldr } => run_stdio_server(debug, tldr).await,
113116
Commands::Http { address, debug } => run_http_server(address, debug).await,
114117
Commands::Test {
115118
tool,
@@ -145,7 +148,7 @@ async fn main() -> Result<()> {
145148
}
146149
}
147150

148-
async fn run_stdio_server(debug: bool) -> Result<()> {
151+
async fn run_stdio_server(debug: bool, tldr: bool) -> Result<()> {
149152
// Set up file appender for logging
150153
let file_appender = RollingFileAppender::new(Rotation::DAILY, "logs", "stdio-server.log");
151154

@@ -164,13 +167,16 @@ async fn run_stdio_server(debug: bool) -> Result<()> {
164167
tracing::info!("Starting MCP documentation server in STDIN/STDOUT mode");
165168

166169
// Create an instance of our documentation router
167-
let router = RouterService(DocRouter::new());
170+
// If tldr is needed globally, you may want to pass it to DocRouter or handle it in tool output
171+
let router = RouterService(DocRouter::new_with_tldr(tldr));
168172

169173
// Create and run the server
170174
let server = Server::new(router);
171175
let transport = ByteTransport::new(stdin(), stdout());
172176

173177
tracing::info!("Documentation server initialized and ready to handle requests");
178+
// Note: tldr is parsed and available, but not yet used in stdio mode.
179+
// If you want to apply TLDR globally, you would need to modify DocRouter or Server to use it.
174180
Ok(server.run(transport).await?)
175181
}
176182

@@ -201,36 +207,6 @@ async fn run_http_server(address: String, debug: bool) -> Result<()> {
201207
}
202208

203209
// --- TLDR Helper Function ---
204-
fn apply_tldr(input: &str) -> String {
205-
// Remove LICENSE and VERSION(S) sections by skipping lines between those headings and the next heading or EOF.
206-
let mut output = Vec::new();
207-
let mut skip = false;
208-
209-
// Match any heading (with or without space) for LICENSE or VERSION(S)
210-
let tldr_section_re = Regex::new(r"(?i)^\s*#+\s*license\b|^\s*#+\s*version(s)?\b|^\s*#+license\b|^\s*#+version(s)?\b").unwrap();
211-
// Match any heading (for ending the skip)
212-
let heading_re = Regex::new(r"^\s*#+").unwrap();
213-
// Match <detail> tags including start, end, and inline attributes
214-
let detail_tag_re = Regex::new(r"<[/]?detail.*?>").unwrap();
215-
216-
for line in input.lines() {
217-
// Start skipping if we hit a LICENSE or VERSION(S) heading
218-
if !skip && tldr_section_re.is_match(line) {
219-
skip = true;
220-
continue; // skip the heading line itself
221-
}
222-
// Stop skipping at the next heading (but do not skip the heading itself)
223-
if skip && heading_re.is_match(line) && !tldr_section_re.is_match(line) {
224-
skip = false;
225-
}
226-
if !skip {
227-
// Remove <detail> tags from the line
228-
let cleaned_line = detail_tag_re.replace_all(line, "").to_string();
229-
output.push(cleaned_line.to_string());
230-
}
231-
}
232-
output.iter().map(|s| s.as_str()).collect::<Vec<_>>().join("\n")
233-
}
234210

235211
/// Configuration for the test tool
236212
struct TestToolConfig {
@@ -407,7 +383,7 @@ async fn run_test_tool(config: TestToolConfig) -> Result<()> {
407383

408384
// TL;DR processing: strip LICENSE and VERSION(S) sections if --tldr is set
409385
if tldr {
410-
content_str = apply_tldr(&content_str);
386+
content_str = tldr::apply_tldr(&content_str);
411387
}
412388

413389
let formatted_output = match format.as_str() {
@@ -507,7 +483,7 @@ async fn run_test_tool(config: TestToolConfig) -> Result<()> {
507483
}
508484
#[cfg(test)]
509485
mod tldr_tests {
510-
use super::apply_tldr;
486+
use cratedocs_mcp::tools::tldr::apply_tldr;
511487

512488
#[test]
513489
fn test_apply_tldr_removes_license_and_versions() {

src/tools/docs/docs.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::tools::item_list;
2+
use crate::tools::tldr;
23
use std::{future::Future, pin::Pin, sync::Arc};
34

45
use mcp_core::{
@@ -47,6 +48,7 @@ impl DocCache {
4748
pub struct DocRouter {
4849
pub client: Client,
4950
pub cache: DocCache,
51+
pub tldr: bool,
5052
}
5153

5254
impl Default for DocRouter {
@@ -56,12 +58,16 @@ impl Default for DocRouter {
5658
}
5759

5860
impl DocRouter {
59-
pub fn new() -> Self {
61+
pub fn new_with_tldr(tldr: bool) -> Self {
6062
Self {
6163
client: Client::new(),
6264
cache: DocCache::new(),
65+
tldr,
6366
}
6467
}
68+
pub fn new() -> Self {
69+
Self::new_with_tldr(false)
70+
}
6571

6672
// Fetch crate documentation from docs.rs
6773
async fn lookup_crate(&self, crate_name: String, version: Option<String>) -> Result<String, ToolError> {
@@ -363,9 +369,10 @@ impl mcp_server::Router for DocRouter {
363369
let this = self.clone();
364370
let tool_name = tool_name.to_string();
365371
let arguments = arguments.clone();
372+
let tldr = self.tldr;
366373

367374
Box::pin(async move {
368-
match tool_name.as_str() {
375+
let mut result = match tool_name.as_str() {
369376
"lookup_crate" => {
370377
let crate_name = arguments
371378
.get("crate_name")
@@ -455,7 +462,18 @@ impl mcp_server::Router for DocRouter {
455462
Ok(vec![Content::text(result)])
456463
}
457464
_ => Err(ToolError::NotFound(format!("Tool {} not found", tool_name))),
465+
}?;
466+
467+
// Apply TLDR filter if enabled
468+
if tldr {
469+
for content in &mut result {
470+
if let Content::Text(text) = content {
471+
text.text = tldr::apply_tldr(&text.text);
472+
}
473+
}
458474
}
475+
476+
Ok(result)
459477
})
460478
}
461479

src/tools/item_list.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use std::fs;
44
use std::path::Path;
55
use tar::Archive;
66
use flate2::read::GzDecoder;
7-
use syn::{File, Item};
7+
use syn::{Item};
88

99
/// Represents filters for item listing.
1010
#[derive(Debug)]

src/tools/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
pub mod docs;
22
pub mod item_list;
3+
pub mod tldr;
34

45
pub use docs::DocRouter;
56
pub use docs::docs::DocCache;

0 commit comments

Comments
 (0)