1use serde::{Deserialize, Serialize};
7use serde_json::Value;
8
9#[derive(Debug, Clone, Deserialize, Serialize)]
11pub struct JsonRpcRequest {
12 pub jsonrpc: String,
14 #[serde(skip_serializing_if = "Option::is_none")]
16 pub id: Option<Value>,
17 pub method: String,
19 #[serde(skip_serializing_if = "Option::is_none")]
21 pub params: Option<Value>,
22}
23
24impl JsonRpcRequest {
25 pub fn new(id: Value, method: impl Into<String>, params: Option<Value>) -> Self {
27 Self {
28 jsonrpc: "2.0".to_string(),
29 id: Some(id),
30 method: method.into(),
31 params,
32 }
33 }
34
35 pub fn notification(method: impl Into<String>, params: Option<Value>) -> Self {
37 Self {
38 jsonrpc: "2.0".to_string(),
39 id: None,
40 method: method.into(),
41 params,
42 }
43 }
44
45 pub fn is_notification(&self) -> bool {
47 self.id.is_none()
48 }
49}
50
51#[derive(Debug, Clone, Serialize, Deserialize)]
53pub struct JsonRpcResponse {
54 pub jsonrpc: String,
56 pub id: Value,
58 #[serde(skip_serializing_if = "Option::is_none")]
60 pub result: Option<Value>,
61 #[serde(skip_serializing_if = "Option::is_none")]
63 pub error: Option<JsonRpcError>,
64}
65
66impl JsonRpcResponse {
67 pub fn success(id: Value, result: Value) -> Self {
69 Self {
70 jsonrpc: "2.0".to_string(),
71 id,
72 result: Some(result),
73 error: None,
74 }
75 }
76
77 pub fn error(id: Value, error: JsonRpcError) -> Self {
79 Self {
80 jsonrpc: "2.0".to_string(),
81 id,
82 result: None,
83 error: Some(error),
84 }
85 }
86}
87
88#[derive(Debug, Clone, Serialize, Deserialize)]
90pub struct JsonRpcError {
91 pub code: i32,
93 pub message: String,
95 #[serde(skip_serializing_if = "Option::is_none")]
97 pub data: Option<Value>,
98}
99
100impl JsonRpcError {
101 pub fn new(code: i32, message: impl Into<String>) -> Self {
103 Self {
104 code,
105 message: message.into(),
106 data: None,
107 }
108 }
109
110 pub fn with_data(mut self, data: Value) -> Self {
112 self.data = Some(data);
113 self
114 }
115
116 pub fn parse_error(message: impl Into<String>) -> Self {
118 Self::new(-32700, message)
119 }
120
121 pub fn invalid_request(message: impl Into<String>) -> Self {
123 Self::new(-32600, message)
124 }
125
126 pub fn method_not_found(message: impl Into<String>) -> Self {
128 Self::new(-32601, message)
129 }
130
131 pub fn invalid_params(message: impl Into<String>) -> Self {
133 Self::new(-32602, message)
134 }
135
136 pub fn internal_error(message: impl Into<String>) -> Self {
138 Self::new(-32603, message)
139 }
140}
141
142#[derive(Debug, Clone, Serialize, Deserialize)]
144pub struct Implementation {
145 pub name: String,
147 pub version: String,
149}
150
151impl Implementation {
152 pub fn new(name: impl Into<String>, version: impl Into<String>) -> Self {
154 Self {
155 name: name.into(),
156 version: version.into(),
157 }
158 }
159}
160
161#[derive(Debug, Clone, Default)]
163pub struct ClientInfo {
164 pub name: String,
166 pub version: String,
168}
169
170impl ClientInfo {
171 pub fn new(name: impl Into<String>, version: impl Into<String>) -> Self {
173 Self {
174 name: name.into(),
175 version: version.into(),
176 }
177 }
178
179 pub fn is_supported(&self, min_versions: &[(&str, &str)]) -> bool {
183 for (name, min_version) in min_versions {
184 if self.name == *name {
185 return version_gte(&self.version, min_version);
186 }
187 }
188 true
190 }
191}
192
193pub fn version_gte(version: &str, min: &str) -> bool {
197 let parse = |v: &str| -> (u32, u32, u32) {
198 let parts: Vec<u32> = v.split('.').filter_map(|p| p.parse().ok()).collect();
199 (
200 parts.first().copied().unwrap_or(0),
201 parts.get(1).copied().unwrap_or(0),
202 parts.get(2).copied().unwrap_or(0),
203 )
204 };
205
206 let (v_maj, v_min, v_patch) = parse(version);
207 let (m_maj, m_min, m_patch) = parse(min);
208
209 (v_maj, v_min, v_patch) >= (m_maj, m_min, m_patch)
210}
211
212#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
221#[serde(rename_all = "camelCase")]
222pub struct Root {
223 pub uri: String,
225 #[serde(skip_serializing_if = "Option::is_none")]
227 pub name: Option<String>,
228}
229
230#[derive(Debug, Clone, Serialize, Deserialize)]
232pub struct ListRootsResult {
233 pub roots: Vec<Root>,
235}
236
237#[derive(Debug, Clone, Serialize, Deserialize)]
241pub struct RootsListChangedNotification {}
242
243#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
249#[serde(rename_all = "lowercase")]
250pub enum Role {
251 User,
253 Assistant,
255}
256
257#[derive(Debug, Clone, Serialize, Deserialize)]
259#[serde(rename_all = "camelCase")]
260pub struct SamplingMessage {
261 pub role: Role,
263 pub content: Value, }
266
267#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
269#[serde(rename_all = "camelCase")]
270pub enum ContextInclusion {
271 None,
273 ThisServer,
275 AllServers,
277}
278
279#[derive(Debug, Clone, Serialize, Deserialize)]
281#[serde(rename_all = "camelCase")]
282pub struct ModelHint {
283 #[serde(skip_serializing_if = "Option::is_none")]
285 pub name: Option<String>,
286}
287
288#[derive(Debug, Clone, Serialize, Deserialize)]
290#[serde(rename_all = "camelCase")]
291pub struct ModelPreferences {
292 #[serde(skip_serializing_if = "Option::is_none")]
294 pub hints: Option<Vec<ModelHint>>,
295 #[serde(skip_serializing_if = "Option::is_none")]
297 pub cost_priority: Option<f64>,
298 #[serde(skip_serializing_if = "Option::is_none")]
300 pub speed_priority: Option<f64>,
301 #[serde(skip_serializing_if = "Option::is_none")]
303 pub intelligence_priority: Option<f64>,
304}
305
306#[derive(Debug, Clone, Serialize, Deserialize)]
308#[serde(rename_all = "camelCase")]
309pub struct CreateMessageRequest {
310 pub messages: Vec<SamplingMessage>,
312 #[serde(skip_serializing_if = "Option::is_none")]
314 pub model_preferences: Option<ModelPreferences>,
315 #[serde(skip_serializing_if = "Option::is_none")]
317 pub system_prompt: Option<String>,
318 #[serde(skip_serializing_if = "Option::is_none")]
320 pub include_context: Option<ContextInclusion>,
321 #[serde(skip_serializing_if = "Option::is_none")]
323 pub temperature: Option<f64>,
324 pub max_tokens: u32,
326 #[serde(skip_serializing_if = "Option::is_none")]
328 pub stop_sequences: Option<Vec<String>>,
329 #[serde(skip_serializing_if = "Option::is_none")]
331 pub metadata: Option<Value>,
332}
333
334#[derive(Debug, Clone, Serialize, Deserialize)]
336#[serde(rename_all = "camelCase")]
337pub struct CreateMessageResult {
338 pub message: SamplingMessage,
340 pub model: String,
342 #[serde(skip_serializing_if = "Option::is_none")]
344 pub stop_reason: Option<String>, }
346
347impl CreateMessageResult {
348 pub const STOP_REASON_END_TURN: &'static str = "endTurn";
350 pub const STOP_REASON_STOP_SEQUENCE: &'static str = "stopSequence";
352 pub const STOP_REASON_MAX_TOKENS: &'static str = "maxTokens";
354}
355
356#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
362#[serde(rename_all = "lowercase")]
363pub enum ElicitationAction {
364 Accept,
366 Decline,
368 Cancel,
370}
371
372#[derive(Debug, Clone, Serialize, Deserialize)]
374#[serde(rename_all = "camelCase")]
375pub struct CreateElicitationRequest {
376 pub message: String,
378 pub requested_schema: Value, }
381
382#[derive(Debug, Clone, Serialize, Deserialize)]
384pub struct CreateElicitationResult {
385 pub action: ElicitationAction,
387 #[serde(skip_serializing_if = "Option::is_none")]
389 pub content: Option<Value>,
390}
391
392#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash)]
398#[serde(rename_all = "snake_case")]
399pub enum TaskStatus {
400 Working,
402 InputRequired,
404 Completed,
406 Failed,
408 Cancelled,
410}
411
412#[derive(Debug, Clone, Serialize, Deserialize)]
414#[serde(rename_all = "camelCase")]
415pub struct TaskMetadata {
416 #[serde(skip_serializing_if = "Option::is_none")]
418 pub ttl: Option<u64>,
419}
420
421#[derive(Debug, Clone, Serialize, Deserialize)]
423#[serde(rename_all = "camelCase")]
424pub struct Task {
425 pub task_id: String,
427 pub status: TaskStatus,
429 #[serde(skip_serializing_if = "Option::is_none")]
431 pub status_message: Option<String>,
432 pub created_at: String,
434 pub last_updated_at: String,
436 pub ttl: Option<u64>,
438 #[serde(skip_serializing_if = "Option::is_none")]
440 pub poll_interval: Option<u64>,
441}
442
443#[derive(Debug, Clone, Serialize, Deserialize)]
445#[serde(rename_all = "camelCase")]
446pub struct CreateTaskResult {
447 pub task: Task,
449}
450
451#[derive(Debug, Clone, Serialize, Deserialize)]
453#[serde(rename_all = "camelCase")]
454pub struct GetTaskParams {
455 pub task_id: String,
457}
458
459#[derive(Debug, Clone, Serialize, Deserialize)]
461#[serde(rename_all = "camelCase")]
462pub struct CancelTaskParams {
463 pub task_id: String,
465}
466
467#[derive(Debug, Clone, Default, Serialize, Deserialize)]
469#[serde(rename_all = "camelCase")]
470pub struct ToolExecution {
471 #[serde(skip_serializing_if = "Option::is_none")]
473 pub task_support: Option<TaskSupport>,
474}
475
476#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
478#[serde(rename_all = "lowercase")]
479pub enum TaskSupport {
480 Forbidden,
482 Optional,
484 Required,
486}
487
488#[derive(Debug, Clone, Serialize, Deserialize)]
494pub struct SetLevelRequest {
495 pub level: String,
497}
498
499#[cfg(test)]
500mod tests {
501 use super::*;
502
503 #[test]
504 fn test_version_gte_equal() {
505 assert!(version_gte("1.0.0", "1.0.0"));
506 assert!(version_gte("2.0.56", "2.0.56"));
507 }
508
509 #[test]
510 fn test_version_gte_major_greater() {
511 assert!(version_gte("2.0.0", "1.0.0"));
512 assert!(version_gte("3.0.0", "2.9.99"));
513 }
514
515 #[test]
516 fn test_version_gte_minor_greater() {
517 assert!(version_gte("1.2.0", "1.1.0"));
518 assert!(version_gte("1.10.0", "1.9.0"));
519 }
520
521 #[test]
522 fn test_version_gte_patch_greater() {
523 assert!(version_gte("1.0.2", "1.0.1"));
524 assert!(version_gte("2.0.56", "2.0.55"));
525 }
526
527 #[test]
528 fn test_version_gte_less_than() {
529 assert!(!version_gte("1.0.0", "2.0.0"));
530 assert!(!version_gte("2.0.55", "2.0.56"));
531 assert!(!version_gte("1.9.0", "2.0.0"));
532 }
533
534 #[test]
535 fn test_jsonrpc_request_creation() {
536 let req = JsonRpcRequest::new(
537 Value::from(1),
538 "test_method",
539 Some(serde_json::json!({"key": "value"})),
540 );
541 assert_eq!(req.jsonrpc, "2.0");
542 assert_eq!(req.method, "test_method");
543 assert!(req.id.is_some());
544 }
545
546 #[test]
547 fn test_jsonrpc_notification() {
548 let notif = JsonRpcRequest::notification("test_notif", None);
549 assert!(notif.is_notification());
550 assert!(notif.id.is_none());
551 }
552
553 #[test]
554 fn test_jsonrpc_response_success() {
555 let resp = JsonRpcResponse::success(Value::from(1), serde_json::json!({"status": "ok"}));
556 assert!(resp.result.is_some());
557 assert!(resp.error.is_none());
558 }
559
560 #[test]
561 fn test_jsonrpc_response_error() {
562 let error = JsonRpcError::method_not_found("test method not found");
563 let resp = JsonRpcResponse::error(Value::from(1), error);
564 assert!(resp.result.is_none());
565 assert!(resp.error.is_some());
566 assert_eq!(resp.error.unwrap().code, -32601);
567 }
568}