use serde::{Deserialize, Serialize};
use super::RequestId;
use crate::protocol::messages::{Request, Notification, Result as MessageResult};
pub const JSONRPC_VERSION: &str = "2.0";
pub mod error_codes {
pub const PARSE_ERROR: i32 = -32700;
pub const INVALID_REQUEST: i32 = -32600;
pub const METHOD_NOT_FOUND: i32 = -32601;
pub const INVALID_PARAMS: i32 = -32602;
pub const INTERNAL_ERROR: i32 = -32603;
pub const MCP_ERROR_START: i32 = -32000;
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(untagged)]
pub enum JSONRPCMessage {
Request(JSONRPCRequest),
Notification(JSONRPCNotification),
Response(JSONRPCResponse),
Error(JSONRPCError),
BatchRequest(Vec<JSONRPCBatchRequestItem>),
BatchResponse(Vec<JSONRPCBatchResponseItem>),
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct JSONRPCRequest {
pub jsonrpc: String,
pub id: RequestId,
pub method: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub params: Option<serde_json::Value>,
}
impl JSONRPCRequest {
pub fn new<I: Into<RequestId>>(id: I, method: impl Into<String>, params: Option<serde_json::Value>) -> Self {
Self {
jsonrpc: JSONRPC_VERSION.to_string(),
id: id.into(),
method: method.into(),
params,
}
}
pub fn from_request<I: Into<RequestId>, T: Request>(id: I, request: &T) -> Result<Self, serde_json::Error> {
let params = if let Some(params) = request.params() {
Some(serde_json::to_value(params)?)
} else {
None
};
Ok(Self::new(id, request.method().to_string(), params))
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct JSONRPCNotification {
pub jsonrpc: String,
pub method: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub params: Option<serde_json::Value>,
}
impl JSONRPCNotification {
pub fn new(method: impl Into<String>, params: Option<serde_json::Value>) -> Self {
Self {
jsonrpc: JSONRPC_VERSION.to_string(),
method: method.into(),
params,
}
}
pub fn from_notification<T: Notification>(notification: &T) -> Result<Self, serde_json::Error> {
let params = if let Some(params) = notification.params() {
Some(serde_json::to_value(params)?)
} else {
None
};
Ok(Self::new(notification.method().to_string(), params))
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct JSONRPCResponse {
pub jsonrpc: String,
pub id: RequestId,
pub result: serde_json::Value,
}
impl JSONRPCResponse {
pub fn new<I: Into<RequestId>>(id: I, result: serde_json::Value) -> Self {
Self {
jsonrpc: JSONRPC_VERSION.to_string(),
id: id.into(),
result,
}
}
pub fn from_result<I: Into<RequestId>>(id: I, result: &MessageResult) -> Result<Self, serde_json::Error> {
Ok(Self::new(id, serde_json::to_value(result)?))
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct JSONRPCError {
pub jsonrpc: String,
pub id: RequestId,
pub error: JSONRPCErrorInfo,
}
impl JSONRPCError {
pub fn new<I: Into<RequestId>>(id: I, code: i32, message: impl Into<String>, data: Option<serde_json::Value>) -> Self {
Self {
jsonrpc: JSONRPC_VERSION.to_string(),
id: id.into(),
error: JSONRPCErrorInfo {
code,
message: message.into(),
data,
},
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct JSONRPCErrorInfo {
pub code: i32,
pub message: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub data: Option<serde_json::Value>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(untagged)]
pub enum JSONRPCBatchRequestItem {
Request(JSONRPCRequest),
Notification(JSONRPCNotification),
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(untagged)]
pub enum JSONRPCBatchResponseItem {
Response(JSONRPCResponse),
Error(JSONRPCError),
}
pub type JSONRPCBatchRequest = Vec<JSONRPCBatchRequestItem>;
pub type JSONRPCBatchResponse = Vec<JSONRPCBatchResponseItem>;