Skip to main content

mcp_kit/
error.rs

1use serde::{Deserialize, Serialize};
2use thiserror::Error;
3
4pub type McpResult<T> = Result<T, McpError>;
5
6/// MCP protocol error codes (JSON-RPC 2.0 + MCP extensions)
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub enum ErrorCode {
9    // JSON-RPC 2.0 standard codes
10    ParseError = -32700,
11    InvalidRequest = -32600,
12    MethodNotFound = -32601,
13    InvalidParams = -32602,
14    InternalError = -32603,
15
16    // MCP-specific codes
17    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/// Main error type for the MCP library
32#[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/// JSON-serializable error data
111#[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}