Skip to content

Commit b2df171

Browse files
added version tool
1 parent fc3f2f9 commit b2df171

File tree

6 files changed

+91
-6
lines changed

6 files changed

+91
-6
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,4 @@ Thumbs.db
2424
*.swo
2525
output_tests
2626
target/*
27+
context_portal/*

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ This is an MCP (Model Context Protocol) server that provides tools for Rust crat
1111
## Installation
1212

1313
```bash
14-
git clone https://github.com/d6e/cratedocs-mcp.git
14+
git clone https://github.com/promptexecution/cratedocs-mcp.git
1515
cd cratedocs-mcp
1616
cargo build --release
17+
cargo install --path .
1718
```
1819

1920
## Running the Server

src/bin/cratedocs.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ struct Cli {
2222

2323
#[derive(Subcommand)]
2424
enum Commands {
25+
/// Output the version and exit
26+
Version,
2527
/// Run the server in stdin/stdout mode
2628
Stdio {
2729
/// Enable debug logging
@@ -103,6 +105,10 @@ async fn main() -> Result<()> {
103105
let cli = Cli::parse();
104106

105107
match cli.command {
108+
Commands::Version => {
109+
println!("{}", env!("CARGO_PKG_VERSION"));
110+
Ok(())
111+
},
106112
Commands::Stdio { debug } => run_stdio_server(debug).await,
107113
Commands::Http { address, debug } => run_http_server(address, debug).await,
108114
Commands::Test {

src/tools/docs/tests.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,8 @@ async fn test_list_tools() {
7575
let router = DocRouter::new();
7676
let tools = router.list_tools();
7777

78-
// Should have exactly 3 tools
79-
assert_eq!(tools.len(), 3);
78+
// Should have exactly 4 tools (lookup_crate, search_crates, lookup_item, list_crate_items)
79+
assert_eq!(tools.len(), 4);
8080

8181
// Check tool names
8282
let tool_names: Vec<String> = tools.iter().map(|t| t.name.clone()).collect();

src/tools/item_list.rs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
use anyhow::Result;
2+
3+
/// Represents filters for item listing.
4+
#[derive(Debug)]
5+
pub struct ItemListFilters {
6+
pub item_type: Option<String>,
7+
pub visibility: Option<String>,
8+
pub module: Option<String>,
9+
}
10+
11+
/// Stub for the crate item enumeration tool.
12+
/// This will use rust-analyzer to enumerate items in a crate.
13+
pub async fn list_crate_items(
14+
crate_name: &str,
15+
version: &str,
16+
filters: Option<ItemListFilters>,
17+
) -> Result<String> {
18+
// 🦨 skunky: Implementation pending. Will use rust-analyzer APIs.
19+
Ok(format!(
20+
"Stub: list_crate_items for crate: {}, version: {}, filters: {:?}",
21+
crate_name, version, filters
22+
))
23+
}
24+
25+
#[cfg(test)]
26+
mod tests {
27+
use super::*;
28+
use tokio;
29+
30+
#[tokio::test]
31+
async fn test_basic_call_returns_stub() {
32+
let result = list_crate_items("serde", "1.0.0", None).await.unwrap();
33+
assert!(result.contains("Stub: list_crate_items for crate: serde, version: 1.0.0"), "Stub output missing expected text");
34+
}
35+
36+
#[tokio::test]
37+
async fn test_with_item_type_filter() {
38+
let filters = ItemListFilters {
39+
item_type: Some("struct".to_string()),
40+
visibility: None,
41+
module: None,
42+
};
43+
let result = list_crate_items("serde", "1.0.0", Some(filters)).await.unwrap();
44+
assert!(result.contains("filters: Some"), "Stub output missing filters");
45+
assert!(result.contains("struct"), "Stub output missing item_type");
46+
}
47+
48+
#[tokio::test]
49+
async fn test_with_visibility_filter() {
50+
let filters = ItemListFilters {
51+
item_type: None,
52+
visibility: Some("pub".to_string()),
53+
module: None,
54+
};
55+
let result = list_crate_items("serde", "1.0.0", Some(filters)).await.unwrap();
56+
assert!(result.contains("filters: Some"), "Stub output missing filters");
57+
assert!(result.contains("pub"), "Stub output missing visibility");
58+
}
59+
60+
#[tokio::test]
61+
async fn test_with_module_filter() {
62+
let filters = ItemListFilters {
63+
item_type: None,
64+
visibility: None,
65+
module: Some("serde::de".to_string()),
66+
};
67+
let result = list_crate_items("serde", "1.0.0", Some(filters)).await.unwrap();
68+
assert!(result.contains("filters: Some"), "Stub output missing filters");
69+
assert!(result.contains("serde::de"), "Stub output missing module filter");
70+
}
71+
72+
#[tokio::test]
73+
async fn test_invalid_crate_name() {
74+
let result = list_crate_items("not_a_real_crate", "0.0.1", None).await.unwrap();
75+
assert!(result.contains("not_a_real_crate"), "Stub output missing invalid crate name");
76+
}
77+
}

tests/integration_tests.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ async fn test_doc_router_initialization() {
1313

1414
// Tools should be available and correctly configured
1515
let tools = router.list_tools();
16-
assert_eq!(tools.len(), 3);
16+
assert_eq!(tools.len(), 4);
1717

1818
// Check specific tool schemas
1919
let lookup_crate_tool = tools.iter().find(|t| t.name == "lookup_crate").unwrap();
@@ -68,8 +68,8 @@ async fn test_end_to_end_crate_lookup() {
6868
// The response should be HTML from docs.rs
6969
match &content[0] {
7070
mcp_core::Content::Text(text) => {
71-
assert!(text.text.contains("<!DOCTYPE html>"));
72-
assert!(text.text.contains("serde"));
71+
// Output is now markdown, not HTML
72+
assert!(text.text.to_lowercase().contains("serde"));
7373
},
7474
_ => panic!("Expected text content"),
7575
}

0 commit comments

Comments
 (0)