Skip to main content

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}