Skip to main content

deck_mcp/
wire.rs

1//! JSON-RPC 2.0 wire types for MCP. Only the subset we use.
2
3use serde::{Deserialize, Serialize};
4use serde_json::Value;
5
6#[derive(Debug, Serialize, Deserialize)]
7pub struct JsonRpcRequest<'a> {
8    pub jsonrpc: &'static str,
9    pub id: u64,
10    pub method: &'a str,
11    #[serde(skip_serializing_if = "Option::is_none")]
12    pub params: Option<Value>,
13}
14
15#[derive(Debug, Deserialize)]
16pub struct JsonRpcResponse {
17    #[allow(dead_code)]
18    pub jsonrpc: String,
19    pub id: Option<u64>,
20    pub result: Option<Value>,
21    pub error: Option<JsonRpcError>,
22}
23
24#[derive(Debug, Deserialize)]
25pub struct JsonRpcError {
26    pub code: i64,
27    pub message: String,
28    #[serde(default)]
29    pub data: Option<Value>,
30}
31
32#[must_use]
33pub fn make_request(id: u64, method: &str, params: Option<Value>) -> String {
34    let req = JsonRpcRequest {
35        jsonrpc: "2.0",
36        id,
37        method,
38        params,
39    };
40    serde_json::to_string(&req).expect("serialize jsonrpc")
41}
42
43#[cfg(test)]
44mod tests {
45    use super::*;
46    use serde_json::json;
47
48    #[test]
49    fn request_serializes_with_jsonrpc_field() {
50        let s = make_request(
51            1,
52            "initialize",
53            Some(json!({"protocolVersion": "2024-11-05"})),
54        );
55        assert!(s.contains("\"jsonrpc\":\"2.0\""));
56        assert!(s.contains("\"method\":\"initialize\""));
57    }
58}