1use serde::{Deserialize, Serialize};
2use thiserror::Error;
3
4pub type McpResult<T> = Result<T, McpError>;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub enum ErrorCode {
9 ParseError = -32700,
11 InvalidRequest = -32600,
12 MethodNotFound = -32601,
13 InvalidParams = -32602,
14 InternalError = -32603,
15
16 ConnectionClosed = -32000,
18 RequestTimeout = -32001,
19 ResourceNotFound = -32002,
20 ToolNotFound = -32003,
21 PromptNotFound = -32004,
22 Unauthorized = -32005,
23}
24
25impl ErrorCode {
26 pub fn code(self) -> i64 {
27 self as i64
28 }
29}
30
31#[derive(Debug, Error)]
33pub enum McpError {
34 #[error("Parse error: {0}")]
35 ParseError(String),
36
37 #[error("Invalid request: {0}")]
38 InvalidRequest(String),
39
40 #[error("Method not found: {0}")]
41 MethodNotFound(String),
42
43 #[error("Invalid params: {0}")]
44 InvalidParams(String),
45
46 #[error("Internal error: {0}")]
47 InternalError(String),
48
49 #[error("Resource not found: {0}")]
50 ResourceNotFound(String),
51
52 #[error("Tool not found: {0}")]
53 ToolNotFound(String),
54
55 #[error("Prompt not found: {0}")]
56 PromptNotFound(String),
57
58 #[error("Transport error: {0}")]
59 Transport(String),
60
61 #[error("IO error: {0}")]
62 Io(#[from] std::io::Error),
63
64 #[error("JSON serialization error: {0}")]
65 Json(#[from] serde_json::Error),
66
67 #[error("Unauthorized: {0}")]
68 Unauthorized(String),
69
70 #[error("Connection closed")]
71 ConnectionClosed,
72
73 #[error("Request timeout")]
74 Timeout,
75
76 #[error("{0}")]
77 Other(String),
78}
79
80impl McpError {
81 pub fn code(&self) -> i64 {
82 match self {
83 Self::ParseError(_) => ErrorCode::ParseError.code(),
84 Self::InvalidRequest(_) => ErrorCode::InvalidRequest.code(),
85 Self::MethodNotFound(_) => ErrorCode::MethodNotFound.code(),
86 Self::InvalidParams(_) => ErrorCode::InvalidParams.code(),
87 Self::ResourceNotFound(_) => ErrorCode::ResourceNotFound.code(),
88 Self::ToolNotFound(_) => ErrorCode::ToolNotFound.code(),
89 Self::PromptNotFound(_) => ErrorCode::PromptNotFound.code(),
90 Self::Unauthorized(_) => ErrorCode::Unauthorized.code(),
91 Self::ConnectionClosed => ErrorCode::ConnectionClosed.code(),
92 Self::Timeout => ErrorCode::RequestTimeout.code(),
93 _ => ErrorCode::InternalError.code(),
94 }
95 }
96
97 pub fn message(&self) -> String {
98 self.to_string()
99 }
100
101 pub fn invalid_params(msg: impl Into<String>) -> Self {
102 Self::InvalidParams(msg.into())
103 }
104
105 pub fn internal(msg: impl Into<String>) -> Self {
106 Self::InternalError(msg.into())
107 }
108}
109
110#[derive(Debug, Clone, Serialize, Deserialize)]
112pub struct ErrorData {
113 pub code: i64,
114 pub message: String,
115 #[serde(skip_serializing_if = "Option::is_none")]
116 pub data: Option<serde_json::Value>,
117}
118
119impl From<&McpError> for ErrorData {
120 fn from(err: &McpError) -> Self {
121 Self {
122 code: err.code(),
123 message: err.message(),
124 data: None,
125 }
126 }
127}
128
129impl From<McpError> for ErrorData {
130 fn from(err: McpError) -> Self {
131 Self::from(&err)
132 }
133}