rust_mcp_transport/
error.rs

1use rust_mcp_schema::{schema_utils::SdkError, RpcError};
2use thiserror::Error;
3
4use crate::utils::CancellationError;
5use core::fmt;
6use std::any::Any;
7use tokio::sync::broadcast;
8
9/// A wrapper around a broadcast send error. This structure allows for generic error handling
10/// by boxing the underlying error into a type-erased form.
11#[derive(Debug)]
12pub struct GenericSendError {
13    inner: Box<dyn Any + Send>,
14}
15
16#[allow(unused)]
17impl GenericSendError {
18    pub fn new<T: Send + 'static>(error: broadcast::error::SendError<T>) -> Self {
19        Self {
20            inner: Box::new(error),
21        }
22    }
23
24    /// Attempts to downcast the wrapped error to a specific `broadcast::error::SendError` type.
25    ///
26    /// # Returns
27    /// `Some(T)` if the error can be downcasted, `None` otherwise.
28    fn downcast<T: Send + 'static>(self) -> Option<broadcast::error::SendError<T>> {
29        self.inner
30            .downcast::<broadcast::error::SendError<T>>()
31            .ok()
32            .map(|boxed| *boxed)
33    }
34}
35
36impl fmt::Display for GenericSendError {
37    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38        write!(f, "Broadcast SendError: Failed to send a message.")
39    }
40}
41// Implementing `Error` trait
42impl std::error::Error for GenericSendError {}
43
44/// A wrapper around a broadcast send error. This structure allows for generic error handling
45/// by boxing the underlying error into a type-erased form.
46#[derive(Debug)]
47pub struct GenericWatchSendError {
48    inner: Box<dyn Any + Send>,
49}
50
51#[allow(unused)]
52impl GenericWatchSendError {
53    pub fn new<T: Send + 'static>(error: tokio::sync::watch::error::SendError<T>) -> Self {
54        Self {
55            inner: Box::new(error),
56        }
57    }
58
59    /// Attempts to downcast the wrapped error to a specific `broadcast::error::SendError` type.
60    ///
61    /// # Returns
62    /// `Some(T)` if the error can be downcasted, `None` otherwise.
63    fn downcast<T: Send + 'static>(self) -> Option<tokio::sync::watch::error::SendError<T>> {
64        self.inner
65            .downcast::<tokio::sync::watch::error::SendError<T>>()
66            .ok()
67            .map(|boxed| *boxed)
68    }
69}
70
71impl fmt::Display for GenericWatchSendError {
72    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
73        write!(f, "Watch SendError: Failed to send a message.")
74    }
75}
76// Implementing `Error` trait
77impl std::error::Error for GenericWatchSendError {}
78
79pub type TransportResult<T> = core::result::Result<T, TransportError>;
80
81#[derive(Debug, Error)]
82pub enum TransportError {
83    #[error("{0}")]
84    InvalidOptions(String),
85    #[error("{0}")]
86    SendError(#[from] GenericSendError),
87    #[error("{0}")]
88    WatchSendError(#[from] GenericWatchSendError),
89    #[error("Send Error: {0}")]
90    StdioError(#[from] std::io::Error),
91    #[error("{0}")]
92    JsonrpcError(#[from] RpcError),
93    #[error("{0}")]
94    SdkError(#[from] SdkError),
95    #[error("Process error{0}")]
96    ProcessError(String),
97    #[error("{0}")]
98    FromString(String),
99    #[error("{0}")]
100    OneshotRecvError(#[from] tokio::sync::oneshot::error::RecvError),
101    #[cfg(feature = "sse")]
102    #[error("{0}")]
103    SendMessageError(#[from] reqwest::Error),
104    #[error("Http Error: {0}")]
105    HttpError(u16),
106    #[error("Shutdown timed out")]
107    ShutdownTimeout,
108    #[error("Cancellation error : {0}")]
109    CancellationError(#[from] CancellationError),
110}