pulseengine_mcp_protocol/
error.rs1use serde::{Deserialize, Serialize};
4use std::fmt;
5
6pub type Result<T> = std::result::Result<T, Error>;
8
9#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, thiserror::Error)]
11pub struct Error {
12 pub code: ErrorCode,
14 pub message: String,
16 #[serde(skip_serializing_if = "Option::is_none")]
18 pub data: Option<serde_json::Value>,
19}
20
21impl fmt::Display for Error {
22 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23 write!(f, "{}: {}", self.code, self.message)
24 }
25}
26
27impl Error {
28 pub fn new(code: ErrorCode, message: impl Into<String>) -> Self {
30 Self {
31 code,
32 message: message.into(),
33 data: None,
34 }
35 }
36
37 pub fn with_data(code: ErrorCode, message: impl Into<String>, data: serde_json::Value) -> Self {
39 Self {
40 code,
41 message: message.into(),
42 data: Some(data),
43 }
44 }
45
46 pub fn parse_error(message: impl Into<String>) -> Self {
48 Self::new(ErrorCode::ParseError, message)
49 }
50
51 pub fn invalid_request(message: impl Into<String>) -> Self {
53 Self::new(ErrorCode::InvalidRequest, message)
54 }
55
56 pub fn method_not_found(method: impl Into<String>) -> Self {
58 Self::new(
59 ErrorCode::MethodNotFound,
60 format!("Method not found: {}", method.into()),
61 )
62 }
63
64 pub fn invalid_params(message: impl Into<String>) -> Self {
66 Self::new(ErrorCode::InvalidParams, message)
67 }
68
69 pub fn internal_error(message: impl Into<String>) -> Self {
71 Self::new(ErrorCode::InternalError, message)
72 }
73
74 pub fn protocol_version_mismatch(client_version: &str, server_version: &str) -> Self {
76 Self::with_data(
77 ErrorCode::InvalidRequest,
78 format!("Protocol version mismatch: client={client_version}, server={server_version}"),
79 serde_json::json!({
80 "client_version": client_version,
81 "server_version": server_version
82 }),
83 )
84 }
85
86 pub fn unauthorized(message: impl Into<String>) -> Self {
88 Self::new(ErrorCode::Unauthorized, message)
89 }
90
91 pub fn forbidden(message: impl Into<String>) -> Self {
93 Self::new(ErrorCode::Forbidden, message)
94 }
95
96 pub fn resource_not_found(resource: impl Into<String>) -> Self {
98 Self::new(
99 ErrorCode::ResourceNotFound,
100 format!("Resource not found: {}", resource.into()),
101 )
102 }
103
104 pub fn tool_not_found(tool: impl Into<String>) -> Self {
106 Self::new(
107 ErrorCode::ToolNotFound,
108 format!("Tool not found: {}", tool.into()),
109 )
110 }
111
112 pub fn validation_error(message: impl Into<String>) -> Self {
114 Self::new(ErrorCode::ValidationError, message)
115 }
116
117 pub fn rate_limit_exceeded(message: impl Into<String>) -> Self {
119 Self::new(ErrorCode::RateLimitExceeded, message)
120 }
121}
122
123#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
125pub enum ErrorCode {
126 #[serde(rename = "-32700")]
128 ParseError = -32700,
129 #[serde(rename = "-32600")]
130 InvalidRequest = -32600,
131 #[serde(rename = "-32601")]
132 MethodNotFound = -32601,
133 #[serde(rename = "-32602")]
134 InvalidParams = -32602,
135 #[serde(rename = "-32603")]
136 InternalError = -32603,
137
138 #[serde(rename = "-32000")]
140 Unauthorized = -32000,
141 #[serde(rename = "-32001")]
142 Forbidden = -32001,
143 #[serde(rename = "-32002")]
144 ResourceNotFound = -32002,
145 #[serde(rename = "-32003")]
146 ToolNotFound = -32003,
147 #[serde(rename = "-32004")]
148 ValidationError = -32004,
149 #[serde(rename = "-32005")]
150 RateLimitExceeded = -32005,
151}
152
153impl fmt::Display for ErrorCode {
154 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
155 let name = match self {
156 ErrorCode::ParseError => "ParseError",
157 ErrorCode::InvalidRequest => "InvalidRequest",
158 ErrorCode::MethodNotFound => "MethodNotFound",
159 ErrorCode::InvalidParams => "InvalidParams",
160 ErrorCode::InternalError => "InternalError",
161 ErrorCode::Unauthorized => "Unauthorized",
162 ErrorCode::Forbidden => "Forbidden",
163 ErrorCode::ResourceNotFound => "ResourceNotFound",
164 ErrorCode::ToolNotFound => "ToolNotFound",
165 ErrorCode::ValidationError => "ValidationError",
166 ErrorCode::RateLimitExceeded => "RateLimitExceeded",
167 };
168 write!(f, "{name}")
169 }
170}
171
172impl From<serde_json::Error> for Error {
174 fn from(err: serde_json::Error) -> Self {
175 Error::parse_error(err.to_string())
176 }
177}
178
179impl From<uuid::Error> for Error {
180 fn from(err: uuid::Error) -> Self {
181 Error::validation_error(format!("Invalid UUID: {err}"))
182 }
183}
184
185impl From<validator::ValidationErrors> for Error {
186 fn from(err: validator::ValidationErrors) -> Self {
187 Error::validation_error(err.to_string())
188 }
189}