airsprotocols_mcp/protocol/
errors.rs1use serde::{Deserialize, Serialize};
28use thiserror::Error;
29
30use crate::protocol::transport::TransportError;
32#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Error)]
40pub enum ProtocolError {
41 #[error("JSON-RPC error: {message}")]
43 JsonRpc { message: String },
44
45 #[error("MCP protocol error: {message}")]
47 Mcp { message: String },
48
49 #[error("Transport error: {message}")]
51 Transport { message: String },
52
53 #[error("Serialization error: {message}")]
55 Serialization { message: String },
56
57 #[error("Invalid message: {message}")]
59 InvalidMessage { message: String },
60
61 #[error("Invalid base64 data")]
63 InvalidBase64Data,
64
65 #[error("Invalid protocol version: {0}")]
67 InvalidProtocolVersion(String),
68
69 #[error("Invalid URI: {0}")]
71 InvalidUri(String),
72
73 #[error("Invalid MIME type: {0}")]
75 InvalidMimeType(String),
76}
77
78pub type ProtocolResult<T> = Result<T, ProtocolError>;
80
81impl From<serde_json::Error> for ProtocolError {
82 fn from(err: serde_json::Error) -> Self {
83 Self::Serialization {
84 message: err.to_string(),
85 }
86 }
87}
88
89impl From<TransportError> for ProtocolError {
90 fn from(err: TransportError) -> Self {
91 Self::Transport {
92 message: err.to_string(),
93 }
94 }
95}
96
97#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Error)]
100pub enum JsonRpcError {
101 #[error("Parse error: {message}")]
103 ParseError { message: String },
104
105 #[error("Invalid request: {message}")]
107 InvalidRequest { message: String },
108
109 #[error("Method not found: {method}")]
111 MethodNotFound { method: String },
112
113 #[error("Invalid parameters: {message}")]
115 InvalidParams { message: String },
116
117 #[error("Internal error: {message}")]
119 InternalError { message: String },
120
121 #[error("Server error {code}: {message}")]
123 ServerError { code: i32, message: String },
124}
125
126#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Error)]
129pub enum McpError {
130 #[error("Protocol version mismatch: expected {expected}, got {actual}")]
132 VersionMismatch { expected: String, actual: String },
133
134 #[error("Unsupported capability: {capability}")]
136 UnsupportedCapability { capability: String },
137
138 #[error("Resource not found: {uri}")]
140 ResourceNotFound { uri: String },
141
142 #[error("Authorization failed: {reason}")]
144 AuthorizationFailed { reason: String },
145
146 #[error("Invalid URI: {uri} - {reason}")]
148 InvalidUri { uri: String, reason: String },
149
150 #[error("Request timeout after {timeout_ms}ms")]
152 RequestTimeout { timeout_ms: u64 },
153}
154
155impl JsonRpcError {
157 pub const PARSE_ERROR: i32 = -32700;
159 pub const INVALID_REQUEST: i32 = -32600;
160 pub const METHOD_NOT_FOUND: i32 = -32601;
161 pub const INVALID_PARAMS: i32 = -32602;
162 pub const INTERNAL_ERROR: i32 = -32603;
163
164 pub fn error_code(&self) -> i32 {
166 match self {
167 JsonRpcError::ParseError { .. } => Self::PARSE_ERROR,
168 JsonRpcError::InvalidRequest { .. } => Self::INVALID_REQUEST,
169 JsonRpcError::MethodNotFound { .. } => Self::METHOD_NOT_FOUND,
170 JsonRpcError::InvalidParams { .. } => Self::INVALID_PARAMS,
171 JsonRpcError::InternalError { .. } => Self::INTERNAL_ERROR,
172 JsonRpcError::ServerError { code, .. } => *code,
173 }
174 }
175
176 pub fn parse_error(message: impl Into<String>) -> Self {
178 Self::ParseError {
179 message: message.into(),
180 }
181 }
182
183 pub fn invalid_request(message: impl Into<String>) -> Self {
185 Self::InvalidRequest {
186 message: message.into(),
187 }
188 }
189
190 pub fn method_not_found(method: impl Into<String>) -> Self {
192 Self::MethodNotFound {
193 method: method.into(),
194 }
195 }
196
197 pub fn invalid_params(message: impl Into<String>) -> Self {
199 Self::InvalidParams {
200 message: message.into(),
201 }
202 }
203
204 pub fn internal_error(message: impl Into<String>) -> Self {
206 Self::InternalError {
207 message: message.into(),
208 }
209 }
210
211 pub fn server_error(code: i32, message: impl Into<String>) -> Self {
213 Self::ServerError {
214 code,
215 message: message.into(),
216 }
217 }
218}
219
220impl ProtocolError {
222 pub fn jsonrpc(message: impl Into<String>) -> Self {
224 Self::JsonRpc {
225 message: message.into(),
226 }
227 }
228
229 pub fn mcp(message: impl Into<String>) -> Self {
231 Self::Mcp {
232 message: message.into(),
233 }
234 }
235
236 pub fn transport(message: impl Into<String>) -> Self {
238 Self::Transport {
239 message: message.into(),
240 }
241 }
242
243 pub fn invalid_message(message: impl Into<String>) -> Self {
245 Self::InvalidMessage {
246 message: message.into(),
247 }
248 }
249}
250
251impl McpError {
253 pub fn version_mismatch(expected: impl Into<String>, actual: impl Into<String>) -> Self {
255 Self::VersionMismatch {
256 expected: expected.into(),
257 actual: actual.into(),
258 }
259 }
260
261 pub fn unsupported_capability(capability: impl Into<String>) -> Self {
263 Self::UnsupportedCapability {
264 capability: capability.into(),
265 }
266 }
267
268 pub fn resource_not_found(uri: impl Into<String>) -> Self {
270 Self::ResourceNotFound { uri: uri.into() }
271 }
272
273 pub fn authorization_failed(reason: impl Into<String>) -> Self {
275 Self::AuthorizationFailed {
276 reason: reason.into(),
277 }
278 }
279
280 pub fn invalid_uri(uri: impl Into<String>, reason: impl Into<String>) -> Self {
282 Self::InvalidUri {
283 uri: uri.into(),
284 reason: reason.into(),
285 }
286 }
287
288 pub fn request_timeout(timeout_ms: u64) -> Self {
290 Self::RequestTimeout { timeout_ms }
291 }
292}