mcp_ectors/messages/mcp/
protocol.rs

1
2use mcp_spec::protocol::{ErrorData, JsonRpcError, JsonRpcMessage, JsonRpcNotification, JsonRpcRequest, JsonRpcResponse};
3use serde::{Deserialize, Serialize};
4use serde_json::Value;
5
6
7
8
9
10
11#[derive(Debug, Serialize, Deserialize)]
12struct JsonRpcRaw {
13    jsonrpc: String,
14    #[serde(skip_serializing_if = "Option::is_none")]
15    id: Option<u64>,
16    #[serde(skip_serializing_if = "Option::is_none")]
17    method: Option<String>,
18    #[serde(skip_serializing_if = "Option::is_none")]
19    params: Option<Value>,
20    #[serde(skip_serializing_if = "Option::is_none")]
21    result: Option<Value>,
22    #[serde(skip_serializing_if = "Option::is_none")]
23    error: Option<ErrorData>,
24}
25    
26
27impl TryFrom<JsonRpcRaw> for JsonRpcMessage {
28    type Error = String;
29
30    fn try_from(raw: JsonRpcRaw) -> Result<Self, <Self as TryFrom<JsonRpcRaw>>::Error> {
31        // If it has an error field, it's an error response
32        if raw.error.is_some() {
33            return Ok(JsonRpcMessage::Error(JsonRpcError {
34                jsonrpc: raw.jsonrpc,
35                id: raw.id,
36                error: raw.error.unwrap(),
37            }));
38        }
39
40        // If it has a result field, it's a response
41        if raw.result.is_some() {
42            return Ok(JsonRpcMessage::Response(JsonRpcResponse {
43                jsonrpc: raw.jsonrpc,
44                id: raw.id,
45                result: raw.result,
46                error: None,
47            }));
48        }
49
50        // If we have a method, it's either a notification or request
51        if let Some(method) = raw.method {
52            if raw.id.is_none() {
53                return Ok(JsonRpcMessage::Notification(JsonRpcNotification {
54                    jsonrpc: raw.jsonrpc,
55                    method,
56                    params: raw.params,
57                }));
58            }
59
60            return Ok(JsonRpcMessage::Request(JsonRpcRequest {
61                jsonrpc: raw.jsonrpc,
62                id: raw.id,
63                method,
64                params: raw.params,
65            }));
66        }
67
68        // If we have no method and no result/error, it's a nil response
69        if raw.id.is_none() && raw.result.is_none() && raw.error.is_none() {
70            return Ok(JsonRpcMessage::Nil);
71        }
72
73        // If we get here, something is wrong with the message
74        Err(format!(
75            "Invalid JSON-RPC message format: id={:?}, method={:?}, result={:?}, error={:?}",
76            raw.id, raw.method, raw.result, raw.error
77        ))
78    }
79}
80
81// Standard JSON-RPC error codes
82pub const PARSE_ERROR: i32 = -32700;
83pub const INVALID_REQUEST: i32 = -32600;
84pub const METHOD_NOT_FOUND: i32 = -32601;
85pub const INVALID_PARAMS: i32 = -32602;
86pub const INTERNAL_ERROR: i32 = -32603;
87/*
88
89#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
90#[serde(rename_all = "camelCase")]
91pub struct ListResourcesResult {
92    pub resources: Vec<Resource>,
93    #[serde(skip_serializing_if = "Option::is_none")]
94    pub next_cursor: Option<String>,
95}
96
97#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
98pub struct ReadResourceResult {
99    pub contents: Vec<ResourceContents>,
100}
101
102#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
103#[serde(rename_all = "camelCase")]
104pub struct ListToolsResult {
105    pub tools: Vec<Tool>,
106    #[serde(skip_serializing_if = "Option::is_none")]
107    pub next_cursor: Option<String>,
108}
109
110#[derive(Debug, Serialize, Deserialize)]
111#[serde(rename_all = "camelCase")]
112pub struct CallToolResult {
113    pub content: Vec<Content>,
114    #[serde(skip_serializing_if = "Option::is_none")]
115    pub is_error: Option<bool>,
116}
117
118#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
119pub struct ListPromptsResult {
120    pub prompts: Vec<Prompt>,
121}
122
123#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
124pub struct GetPromptResult {
125    #[serde(skip_serializing_if = "Option::is_none")]
126    pub description: Option<String>,
127    pub messages: Vec<PromptMessage>,
128}
129*/
130#[derive(Debug, Serialize, Deserialize)]
131pub struct EmptyResult {}
132
133#[cfg(test)]
134mod tests {
135    use super::*;
136    use serde_json::json;
137
138    #[test]
139    fn test_notification_conversion() {
140        let raw = JsonRpcRaw {
141            jsonrpc: "2.0".to_string(),
142            id: None,
143            method: Some("notify".to_string()),
144            params: Some(json!({"key": "value"})),
145            result: None,
146            error: None,
147        };
148
149        let message = JsonRpcMessage::try_from(raw).unwrap();
150        match message {
151            JsonRpcMessage::Notification(n) => {
152                assert_eq!(n.jsonrpc, "2.0");
153                assert_eq!(n.method, "notify");
154                assert_eq!(n.params.unwrap(), json!({"key": "value"}));
155            }
156            _ => panic!("Expected Notification"),
157        }
158    }
159
160    #[test]
161    fn test_request_conversion() {
162        let raw = JsonRpcRaw {
163            jsonrpc: "2.0".to_string(),
164            id: Some(1),
165            method: Some("request".to_string()),
166            params: Some(json!({"key": "value"})),
167            result: None,
168            error: None,
169        };
170
171        let message = JsonRpcMessage::try_from(raw).unwrap();
172        match message {
173            JsonRpcMessage::Request(r) => {
174                assert_eq!(r.jsonrpc, "2.0");
175                assert_eq!(r.id, Some(1));
176                assert_eq!(r.method, "request");
177                assert_eq!(r.params.unwrap(), json!({"key": "value"}));
178            }
179            _ => panic!("Expected Request"),
180        }
181    }
182}