rust_mcp_transport/
error.rs

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