rust_mcp_transport/
error.rs

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