mcp_runner/transport/
json_rpc.rs1use serde::{Deserialize, Serialize};
11use serde_json::Value;
12use std::fmt;
13
14pub const JSON_RPC_VERSION: &str = "2.0";
16
17pub mod error_codes {
20 pub const PARSE_ERROR: i32 = -32700;
22 pub const INVALID_REQUEST: i32 = -32600;
24 pub const METHOD_NOT_FOUND: i32 = -32601;
26 pub const INVALID_PARAMS: i32 = -32602;
28 pub const INTERNAL_ERROR: i32 = -32603;
30
31 pub const SERVER_ERROR: i32 = -32000;
34}
35
36#[derive(Debug, Clone, Serialize, Deserialize)]
38#[serde(untagged)]
39pub enum JsonRpcMessage {
40 Request(JsonRpcRequest),
42 Response(JsonRpcResponse),
44 Notification(JsonRpcNotification),
46}
47
48#[derive(Debug, Clone, Serialize, Deserialize)]
50pub struct JsonRpcRequest {
51 pub jsonrpc: String,
53 pub id: Value,
55 pub method: String,
57 #[serde(skip_serializing_if = "Option::is_none")]
59 pub params: Option<Value>,
60}
61
62impl JsonRpcRequest {
63 pub fn new(id: impl Into<Value>, method: impl Into<String>, params: Option<Value>) -> Self {
65 Self {
66 jsonrpc: JSON_RPC_VERSION.to_string(),
67 id: id.into(),
68 method: method.into(),
69 params,
70 }
71 }
72
73 pub fn list_tools(id: impl Into<Value>) -> Self {
75 Self::new(id, "tools/list", None)
76 }
77
78 pub fn call_tool(id: impl Into<Value>, name: impl Into<String>, args: Value) -> Self {
80 let params = serde_json::json!({
81 "name": name.into(),
82 "arguments": args
83 });
84 Self::new(id, "tools/call", Some(params))
85 }
86
87 pub fn list_resources(id: impl Into<Value>) -> Self {
89 Self::new(id, "resources/list", None)
90 }
91
92 pub fn get_resource(id: impl Into<Value>, uri: impl Into<String>) -> Self {
94 let params = serde_json::json!({
95 "uri": uri.into()
96 });
97 Self::new(id, "resources/get", Some(params))
98 }
99}
100
101#[derive(Debug, Clone, Serialize, Deserialize)]
103pub struct JsonRpcNotification {
104 pub jsonrpc: String,
106 pub method: String,
108 #[serde(skip_serializing_if = "Option::is_none")]
110 pub params: Option<Value>,
111}
112
113impl JsonRpcNotification {
114 pub fn new(method: impl Into<String>, params: Option<Value>) -> Self {
116 Self {
117 jsonrpc: JSON_RPC_VERSION.to_string(),
118 method: method.into(),
119 params,
120 }
121 }
122
123 pub fn initialized() -> Self {
125 Self::new("notifications/initialized", None)
126 }
127}
128
129#[derive(Debug, Clone, Serialize, Deserialize)]
131pub struct JsonRpcError {
132 pub code: i32,
134 pub message: String,
136 #[serde(skip_serializing_if = "Option::is_none")]
138 pub data: Option<Value>,
139}
140
141impl fmt::Display for JsonRpcError {
142 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
143 write!(f, "JSON-RPC error {}: {}", self.code, self.message)
144 }
145}
146
147#[derive(Debug, Clone, Serialize, Deserialize)]
149pub struct JsonRpcResponse {
150 pub jsonrpc: String,
152 pub id: Value,
154 #[serde(skip_serializing_if = "Option::is_none")]
156 pub result: Option<Value>,
157 #[serde(skip_serializing_if = "Option::is_none")]
159 pub error: Option<JsonRpcError>,
160}
161
162impl JsonRpcResponse {
163 pub fn success(id: impl Into<Value>, result: Value) -> Self {
165 Self {
166 jsonrpc: JSON_RPC_VERSION.to_string(),
167 id: id.into(),
168 result: Some(result),
169 error: None,
170 }
171 }
172
173 pub fn error(
175 id: impl Into<Value>,
176 code: i32,
177 message: impl Into<String>,
178 data: Option<Value>,
179 ) -> Self {
180 Self {
181 jsonrpc: JSON_RPC_VERSION.to_string(),
182 id: id.into(),
183 result: None,
184 error: Some(JsonRpcError {
185 code,
186 message: message.into(),
187 data,
188 }),
189 }
190 }
191
192 pub fn is_success(&self) -> bool {
194 self.error.is_none() && self.result.is_some()
195 }
196}