mcprotocol_rs/transport/
mod.rs1use 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
10pub 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#[derive(Debug, Clone)]
18pub struct TransportConfig {
19 pub transport_type: TransportType,
21 pub parameters: Option<Value>,
23}
24
25#[derive(Debug, Clone)]
27pub enum TransportType {
28 Stdio {
30 server_path: Option<String>,
32 server_args: Option<Vec<String>>,
34 },
35 Http {
37 base_url: String,
39 auth_token: Option<String>,
41 },
42}
43
44#[async_trait]
46pub trait Transport: Send + Sync {
47 async fn initialize(&mut self) -> Result<()>;
49 async fn send(&self, message: Message) -> Result<()>;
51 async fn receive(&self) -> Result<Message>;
53 async fn close(&mut self) -> Result<()>;
55}
56
57pub struct ClientTransportFactory;
59
60impl ClientTransportFactory {
61 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
95pub struct ServerTransportFactory;
97
98impl ServerTransportFactory {
99 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
123struct StdioClientTransport(stdio::client::StdioClient);
125struct StdioServerTransport(stdio::server::StdioServer);
126struct HttpClientTransport(http::client::HttpClient);
127struct HttpServerTransport(http::server::AxumHttpServer);
128
129macro_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);