mcp_core/transport/
mod.rs

1//! # MCP Transport Layer
2//!
3//! This module implements the transport layer for the Model Context Protocol (MCP).
4//! It provides abstractions for sending and receiving JSON-RPC messages between
5//! clients and servers using different transport mechanisms.
6//!
7//! The transport layer:
8//! - Handles serialization and deserialization of messages
9//! - Provides interfaces for sending and receiving messages
10//! - Defines transport-specific implementations (SSE, stdio)
11//! - Abstracts the underlying communication protocol
12//!
13//! The core component is the `Transport` trait, which defines the operations that
14//! any MCP transport must support, regardless of the underlying mechanism.
15
16use std::{future::Future, pin::Pin};
17
18use anyhow::Result;
19use async_trait::async_trait;
20use serde::{Deserialize, Serialize};
21
22mod client;
23pub use client::*;
24
25mod server;
26pub use server::*;
27
28use crate::protocol::RequestOptions;
29
30/// A message in the MCP protocol.
31///
32/// Currently, only JSON-RPC messages are supported, as defined in the
33/// [MCP specification](https://spec.modelcontextprotocol.io/specification/basic/messages/).
34pub type Message = JsonRpcMessage;
35
36/// Core trait that defines operations for MCP transports.
37///
38/// This trait abstracts the transport layer, allowing the protocol to work
39/// with different communication mechanisms (SSE, stdio, etc.).
40#[async_trait()]
41pub trait Transport: Send + Sync + 'static {
42    /// Opens the transport connection.
43    ///
44    /// This initializes the transport and prepares it for communication.
45    ///
46    /// # Returns
47    ///
48    /// A `Result` indicating success or failure
49    async fn open(&self) -> Result<()>;
50
51    /// Closes the transport connection.
52    ///
53    /// This terminates the transport and releases any resources.
54    ///
55    /// # Returns
56    ///
57    /// A `Result` indicating success or failure
58    async fn close(&self) -> Result<()>;
59
60    /// Polls for incoming messages.
61    ///
62    /// This checks for any new messages from the other endpoint.
63    ///
64    /// # Returns
65    ///
66    /// A `Result` containing an `Option<Message>` if a message is available
67    async fn poll_message(&self) -> Result<Option<Message>>;
68
69    /// Sends a request and waits for the response.
70    ///
71    /// # Arguments
72    ///
73    /// * `method` - The method name for the request
74    /// * `params` - Optional parameters for the request
75    /// * `options` - Request options (like timeout)
76    ///
77    /// # Returns
78    ///
79    /// A `Future` that resolves to a `Result` containing the response
80    fn request(
81        &self,
82        method: &str,
83        params: Option<serde_json::Value>,
84        options: RequestOptions,
85    ) -> Pin<Box<dyn Future<Output = Result<JsonRpcResponse>> + Send + Sync>>;
86
87    /// Sends a notification.
88    ///
89    /// Unlike requests, notifications do not expect a response.
90    ///
91    /// # Arguments
92    ///
93    /// * `method` - The method name for the notification
94    /// * `params` - Optional parameters for the notification
95    ///
96    /// # Returns
97    ///
98    /// A `Result` indicating success or failure
99    async fn send_notification(
100        &self,
101        method: &str,
102        params: Option<serde_json::Value>,
103    ) -> Result<()>;
104
105    /// Sends a response to a request.
106    ///
107    /// # Arguments
108    ///
109    /// * `id` - The ID of the request being responded to
110    /// * `result` - Optional successful result
111    /// * `error` - Optional error information
112    ///
113    /// # Returns
114    ///
115    /// A `Result` indicating success or failure
116    async fn send_response(
117        &self,
118        id: RequestId,
119        result: Option<serde_json::Value>,
120        error: Option<JsonRpcError>,
121    ) -> Result<()>;
122}
123
124/// Type representing a JSON-RPC request ID.
125///
126/// Request IDs are used to match responses to their corresponding requests.
127pub type RequestId = u64;
128
129/// Represents a JSON-RPC protocol version.
130///
131/// The JSON-RPC version is included in all JSON-RPC messages and
132/// is typically "2.0" for the current version of the protocol.
133#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
134#[serde(transparent)]
135pub struct JsonRpcVersion(String);
136
137impl Default for JsonRpcVersion {
138    /// Creates a default JSON-RPC version (2.0).
139    ///
140    /// # Returns
141    ///
142    /// A new `JsonRpcVersion` with value "2.0"
143    fn default() -> Self {
144        JsonRpcVersion("2.0".to_owned())
145    }
146}
147
148impl JsonRpcVersion {
149    /// Returns the version as a string slice.
150    ///
151    /// # Returns
152    ///
153    /// A string slice containing the version
154    pub fn as_str(&self) -> &str {
155        &self.0
156    }
157}
158
159/// Represents a JSON-RPC message.
160///
161/// This enum can be a request, a response, or a notification.
162#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
163#[serde(deny_unknown_fields)]
164#[serde(untagged)]
165pub enum JsonRpcMessage {
166    /// A response to a request
167    Response(JsonRpcResponse),
168    /// A request that expects a response
169    Request(JsonRpcRequest),
170    /// A notification that does not expect a response
171    Notification(JsonRpcNotification),
172}
173
174/// Represents a JSON-RPC request.
175///
176/// A request is a message that expects a response with the same ID.
177#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
178#[serde(deny_unknown_fields)]
179pub struct JsonRpcRequest {
180    /// The request ID, used to match with the response
181    pub id: RequestId,
182    /// The method name to call
183    pub method: String,
184    /// Optional parameters for the method
185    #[serde(skip_serializing_if = "Option::is_none")]
186    pub params: Option<serde_json::Value>,
187    /// The JSON-RPC version
188    pub jsonrpc: JsonRpcVersion,
189}
190
191/// Represents a JSON-RPC notification.
192///
193/// A notification is a message that does not expect a response.
194#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
195#[serde(rename_all = "camelCase")]
196#[serde(deny_unknown_fields)]
197#[serde(default)]
198pub struct JsonRpcNotification {
199    /// The method name for the notification
200    pub method: String,
201    /// Optional parameters for the notification
202    #[serde(skip_serializing_if = "Option::is_none")]
203    pub params: Option<serde_json::Value>,
204    /// The JSON-RPC version
205    pub jsonrpc: JsonRpcVersion,
206}
207
208/// Represents a JSON-RPC response.
209///
210/// A response is a message sent in reply to a request with the same ID.
211#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
212#[serde(deny_unknown_fields)]
213#[serde(rename_all = "camelCase")]
214#[serde(default)]
215pub struct JsonRpcResponse {
216    /// The request ID this response corresponds to
217    pub id: RequestId,
218    /// The result of the request, if successful
219    #[serde(skip_serializing_if = "Option::is_none")]
220    pub result: Option<serde_json::Value>,
221    /// The error, if the request failed
222    #[serde(skip_serializing_if = "Option::is_none")]
223    pub error: Option<JsonRpcError>,
224    /// The JSON-RPC version
225    pub jsonrpc: JsonRpcVersion,
226}
227
228/// Represents a JSON-RPC error.
229///
230/// An error is included in a response when the request fails.
231#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
232#[serde(rename_all = "camelCase")]
233#[serde(default)]
234pub struct JsonRpcError {
235    /// Error code
236    pub code: i32,
237    /// Error message
238    pub message: String,
239    /// Optional additional error data
240    #[serde(skip_serializing_if = "Option::is_none")]
241    pub data: Option<serde_json::Value>,
242}