use serde::{Deserialize, Serialize};
use serde_json::{Value, json};
pub const MCP_PROTOCOL_VERSION: &str = "2025-06-18";
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct JsonRpcRequest {
pub jsonrpc: String,
pub id: Option<Value>,
pub method: String,
#[serde(default)]
pub params: Option<Value>,
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct JsonRpcResponse {
pub jsonrpc: String,
pub id: Value,
#[serde(skip_serializing_if = "Option::is_none")]
pub result: Option<Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub error: Option<JsonRpcError>,
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct JsonRpcError {
pub code: i32,
pub message: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub data: Option<Value>,
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct McpBridgeRequest {
pub line: String,
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct McpBridgeResponse {
pub line: Option<String>,
}
pub fn json_rpc_result(id: Value, result: Value) -> JsonRpcResponse {
JsonRpcResponse {
jsonrpc: "2.0".to_owned(),
id,
result: Some(result),
error: None,
}
}
pub fn json_rpc_failure(id: Value, error: JsonRpcError) -> JsonRpcResponse {
JsonRpcResponse {
jsonrpc: "2.0".to_owned(),
id,
result: None,
error: Some(error),
}
}
pub fn json_rpc_error(code: i32, message: impl Into<String>) -> JsonRpcError {
JsonRpcError {
code,
message: message.into(),
data: None,
}
}
pub fn tool_success<T>(text: String, structured: &T) -> Value
where
T: Serialize,
{
json!({
"content": [{"type": "text", "text": text}],
"structuredContent": serde_json::to_value(structured)
.expect("structured MCP result serializes")
})
}
pub fn tool_error(message: impl Into<String>) -> Value {
let message = message.into();
json!({
"content": [{"type": "text", "text": format!("ERROR: {message}")}],
"_meta": {
"rtm_tool_error": {
"is_error": true,
"message": message
}
}
})
}