mcprotocol_rs/transport/
mod.rs

1use async_trait::async_trait;
2use serde_json::Value;
3
4use crate::transport::{http::HttpTransport, stdio::StdioTransport};
5use crate::{protocol::Message, Result};
6
7pub mod http;
8pub mod stdio;
9
10// Re-export default implementations
11pub use http::{client::DefaultHttpClient as HttpClient, server::DefaultHttpServer as HttpServer};
12pub use stdio::{
13    client::DefaultStdioClient as StdioClient, server::DefaultStdioServer as StdioServer,
14};
15
16/// Transport configuration
17#[derive(Debug, Clone)]
18pub struct TransportConfig {
19    /// Transport type
20    pub transport_type: TransportType,
21    /// Optional configuration parameters
22    pub parameters: Option<Value>,
23}
24
25/// Transport type
26#[derive(Debug, Clone)]
27pub enum TransportType {
28    /// Stdio transport
29    Stdio {
30        /// Server executable path (only required for clients)
31        server_path: Option<String>,
32        /// Server arguments (only required for clients)
33        server_args: Option<Vec<String>>,
34    },
35    /// HTTP transport
36    Http {
37        /// Server base URL
38        base_url: String,
39        /// Optional authentication token
40        auth_token: Option<String>,
41    },
42}
43
44/// Base trait for transport layers
45#[async_trait]
46pub trait Transport: Send + Sync {
47    /// Initialize the transport
48    async fn initialize(&mut self) -> Result<()>;
49    /// Send a message
50    async fn send(&self, message: Message) -> Result<()>;
51    /// Receive a message
52    async fn receive(&self) -> Result<Message>;
53    /// Close the transport
54    async fn close(&mut self) -> Result<()>;
55}
56
57/// Client transport factory
58pub struct ClientTransportFactory;
59
60impl ClientTransportFactory {
61    /// Create a new transport instance
62    pub fn create(&self, config: TransportConfig) -> Result<Box<dyn Transport>> {
63        match config.transport_type {
64            TransportType::Stdio {
65                server_path,
66                server_args,
67            } => {
68                use stdio::client::{StdioClient, StdioClientConfig};
69                let config = StdioClientConfig {
70                    server_path: server_path
71                        .map(std::path::PathBuf::from)
72                        .unwrap_or_default(),
73                    server_args: server_args.unwrap_or_default(),
74                    ..Default::default()
75                };
76                let client = StdioClient::new(config);
77                Ok(Box::new(StdioClientTransport(client)))
78            }
79            TransportType::Http {
80                base_url,
81                auth_token,
82            } => {
83                use http::client::{HttpClient, HttpClientConfig};
84                let config = HttpClientConfig {
85                    base_url,
86                    auth_token,
87                };
88                let client = HttpClient::new(config)?;
89                Ok(Box::new(HttpClientTransport(client)))
90            }
91        }
92    }
93}
94
95/// Server transport factory
96pub struct ServerTransportFactory;
97
98impl ServerTransportFactory {
99    /// Create a new transport instance
100    pub fn create(&self, config: TransportConfig) -> Result<Box<dyn Transport>> {
101        match config.transport_type {
102            TransportType::Stdio { .. } => {
103                use stdio::server::{StdioServer, StdioServerConfig};
104                let server = StdioServer::new(StdioServerConfig::default());
105                Ok(Box::new(StdioServerTransport(server)))
106            }
107            TransportType::Http {
108                base_url,
109                auth_token,
110            } => {
111                use http::server::{AxumHttpServer, HttpServerConfig};
112                let addr = base_url
113                    .parse()
114                    .map_err(|e| crate::Error::Transport(format!("Invalid address: {}", e)))?;
115                let config = HttpServerConfig { addr, auth_token };
116                let server = AxumHttpServer::new(config);
117                Ok(Box::new(HttpServerTransport(server)))
118            }
119        }
120    }
121}
122
123// Wrapper types for implementing Transport trait
124struct StdioClientTransport(stdio::client::StdioClient);
125struct StdioServerTransport(stdio::server::StdioServer);
126struct HttpClientTransport(http::client::HttpClient);
127struct HttpServerTransport(http::server::AxumHttpServer);
128
129// Implement Transport trait for wrapper types
130macro_rules! impl_transport {
131    ($wrapper:ident, $inner:ident) => {
132        #[async_trait]
133        impl Transport for $wrapper {
134            async fn initialize(&mut self) -> Result<()> {
135                self.0.initialize().await
136            }
137
138            async fn send(&self, message: Message) -> Result<()> {
139                self.0.send(message).await
140            }
141
142            async fn receive(&self) -> Result<Message> {
143                self.0.receive().await
144            }
145
146            async fn close(&mut self) -> Result<()> {
147                self.0.close().await
148            }
149        }
150    };
151}
152
153impl_transport!(StdioClientTransport, StdioClient);
154impl_transport!(StdioServerTransport, StdioServer);
155impl_transport!(HttpClientTransport, HttpClient);
156impl_transport!(HttpServerTransport, AxumHttpServer);