rust_mcp_server_syncable_cli/
lib.rs

1//! # mcp_rust_server
2//!
3//! High-performance Model Context Protocol (MCP) server for code analysis, security scanning,
4//! and project insights.
5//!
6//! ## Features
7//!
8//! - **Fast & Scalable**: async Rust on Tokio runtime  
9//! - **Protocols**: stdio and SSE (Server-Sent Events) transports  
10//! - **Extensible**: easy to add new handlers and endpoints  
11//! - **Production-Ready**: optimized release profile and structured logging  
12//!
13//! ## Installation
14//!
15//! **As a library**  
16//! Add to your `Cargo.toml` dependencies:
17//! ```toml
18//! [dependencies]
19//! mcp-rust-server = "0.1.0"
20//! ```
21//!
22//! **As CLI binaries**  
23//! Install from crates.io with Cargo:
24//! ```bash
25//! cargo install mcp-rust-server
26//! ```
27//! Binaries (`mcp-stdio` and `mcp-sse`) are placed in `$CARGO_HOME/bin`.
28//!
29//! ## Usage
30//!
31//! ### Library
32//!  
33//! ```rust
34//! use mcp_rust_server::{start_stdio, start_sse};
35//!
36//! #[tokio::main]
37//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
38//!     // Run as stdio MCP server
39//!     start_stdio().await?;
40//!
41//!     // Or run as SSE MCP server
42//!     // start_sse().await?;
43//!     Ok(())
44//! }
45//! ```
46//!
47//! ### CLI
48//!  
49//! ```bash
50//! # Start stdio server
51//! mcp-stdio
52//!
53//! # Start SSE server
54//! mcp-sse
55//! ```
56//!
57//! ## Examples
58//!  
59//! See each function’s docs below for more examples.
60
61mod handler;
62mod tools;
63
64use handler::MyServerHandler;
65use rust_mcp_sdk::{
66    error::SdkResult,
67    mcp_server::{hyper_server, server_runtime, HyperServerOptions, ServerRuntime},
68    schema::{
69        Implementation, InitializeResult, ServerCapabilities, ServerCapabilitiesTools,
70        LATEST_PROTOCOL_VERSION,
71    },
72    McpServer, StdioTransport, TransportOptions,
73};
74use tools::ServerTools;
75use tracing_subscriber::{fmt, prelude::*, EnvFilter};
76
77/// Starts the MCP server in **stdio** mode.
78///
79/// Reads framed MCP requests from `stdin` and writes framed responses to `stdout`.
80///
81/// # Errors
82///
83/// Returns an `SdkResult` error if initialization or transport setup fails.
84///
85/// # Example
86///
87/// ```no_run
88/// use mcp_rust_server::start_stdio;
89///
90/// #[tokio::main]
91/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
92///     start_stdio().await?;
93///     Ok(())
94/// }
95/// ```
96pub async fn start_stdio() -> SdkResult<()> {
97    // 1) Init logging
98    env_logger::init();
99
100    // 2) Build initialize result
101    let server_details = InitializeResult {
102        server_info: Implementation {
103            name: "Syncable-MCP-Server".to_string(),
104            version: env!("CARGO_PKG_VERSION").to_string(),
105        },
106        capabilities: ServerCapabilities {
107            tools: Some(ServerCapabilitiesTools { list_changed: None }),
108            ..Default::default()
109        },
110        protocol_version: LATEST_PROTOCOL_VERSION.to_string(),
111        instructions: Some(
112            "Welcome to the Syncable-MCP-Server. Use list_tools to see available functionalities."
113                .into(),
114        ),
115        meta: None,
116    };
117
118    // 3) Log banners to stderr
119    let available_tools = ServerTools::tools();
120    eprintln!("πŸš€ Starting Syncable-MCP-Server (stdio mode)...");
121    eprintln!("πŸ“‹ Available tools ({}):", available_tools.len());
122    for (i, tool) in available_tools.iter().enumerate() {
123        eprintln!(
124            "   {}. {} - {}",
125            i + 1,
126            tool.name,
127            tool.description.as_deref().unwrap_or("No description")
128        );
129    }
130    eprintln!();
131    eprintln!("βœ… Server initialized successfully. Listening for MCP requests...");
132
133    // 4) Create transport and runtime
134    let transport = StdioTransport::new(TransportOptions::default())?;
135    let handler = MyServerHandler {};
136    let server: ServerRuntime = server_runtime::create_server(server_details, transport, handler);
137
138    // 5) Run
139    server.start().await?;
140    Ok(())
141}
142
143/// Starts the MCP server in **SSE** (Server-Sent Events) mode.
144///
145/// Hosts an HTTP endpoint on `http://0.0.0.0:8000/mcp` that streams MCP responses.
146///
147/// # Errors
148///
149/// Returns an `SdkResult` error if the HTTP server fails to bind or run.
150///
151/// # Example
152///
153/// ```no_run
154/// use mcp_rust_server::start_sse;
155///
156/// #[tokio::main]
157/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
158///     start_sse().await?;
159///     Ok(())
160/// }
161/// ```
162pub async fn start_sse() -> SdkResult<()> {
163    // 1) Initialize tracing
164    tracing_subscriber::registry()
165        .with(fmt::layer())
166        .with(EnvFilter::try_from_default_env().unwrap_or_else(|_| "info".into()))
167        .init();
168
169    tracing::info!("Logger initialized. Defining server details...");
170
171    // 2) Build initialize result
172    let server_details = InitializeResult {
173        server_info: Implementation {
174            name: "Rust MCP Server (SSE)".to_string(),
175            version: env!("CARGO_PKG_VERSION").to_string(),
176        },
177        capabilities: ServerCapabilities {
178            tools: Some(ServerCapabilitiesTools { list_changed: None }),
179            ..Default::default()
180        },
181        protocol_version: LATEST_PROTOCOL_VERSION.to_string(),
182        instructions: Some(
183            "Welcome to the Rust MCP Server (SSE). Connect via a web client.".into(),
184        ),
185        meta: None,
186    };
187
188    // 3) Log tools
189    let available_tools = ServerTools::tools();
190    tracing::info!("πŸš€ Starting Rust MCP Server (SSE)...");
191    tracing::info!("πŸ“‹ Available tools ({}):", available_tools.len());
192    for (i, tool) in available_tools.iter().enumerate() {
193        tracing::info!(
194            "   {}. {} - {}",
195            i + 1,
196            tool.name,
197            tool.description.as_deref().unwrap_or("No description")
198        );
199    }
200
201    // 4) Create handler & server options
202    let handler = MyServerHandler {};
203    let options = HyperServerOptions {
204        host: "0.0.0.0".to_string(),
205        port: 8000,
206        ..Default::default()
207    };
208
209    tracing::info!("Creating the MCP SSE server...");
210    let server = hyper_server::create_server(server_details, handler, options);
211
212    tracing::info!("βœ… SSE server listening on http://0.0.0.0:8000");
213    // 5) Run
214    server.start().await?;
215    Ok(())
216}