mcprotocol_rs/protocol/
message.rs

1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3use std::fmt;
4
5use super::{ClientCapabilities, ImplementationInfo, RequestId, ServerCapabilities};
6use crate::Result;
7
8/// Base JSON-RPC message
9#[derive(Debug, Clone, Serialize, Deserialize)]
10#[serde(untagged)]
11pub enum Message {
12    Request(Request),
13    Response(Response),
14    Notification(Notification),
15}
16
17/// JSON-RPC request message
18#[derive(Debug, Clone, Serialize, Deserialize)]
19pub struct Request {
20    /// Protocol version (must be "2.0")
21    pub jsonrpc: String,
22    /// Request method
23    pub method: String,
24    /// Optional parameters
25    #[serde(skip_serializing_if = "Option::is_none")]
26    pub params: Option<Value>,
27    /// Request ID
28    pub id: RequestId,
29}
30
31/// JSON-RPC response message
32#[derive(Debug, Clone, Serialize, Deserialize)]
33pub struct Response {
34    /// Protocol version (must be "2.0")
35    pub jsonrpc: String,
36    /// Request ID
37    pub id: RequestId,
38    /// Response result
39    #[serde(skip_serializing_if = "Option::is_none")]
40    pub result: Option<Value>,
41    /// Error if any
42    #[serde(skip_serializing_if = "Option::is_none")]
43    pub error: Option<ResponseError>,
44}
45
46/// JSON-RPC notification message (request without ID)
47#[derive(Debug, Clone, Serialize, Deserialize)]
48pub struct Notification {
49    /// Protocol version (must be "2.0")
50    pub jsonrpc: String,
51    /// Notification method
52    pub method: String,
53    /// Optional parameters
54    #[serde(skip_serializing_if = "Option::is_none")]
55    pub params: Option<Value>,
56}
57
58/// Error response
59#[derive(Debug, Clone, Serialize, Deserialize)]
60pub struct ResponseError {
61    /// Error code
62    pub code: i32,
63    /// Error message
64    pub message: String,
65    /// Additional error data
66    #[serde(skip_serializing_if = "Option::is_none")]
67    pub data: Option<Value>,
68}
69
70/// Standard error codes
71pub mod error_codes {
72    pub const PARSE_ERROR: i32 = -32700;
73    pub const INVALID_REQUEST: i32 = -32600;
74    pub const METHOD_NOT_FOUND: i32 = -32601;
75    pub const INVALID_PARAMS: i32 = -32602;
76    pub const INTERNAL_ERROR: i32 = -32603;
77    pub const SERVER_NOT_INITIALIZED: i32 = -32002;
78    pub const UNKNOWN_ERROR_CODE: i32 = -32001;
79    pub const REQUEST_CANCELLED: i32 = -32800;
80}
81
82/// MCP method types
83#[derive(Debug, Clone, Serialize, Deserialize)]
84#[serde(rename_all = "camelCase")]
85pub enum Method {
86    // Lifecycle methods
87    Initialize,
88    Initialized,
89    Shutdown,
90    Exit,
91
92    // Utility methods
93    #[serde(rename = "$/cancelRequest")]
94    Cancel,
95    #[serde(rename = "$/ping")]
96    Ping,
97    #[serde(rename = "$/pong")]
98    Pong,
99    #[serde(rename = "$/progress")]
100    Progress,
101
102    // Server feature methods
103    #[serde(rename = "prompts/list")]
104    ListPrompts,
105    #[serde(rename = "prompts/get")]
106    GetPrompt,
107    #[serde(rename = "prompts/execute")]
108    ExecutePrompt,
109
110    #[serde(rename = "resources/list")]
111    ListResources,
112    #[serde(rename = "resources/get")]
113    GetResource,
114    #[serde(rename = "resources/create")]
115    CreateResource,
116    #[serde(rename = "resources/update")]
117    UpdateResource,
118    #[serde(rename = "resources/delete")]
119    DeleteResource,
120    #[serde(rename = "resources/subscribe")]
121    SubscribeResource,
122    #[serde(rename = "resources/unsubscribe")]
123    UnsubscribeResource,
124
125    #[serde(rename = "tools/list")]
126    ListTools,
127    #[serde(rename = "tools/get")]
128    GetTool,
129    #[serde(rename = "tools/execute")]
130    ExecuteTool,
131    #[serde(rename = "tools/cancel")]
132    CancelTool,
133
134    // Client feature methods
135    #[serde(rename = "roots/list")]
136    ListRoots,
137    #[serde(rename = "roots/get")]
138    GetRoot,
139
140    #[serde(rename = "sampling/request")]
141    SamplingRequest,
142}
143
144impl Request {
145    /// Creates a new request
146    pub fn new(method: Method, params: Option<Value>, id: RequestId) -> Self {
147        Self {
148            jsonrpc: super::PROTOCOL_VERSION.to_string(),
149            method: method.to_string(),
150            params,
151            id,
152        }
153    }
154}
155
156impl Response {
157    /// Creates a new successful response
158    pub fn success(result: Value, id: RequestId) -> Self {
159        Self {
160            jsonrpc: super::PROTOCOL_VERSION.to_string(),
161            result: Some(result),
162            error: None,
163            id,
164        }
165    }
166
167    /// Creates a new error response
168    pub fn error(error: ResponseError, id: RequestId) -> Self {
169        Self {
170            jsonrpc: super::PROTOCOL_VERSION.to_string(),
171            result: None,
172            error: Some(error),
173            id,
174        }
175    }
176}
177
178impl Notification {
179    /// Creates a new notification
180    pub fn new(method: Method, params: Option<Value>) -> Self {
181        Self {
182            jsonrpc: super::PROTOCOL_VERSION.to_string(),
183            method: method.to_string(),
184            params,
185        }
186    }
187}
188
189impl fmt::Display for Method {
190    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
191        match self {
192            Method::Initialize => write!(f, "initialize"),
193            Method::Initialized => write!(f, "initialized"),
194            Method::Shutdown => write!(f, "shutdown"),
195            Method::Exit => write!(f, "exit"),
196            Method::Cancel => write!(f, "$/cancelRequest"),
197            Method::Ping => write!(f, "$/ping"),
198            Method::Pong => write!(f, "$/pong"),
199            Method::Progress => write!(f, "$/progress"),
200            Method::ListPrompts => write!(f, "prompts/list"),
201            Method::GetPrompt => write!(f, "prompts/get"),
202            Method::ExecutePrompt => write!(f, "prompts/execute"),
203            Method::ListResources => write!(f, "resources/list"),
204            Method::GetResource => write!(f, "resources/get"),
205            Method::CreateResource => write!(f, "resources/create"),
206            Method::UpdateResource => write!(f, "resources/update"),
207            Method::DeleteResource => write!(f, "resources/delete"),
208            Method::SubscribeResource => write!(f, "resources/subscribe"),
209            Method::UnsubscribeResource => write!(f, "resources/unsubscribe"),
210            Method::ListTools => write!(f, "tools/list"),
211            Method::GetTool => write!(f, "tools/get"),
212            Method::ExecuteTool => write!(f, "tools/execute"),
213            Method::CancelTool => write!(f, "tools/cancel"),
214            Method::ListRoots => write!(f, "roots/list"),
215            Method::GetRoot => write!(f, "roots/get"),
216            Method::SamplingRequest => write!(f, "sampling/request"),
217        }
218    }
219}