mcpr/schema/
json_rpc.rs

1//! JSON-RPC message types for MCP
2
3use serde::{Deserialize, Serialize};
4use serde_json::Value;
5use std::collections::HashMap;
6
7use crate::constants::JSONRPC_VERSION;
8
9/// A uniquely identifying ID for a request in JSON-RPC.
10#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
11#[serde(untagged)]
12pub enum RequestId {
13    String(String),
14    Number(i64),
15}
16
17/// JSON-RPC message types
18#[derive(Debug, Clone, Serialize, Deserialize)]
19#[serde(untagged)]
20pub enum JSONRPCMessage {
21    Request(JSONRPCRequest),
22    Notification(JSONRPCNotification),
23    Response(JSONRPCResponse),
24    Error(JSONRPCError),
25}
26
27/// A request that expects a response.
28#[derive(Debug, Clone, Serialize, Deserialize)]
29pub struct JSONRPCRequest {
30    pub jsonrpc: String,
31    pub id: RequestId,
32    pub method: String,
33    #[serde(skip_serializing_if = "Option::is_none")]
34    pub params: Option<Value>,
35}
36
37/// A notification which does not expect a response.
38#[derive(Debug, Clone, Serialize, Deserialize)]
39pub struct JSONRPCNotification {
40    pub jsonrpc: String,
41    pub method: String,
42    #[serde(skip_serializing_if = "Option::is_none")]
43    pub params: Option<Value>,
44}
45
46/// A successful (non-error) response to a request.
47#[derive(Debug, Clone, Serialize, Deserialize)]
48pub struct JSONRPCResponse {
49    pub jsonrpc: String,
50    pub id: RequestId,
51    pub result: Value,
52}
53
54/// A response to a request that indicates an error occurred.
55#[derive(Debug, Clone, Serialize, Deserialize)]
56pub struct JSONRPCError {
57    pub jsonrpc: String,
58    pub id: RequestId,
59    pub error: JSONRPCErrorObject,
60}
61
62/// Error object in a JSON-RPC error response
63#[derive(Debug, Clone, Serialize, Deserialize)]
64pub struct JSONRPCErrorObject {
65    /// The error type that occurred.
66    pub code: i32,
67
68    /// A short description of the error.
69    pub message: String,
70
71    /// Additional information about the error.
72    #[serde(skip_serializing_if = "Option::is_none")]
73    pub data: Option<Value>,
74}
75
76/// Standard JSON-RPC error codes
77pub mod error_codes {
78    pub const PARSE_ERROR: i32 = -32700;
79    pub const INVALID_REQUEST: i32 = -32600;
80    pub const METHOD_NOT_FOUND: i32 = -32601;
81    pub const INVALID_PARAMS: i32 = -32602;
82    pub const INTERNAL_ERROR: i32 = -32603;
83}
84
85/// Base request interface
86#[derive(Debug, Clone, Serialize, Deserialize)]
87pub struct Request {
88    pub method: String,
89    #[serde(skip_serializing_if = "Option::is_none")]
90    pub params: Option<RequestParams>,
91}
92
93/// Request parameters
94#[derive(Debug, Clone, Serialize, Deserialize)]
95pub struct RequestParams {
96    #[serde(skip_serializing_if = "Option::is_none")]
97    pub _meta: Option<RequestMeta>,
98    #[serde(flatten)]
99    pub extra: HashMap<String, Value>,
100}
101
102/// Request metadata
103#[derive(Debug, Clone, Serialize, Deserialize)]
104pub struct RequestMeta {
105    #[serde(skip_serializing_if = "Option::is_none")]
106    pub progress_token: Option<super::common::ProgressToken>,
107}
108
109/// Base notification interface
110#[derive(Debug, Clone, Serialize, Deserialize)]
111pub struct Notification {
112    pub method: String,
113    #[serde(skip_serializing_if = "Option::is_none")]
114    pub params: Option<NotificationParams>,
115}
116
117/// Notification parameters
118#[derive(Debug, Clone, Serialize, Deserialize)]
119pub struct NotificationParams {
120    #[serde(skip_serializing_if = "Option::is_none")]
121    pub _meta: Option<HashMap<String, Value>>,
122    #[serde(flatten)]
123    pub extra: HashMap<String, Value>,
124}
125
126/// Base result interface
127#[derive(Debug, Clone, Serialize, Deserialize)]
128pub struct Result {
129    #[serde(skip_serializing_if = "Option::is_none")]
130    pub _meta: Option<HashMap<String, Value>>,
131    #[serde(flatten)]
132    pub extra: HashMap<String, Value>,
133}
134
135/// A response that indicates success but carries no data.
136pub type EmptyResult = Result;
137
138// Helper functions for creating JSON-RPC messages
139impl JSONRPCRequest {
140    /// Create a new JSON-RPC request
141    pub fn new(id: RequestId, method: String, params: Option<Value>) -> Self {
142        Self {
143            jsonrpc: JSONRPC_VERSION.to_string(),
144            id,
145            method,
146            params,
147        }
148    }
149}
150
151impl JSONRPCNotification {
152    /// Create a new JSON-RPC notification
153    pub fn new(method: String, params: Option<Value>) -> Self {
154        Self {
155            jsonrpc: JSONRPC_VERSION.to_string(),
156            method,
157            params,
158        }
159    }
160}
161
162impl JSONRPCResponse {
163    /// Create a new JSON-RPC response
164    pub fn new(id: RequestId, result: Value) -> Self {
165        Self {
166            jsonrpc: JSONRPC_VERSION.to_string(),
167            id,
168            result,
169        }
170    }
171}
172
173impl JSONRPCError {
174    /// Create a new JSON-RPC error
175    pub fn new(id: RequestId, code: i32, message: String, data: Option<Value>) -> Self {
176        Self {
177            jsonrpc: JSONRPC_VERSION.to_string(),
178            id,
179            error: JSONRPCErrorObject {
180                code,
181                message,
182                data,
183            },
184        }
185    }
186}