Skip to main content

max / makenotwork

3.5 KB · 135 lines History Blame Raw
1 //! MCP JSON-RPC 2.0 protocol types for the Streamable HTTP transport.
2 //!
3 //! Only the subset needed for `initialize`, `tools/list`, and `tools/call`.
4
5 use serde::{Deserialize, Serialize};
6 use serde_json::Value;
7
8 pub const MCP_PROTOCOL_VERSION: &str = "2025-06-18";
9
10 #[derive(Debug, Deserialize)]
11 pub struct JsonRpcRequest {
12 #[allow(dead_code)]
13 pub jsonrpc: String,
14 #[serde(default)]
15 pub id: Option<Value>,
16 pub method: String,
17 #[serde(default)]
18 pub params: Option<Value>,
19 }
20
21 #[derive(Debug, Serialize)]
22 pub struct JsonRpcResponse {
23 pub jsonrpc: &'static str,
24 pub id: Value,
25 #[serde(skip_serializing_if = "Option::is_none")]
26 pub result: Option<Value>,
27 #[serde(skip_serializing_if = "Option::is_none")]
28 pub error: Option<JsonRpcError>,
29 }
30
31 impl JsonRpcResponse {
32 pub fn ok(id: Value, result: Value) -> Self {
33 Self {
34 jsonrpc: "2.0",
35 id,
36 result: Some(result),
37 error: None,
38 }
39 }
40
41 pub fn err(id: Value, code: i32, message: impl Into<String>) -> Self {
42 Self {
43 jsonrpc: "2.0",
44 id,
45 result: None,
46 error: Some(JsonRpcError {
47 code,
48 message: message.into(),
49 data: None,
50 }),
51 }
52 }
53 }
54
55 #[derive(Debug, Serialize)]
56 pub struct JsonRpcError {
57 pub code: i32,
58 pub message: String,
59 #[serde(skip_serializing_if = "Option::is_none")]
60 pub data: Option<Value>,
61 }
62
63 pub mod codes {
64 pub const PARSE_ERROR: i32 = -32700;
65 pub const METHOD_NOT_FOUND: i32 = -32601;
66 pub const INVALID_PARAMS: i32 = -32602;
67 pub const INTERNAL_ERROR: i32 = -32603;
68 /// MCP-defined: a `resources/read` (or subscribe) named an unknown uri.
69 pub const RESOURCE_NOT_FOUND: i32 = -32002;
70 /// An in-flight request was cancelled before it completed. Same code LSP
71 /// uses for `ContentModified`/cancellation.
72 pub const REQUEST_CANCELLED: i32 = -32800;
73 }
74
75 #[derive(Debug, Serialize)]
76 pub struct InitializeResult {
77 #[serde(rename = "protocolVersion")]
78 pub protocol_version: &'static str,
79 pub capabilities: ServerCapabilities,
80 #[serde(rename = "serverInfo")]
81 pub server_info: ServerInfo,
82 }
83
84 #[derive(Debug, Serialize)]
85 pub struct ServerCapabilities {
86 pub tools: ToolsCapability,
87 /// Only advertised when the server was configured with a resource
88 /// registry. `subscribe` stays `false` until the push layer lands.
89 #[serde(skip_serializing_if = "Option::is_none")]
90 pub resources: Option<ResourcesCapability>,
91 }
92
93 #[derive(Debug, Serialize)]
94 pub struct ToolsCapability {
95 #[serde(rename = "listChanged")]
96 pub list_changed: bool,
97 }
98
99 #[derive(Debug, Serialize)]
100 pub struct ResourcesCapability {
101 pub subscribe: bool,
102 #[serde(rename = "listChanged")]
103 pub list_changed: bool,
104 }
105
106 #[derive(Debug, Serialize)]
107 pub struct ServerInfo {
108 pub name: String,
109 pub version: String,
110 }
111
112 #[derive(Debug, Deserialize)]
113 pub struct CallToolParams {
114 pub name: String,
115 #[serde(default)]
116 pub arguments: Value,
117 }
118
119 /// `resources/subscribe` and `resources/unsubscribe` param object.
120 #[derive(Debug, Deserialize)]
121 pub struct SubscribeParams {
122 pub uri: String,
123 }
124
125 /// `notifications/cancelled` param object (client → server). `requestId` is the
126 /// id of the request being cancelled; `reason` is optional free text.
127 #[derive(Debug, Deserialize)]
128 pub struct CancelledParams {
129 #[serde(rename = "requestId")]
130 pub request_id: Value,
131 #[serde(default)]
132 #[allow(dead_code)]
133 pub reason: Option<String>,
134 }
135