symposium_ferris/lib.rs
1//! # symposium-ferris - Ferris MCP Server
2//!
3//! Helpful tools for Rust development, exposed as an MCP server.
4//!
5//! ## Tools
6//!
7//! - `crate_source`: Fetch and extract Rust crate source code by name and version
8//! - `rust_researcher`: Research Rust crates using an LLM sub-agent (requires ACP session)
9//!
10//! ## Usage
11//!
12//! As a library for direct crate source access:
13//! ```ignore
14//! let result = Ferris::rust_crate("tokio").version("1.0").fetch().await?;
15//! println!("Sources at: {}", result.path.display());
16//! ```
17//!
18//! As an MCP server configuration:
19//! ```ignore
20//! let server = Ferris::default()
21//! .rust_researcher(true)
22//! .into_mcp_server(cwd);
23//! ```
24
25use std::path::PathBuf;
26
27use sacp::{ProxyToConductor, mcp_server::McpServer};
28
29mod component;
30mod crate_sources;
31pub mod error;
32mod rust_researcher;
33
34pub use component::FerrisComponent;
35pub use crate_sources::{FetchResult, RustCrateFetch};
36pub use error::{FerrisError, Result};
37
38/// Ferris - Rust development tools
39///
40/// This struct serves two purposes:
41/// 1. Configuration for the MCP server (which tools to enable)
42/// 2. Entry point for the public Rust API (associated functions)
43#[derive(Debug, Clone)]
44pub struct Ferris {
45 /// Enable the crate_source tool (default: true)
46 pub crate_sources: bool,
47 /// Enable the rust_researcher tool (default: false)
48 pub rust_researcher: bool,
49}
50
51impl Default for Ferris {
52 fn default() -> Self {
53 Self {
54 crate_sources: true,
55 rust_researcher: false,
56 }
57 }
58}
59
60impl Ferris {
61 /// Create a new Ferris configuration with default settings
62 pub fn new() -> Self {
63 Self::default()
64 }
65
66 /// Enable or disable the crate_source tool
67 pub fn crate_sources(mut self, enabled: bool) -> Self {
68 self.crate_sources = enabled;
69 self
70 }
71
72 /// Enable or disable the rust_researcher tool
73 pub fn rust_researcher(mut self, enabled: bool) -> Self {
74 self.rust_researcher = enabled;
75 self
76 }
77
78 /// Build an MCP server with the configured tools
79 ///
80 /// The `cwd` parameter specifies the working directory for the session.
81 /// This is used by tools that need workspace context (e.g., cargo metadata).
82 pub fn into_mcp_server(
83 self,
84 cwd: impl Into<PathBuf>,
85 ) -> McpServer<ProxyToConductor, impl sacp::JrResponder<ProxyToConductor>> {
86 let cwd = cwd.into();
87
88 let builder = McpServer::builder("ferris".to_string()).instructions(indoc::indoc! {"
89 Rust development tools provided by Ferris.
90
91 Available tools help with:
92 - Fetching Rust crate source code for inspection
93 - Researching Rust crate APIs and usage patterns
94 "});
95
96 let builder = crate::crate_sources::mcp::register(builder, self.crate_sources, cwd.clone());
97 let builder = crate::rust_researcher::register(builder, self.rust_researcher, cwd);
98
99 builder.build()
100 }
101
102 // -------------------------------------------------------------------------
103 // Public API - associated functions for direct usage
104 // -------------------------------------------------------------------------
105
106 /// Access a Rust crate's source code
107 ///
108 /// Returns a builder that can be used to specify version constraints
109 /// and fetch the crate sources.
110 ///
111 /// # Example
112 /// ```ignore
113 /// let result = Ferris::rust_crate("serde", ".")
114 /// .version("1.0")
115 /// .fetch()
116 /// .await?;
117 /// ```
118 pub fn rust_crate(name: &str, cwd: impl Into<std::path::PathBuf>) -> RustCrateFetch {
119 RustCrateFetch::new(name, cwd)
120 }
121}