1#![cfg_attr(docsrs, feature(doc_cfg))]
16#[cfg(all(feature = "io-uring", not(tokio_unstable)))]
28compile_error!(
29 "feature `io-uring` requires cfg `tokio_unstable` (set RUSTFLAGS/RUSTDOCFLAGS to \"--cfg tokio_unstable\")"
30);
31
32pub mod config;
34pub mod s3_client;
36pub mod server;
38
39pub use config::Config;
41pub use s3_client::{BucketInfo, S3Client};
43pub use server::RustfsMcpServer;
45
46use anyhow::{Context, Result};
47use rmcp::ServiceExt;
48use tokio::io::{stdin, stdout};
49use tracing::info;
50
51pub async fn run_server_with_config(config: Config) -> Result<()> {
53 info!("Starting RustFS MCP Server with provided configuration");
54
55 config
56 .validate()
57 .context("Configuration validation failed")?;
58
59 let server = RustfsMcpServer::new(config).await?;
60
61 info!("Running MCP server with stdio transport");
62
63 server
65 .serve((stdin(), stdout()))
66 .await
67 .context("Failed to serve MCP server")?
68 .waiting()
69 .await
70 .context("Error while waiting for server shutdown")?;
71
72 Ok(())
73}
74
75pub async fn run_server() -> Result<()> {
77 info!("Starting RustFS MCP Server with default configuration");
78
79 let config = Config::default();
80 run_server_with_config(config).await
81}
82
83pub fn validate_environment() -> Result<()> {
87 use std::env;
88
89 if env::var("AWS_ACCESS_KEY_ID").is_err() {
90 anyhow::bail!("AWS_ACCESS_KEY_ID environment variable is required");
91 }
92
93 if env::var("AWS_SECRET_ACCESS_KEY").is_err() {
94 anyhow::bail!("AWS_SECRET_ACCESS_KEY environment variable is required");
95 }
96
97 Ok(())
98}
99
100#[cfg(test)]
101mod tests {
102 use super::*;
103
104 #[test]
105 fn test_config_creation() {
106 let config = Config {
107 access_key_id: Some("test_key".to_string()),
108 secret_access_key: Some("test_secret".to_string()),
109 ..Config::default()
110 };
111
112 assert!(config.validate().is_ok());
113 assert_eq!(config.access_key_id(), "test_key");
114 assert_eq!(config.secret_access_key(), "test_secret");
115 }
116
117 #[tokio::test]
118 async fn test_run_server_with_invalid_config() {
119 let config = Config::default();
120
121 let result = run_server_with_config(config).await;
122 assert!(result.is_err());
123 }
124}