pulseengine_mcp_transport/
lib.rs

1//! Transport layer implementations for MCP servers
2//!
3//! This crate provides multiple transport options for MCP servers:
4//! stdio (Claude Desktop), HTTP (web clients), and WebSocket (real-time).
5//!
6//! # Quick Start
7//!
8//! ```rust,ignore
9//! use pulseengine_mcp_transport::{TransportConfig, create_transport};
10//! use pulseengine_mcp_protocol::{Request, Response};
11//!
12//! // Create HTTP transport
13//! let config = TransportConfig::Http { port: 3001 };
14//! let mut transport = create_transport(config).unwrap();
15//!
16//! // Define request handler
17//! let handler = Box::new(|request: Request| {
18//!     Box::pin(async move {
19//!         Response {
20//!             jsonrpc: "2.0".to_string(),
21//!             id: request.id.clone(),
22//!             result: Some(serde_json::json!({"result": "handled"})),
23//!             error: None,
24//!         }
25//!     })
26//! });
27//!
28//! // Start transport (in real code)
29//! // transport.start(handler).await.unwrap();
30//! ```
31
32pub mod batch;
33pub mod config;
34pub mod http;
35pub mod stdio;
36pub mod streamable_http;
37pub mod validation;
38pub mod websocket;
39
40#[cfg(test)]
41mod batch_tests;
42#[cfg(test)]
43mod config_tests;
44#[cfg(test)]
45mod http_test;
46#[cfg(test)]
47mod http_tests;
48#[cfg(test)]
49mod lib_tests;
50#[cfg(test)]
51mod stdio_tests;
52#[cfg(test)]
53mod streamable_http_tests;
54#[cfg(test)]
55mod validation_tests;
56#[cfg(test)]
57mod websocket_tests;
58
59use async_trait::async_trait;
60use pulseengine_mcp_protocol::{Request, Response};
61// std::error::Error not needed with thiserror
62use thiserror::Error as ThisError;
63
64pub use config::TransportConfig;
65
66#[derive(Debug, ThisError)]
67pub enum TransportError {
68    #[error("Transport configuration error: {0}")]
69    Config(String),
70
71    #[error("Connection error: {0}")]
72    Connection(String),
73
74    #[error("Protocol error: {0}")]
75    Protocol(String),
76}
77
78/// Request handler function type
79pub type RequestHandler = Box<
80    dyn Fn(Request) -> std::pin::Pin<Box<dyn std::future::Future<Output = Response> + Send>>
81        + Send
82        + Sync,
83>;
84
85/// Transport layer trait
86#[async_trait]
87pub trait Transport: Send + Sync {
88    async fn start(&mut self, handler: RequestHandler) -> std::result::Result<(), TransportError>;
89    async fn stop(&mut self) -> std::result::Result<(), TransportError>;
90    async fn health_check(&self) -> std::result::Result<(), TransportError>;
91}
92
93/// Create a transport from configuration
94pub fn create_transport(
95    config: TransportConfig,
96) -> std::result::Result<Box<dyn Transport>, TransportError> {
97    match config {
98        TransportConfig::Stdio => Ok(Box::new(stdio::StdioTransport::new())),
99        TransportConfig::Http { port, .. } => Ok(Box::new(http::HttpTransport::new(port))),
100        TransportConfig::StreamableHttp { port, .. } => Ok(Box::new(
101            streamable_http::StreamableHttpTransport::new(port),
102        )),
103        TransportConfig::WebSocket { port, .. } => {
104            Ok(Box::new(websocket::WebSocketTransport::new(port)))
105        }
106    }
107}