1use rmcp::model::ErrorCode;
2
3use crate::proto;
4
5pub const STARTUP_DISABLED_ERROR_CODE: i32 = -32_010;
6
7#[derive(Debug, Clone)]
8pub struct PluginError {
9 pub code: i32,
10 pub message: String,
11 pub data_json: String,
12}
13
14impl PluginError {
15 pub fn invalid_request(message: impl Into<String>) -> Self {
16 Self {
17 code: ErrorCode::INVALID_REQUEST.0,
18 message: message.into(),
19 data_json: String::new(),
20 }
21 }
22
23 pub fn method_not_found(message: impl Into<String>) -> Self {
24 Self {
25 code: ErrorCode::METHOD_NOT_FOUND.0,
26 message: message.into(),
27 data_json: String::new(),
28 }
29 }
30
31 pub fn invalid_params(message: impl Into<String>) -> Self {
32 Self {
33 code: ErrorCode::INVALID_PARAMS.0,
34 message: message.into(),
35 data_json: String::new(),
36 }
37 }
38
39 pub fn internal(message: impl Into<String>) -> Self {
40 Self {
41 code: ErrorCode::INTERNAL_ERROR.0,
42 message: message.into(),
43 data_json: String::new(),
44 }
45 }
46
47 pub fn startup_disabled(message: impl Into<String>) -> Self {
48 Self {
49 code: STARTUP_DISABLED_ERROR_CODE,
50 message: message.into(),
51 data_json: serde_json::json!({ "status": "disabled" }).to_string(),
52 }
53 }
54
55 pub(crate) fn into_error_response(self) -> proto::ErrorResponse {
56 proto::ErrorResponse {
57 code: self.code,
58 message: self.message,
59 data_json: self.data_json,
60 }
61 }
62}
63
64impl std::fmt::Display for PluginError {
65 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
66 write!(f, "{}", self.message)
67 }
68}
69
70impl std::error::Error for PluginError {}
71
72impl From<anyhow::Error> for PluginError {
73 fn from(value: anyhow::Error) -> Self {
74 Self::internal(value.to_string())
75 }
76}
77
78pub type PluginResult<T> = std::result::Result<T, PluginError>;
79pub type PluginRpcResult = PluginResult<proto::envelope::Payload>;