1use serde::{Deserialize, Serialize};
4use serde_json::Value;
5
6#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct JsonRpcRequest {
10 pub jsonrpc: String,
11 pub id: JsonRpcId,
12 pub method: String,
13 #[serde(skip_serializing_if = "Option::is_none")]
14 pub params: Option<Value>,
15}
16
17#[derive(Debug, Clone, Serialize, Deserialize)]
18#[serde(untagged)]
19pub enum JsonRpcId {
20 Number(i64),
21 String(String),
22 Null,
23}
24
25#[derive(Debug, Clone, Serialize, Deserialize)]
26pub struct JsonRpcResponse {
27 pub jsonrpc: String,
28 pub id: JsonRpcId,
29 #[serde(skip_serializing_if = "Option::is_none")]
30 pub result: Option<Value>,
31 #[serde(skip_serializing_if = "Option::is_none")]
32 pub error: Option<JsonRpcError>,
33}
34
35#[derive(Debug, Clone, Serialize, Deserialize)]
36pub struct JsonRpcError {
37 pub code: i32,
38 pub message: String,
39 #[serde(skip_serializing_if = "Option::is_none")]
40 pub data: Option<Value>,
41}
42
43impl JsonRpcRequest {
44 pub fn new(id: i64, method: impl Into<String>, params: Option<Value>) -> Self {
45 Self {
46 jsonrpc: "2.0".to_string(),
47 id: JsonRpcId::Number(id),
48 method: method.into(),
49 params,
50 }
51 }
52}
53
54#[derive(Debug, Clone, Deserialize)]
58pub struct McpToolSpec {
59 pub name: String,
60 pub description: String,
61 #[serde(rename = "inputSchema")]
62 pub input_schema: Value,
63}
64
65#[derive(Debug, Deserialize)]
67pub struct McpToolsListResult {
68 pub tools: Vec<McpToolSpec>,
69}
70
71#[derive(Debug, Deserialize)]
73pub struct McpToolCallResult {
74 pub content: Vec<McpContent>,
75 #[serde(default)]
76 pub is_error: bool,
77}
78
79#[derive(Debug, Deserialize)]
80pub struct McpContent {
81 #[serde(rename = "type")]
82 pub content_type: String,
83 #[serde(default)]
84 pub text: String,
85}
86
87#[derive(Debug, Clone, Serialize, Deserialize)]
91pub struct McpResourceSpec {
92 pub uri: String,
94 pub name: String,
96 #[serde(skip_serializing_if = "Option::is_none")]
97 pub description: Option<String>,
98 #[serde(rename = "mimeType", skip_serializing_if = "Option::is_none")]
100 pub mime_type: Option<String>,
101}
102
103#[derive(Debug, Deserialize)]
105pub struct McpResourcesListResult {
106 pub resources: Vec<McpResourceSpec>,
107}
108
109#[derive(Debug, Clone, Serialize, Deserialize)]
111pub struct McpResourceContent {
112 pub uri: String,
113 #[serde(rename = "mimeType", skip_serializing_if = "Option::is_none")]
114 pub mime_type: Option<String>,
115 #[serde(skip_serializing_if = "Option::is_none")]
117 pub text: Option<String>,
118 #[serde(skip_serializing_if = "Option::is_none")]
120 pub blob: Option<String>,
121}
122
123#[derive(Debug, Deserialize)]
125pub struct McpResourceReadResult {
126 pub contents: Vec<McpResourceContent>,
127}
128
129#[derive(Debug, Clone, Serialize, Deserialize)]
133pub struct SamplingMessage {
134 pub role: String,
135 pub content: SamplingContent,
136}
137
138#[derive(Debug, Clone, Serialize, Deserialize)]
139#[serde(tag = "type", rename_all = "snake_case")]
140pub enum SamplingContent {
141 Text { text: String },
142}
143
144impl SamplingMessage {
145 pub fn user(text: impl Into<String>) -> Self {
146 Self { role: "user".to_string(), content: SamplingContent::Text { text: text.into() } }
147 }
148
149 pub fn assistant(text: impl Into<String>) -> Self {
150 Self { role: "assistant".to_string(), content: SamplingContent::Text { text: text.into() } }
151 }
152}
153
154#[derive(Debug, Clone, Serialize, Deserialize)]
156pub struct SamplingRequest {
157 pub messages: Vec<SamplingMessage>,
158 #[serde(rename = "maxTokens")]
159 pub max_tokens: u32,
160 #[serde(skip_serializing_if = "Option::is_none")]
161 pub system: Option<String>,
162 #[serde(skip_serializing_if = "Option::is_none")]
163 pub temperature: Option<f32>,
164}
165
166#[derive(Debug, Clone, Deserialize)]
168pub struct SamplingResult {
169 pub role: String,
170 pub content: SamplingContent,
171 pub model: String,
172 #[serde(rename = "stopReason", skip_serializing_if = "Option::is_none")]
173 pub stop_reason: Option<String>,
174}