mcpkit_core/error/
details.rs

1//! Boxed error detail types to reduce `McpError` enum size.
2//!
3//! These types contain detailed information about specific error categories
4//! and are boxed within `McpError` variants to keep the enum size small.
5
6use std::fmt;
7
8use super::transport::{TransportContext, TransportErrorKind};
9
10/// Type alias for boxed errors that are Send + Sync.
11pub type BoxError = Box<dyn std::error::Error + Send + Sync + 'static>;
12
13/// Details for invalid params errors (boxed to reduce enum size).
14#[derive(Debug)]
15pub struct InvalidParamsDetails {
16    /// The method that received invalid parameters.
17    pub method: String,
18    /// Human-readable error message.
19    pub message: String,
20    /// The parameter path that failed (e.g., "arguments.query").
21    pub param_path: Option<String>,
22    /// The expected type or format.
23    pub expected: Option<String>,
24    /// The actual value received (truncated/redacted if needed).
25    pub actual: Option<String>,
26    /// The underlying error, if available.
27    pub source: Option<BoxError>,
28}
29
30impl fmt::Display for InvalidParamsDetails {
31    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32        write!(f, "Invalid params for '{}': {}", self.method, self.message)
33    }
34}
35
36impl std::error::Error for InvalidParamsDetails {
37    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
38        self.source
39            .as_ref()
40            .map(|e| e.as_ref() as &(dyn std::error::Error + 'static))
41    }
42}
43
44/// Details for transport errors (boxed to reduce enum size).
45#[derive(Debug)]
46pub struct TransportDetails {
47    /// Classification of the transport error.
48    pub kind: TransportErrorKind,
49    /// Human-readable error message.
50    pub message: String,
51    /// Transport-specific context for debugging.
52    pub context: TransportContext,
53    /// The underlying error, if available.
54    pub source: Option<BoxError>,
55}
56
57impl fmt::Display for TransportDetails {
58    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59        write!(f, "Transport error ({}): {}", self.kind, self.message)
60    }
61}
62
63impl std::error::Error for TransportDetails {
64    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
65        self.source
66            .as_ref()
67            .map(|e| e.as_ref() as &(dyn std::error::Error + 'static))
68    }
69}
70
71/// Details for tool execution errors (boxed to reduce enum size).
72#[derive(Debug)]
73pub struct ToolExecutionDetails {
74    /// The name of the tool that failed.
75    pub tool: String,
76    /// Human-readable error message.
77    pub message: String,
78    /// Whether the LLM should see this error for self-correction.
79    pub is_recoverable: bool,
80    /// Additional structured error data.
81    pub data: Option<serde_json::Value>,
82    /// The underlying error, if available.
83    pub source: Option<BoxError>,
84}
85
86impl fmt::Display for ToolExecutionDetails {
87    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
88        write!(f, "Tool '{}' failed: {}", self.tool, self.message)
89    }
90}
91
92impl std::error::Error for ToolExecutionDetails {
93    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
94        self.source
95            .as_ref()
96            .map(|e| e.as_ref() as &(dyn std::error::Error + 'static))
97    }
98}
99
100/// Details for handshake errors (boxed to reduce enum size).
101#[derive(Debug)]
102pub struct HandshakeDetails {
103    /// Human-readable error message.
104    pub message: String,
105    /// Client protocol version, if available.
106    pub client_version: Option<String>,
107    /// Server protocol version, if available.
108    pub server_version: Option<String>,
109    /// The underlying error, if available.
110    pub source: Option<BoxError>,
111}
112
113impl fmt::Display for HandshakeDetails {
114    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
115        write!(f, "Handshake failed: {}", self.message)
116    }
117}
118
119impl std::error::Error for HandshakeDetails {
120    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
121        self.source
122            .as_ref()
123            .map(|e| e.as_ref() as &(dyn std::error::Error + 'static))
124    }
125}