1use crate::protocol::*;
2use serde_json::json;
3
4#[derive(Debug, Clone)]
6pub struct ToolMeta {
7 description: Option<String>,
8 params: Vec<ParamMeta>,
9 required: Vec<String>,
10}
11
12#[derive(Debug, Clone)]
13struct ParamMeta {
14 name: String,
15 param_type: String,
16 description: String,
17}
18
19impl ToolMeta {
20 pub fn new() -> Self {
21 Self {
22 description: None,
23 params: Vec::new(),
24 required: Vec::new(),
25 }
26 }
27
28 pub fn description(mut self, desc: impl Into<String>) -> Self {
29 self.description = Some(desc.into());
30 self
31 }
32
33 pub fn param(
34 mut self,
35 name: impl Into<String>,
36 param_type: impl Into<String>,
37 description: impl Into<String>,
38 ) -> Self {
39 self.params.push(ParamMeta {
40 name: name.into(),
41 param_type: param_type.into(),
42 description: description.into(),
43 });
44 self
45 }
46
47 pub fn required(mut self, fields: &[&str]) -> Self {
48 self.required = fields.iter().map(|s| s.to_string()).collect();
49 self
50 }
51
52 pub fn to_tool(&self, name: impl Into<String>) -> Tool {
53 let mut properties = serde_json::Map::new();
54
55 for param in &self.params {
56 properties.insert(
57 param.name.clone(),
58 json!({
59 "type": param.param_type,
60 "description": param.description
61 }),
62 );
63 }
64
65 let mut schema = json!({
66 "type": "object",
67 "properties": properties
68 });
69
70 if !self.required.is_empty() {
71 schema["required"] = json!(self.required);
72 }
73
74 Tool {
75 name: name.into(),
76 description: self.description.clone(),
77 input_schema: schema,
78 }
79 }
80}
81
82impl Default for ToolMeta {
83 fn default() -> Self {
84 Self::new()
85 }
86}
87
88#[derive(Debug, Clone)]
90pub struct ResourceMeta {
91 name: String,
92 description: Option<String>,
93 mime_type: Option<String>,
94}
95
96impl ResourceMeta {
97 pub fn new() -> Self {
98 Self {
99 name: String::new(),
100 description: None,
101 mime_type: None,
102 }
103 }
104
105 pub fn name(mut self, name: impl Into<String>) -> Self {
106 self.name = name.into();
107 self
108 }
109
110 pub fn description(mut self, desc: impl Into<String>) -> Self {
111 self.description = Some(desc.into());
112 self
113 }
114
115 pub fn mime_type(mut self, mime: impl Into<String>) -> Self {
116 self.mime_type = Some(mime.into());
117 self
118 }
119
120 pub fn to_resource(&self, uri: impl Into<String>) -> Resource {
121 Resource {
122 uri: uri.into(),
123 name: self.name.clone(),
124 description: self.description.clone(),
125 mime_type: self.mime_type.clone(),
126 }
127 }
128}
129
130impl Default for ResourceMeta {
131 fn default() -> Self {
132 Self::new()
133 }
134}
135
136#[derive(Debug, Clone)]
138pub struct PromptMeta {
139 description: Option<String>,
140 arguments: Vec<PromptArgumentMeta>,
141}
142
143#[derive(Debug, Clone)]
144struct PromptArgumentMeta {
145 name: String,
146 description: Option<String>,
147 required: bool,
148}
149
150impl PromptMeta {
151 pub fn new() -> Self {
152 Self {
153 description: None,
154 arguments: Vec::new(),
155 }
156 }
157
158 pub fn description(mut self, desc: impl Into<String>) -> Self {
159 self.description = Some(desc.into());
160 self
161 }
162
163 pub fn arg(
164 mut self,
165 name: impl Into<String>,
166 description: impl Into<String>,
167 required: bool,
168 ) -> Self {
169 self.arguments.push(PromptArgumentMeta {
170 name: name.into(),
171 description: Some(description.into()),
172 required,
173 });
174 self
175 }
176
177 pub fn to_prompt(&self, name: impl Into<String>) -> Prompt {
178 let arguments = if self.arguments.is_empty() {
179 None
180 } else {
181 Some(
182 self.arguments
183 .iter()
184 .map(|arg| PromptArgument {
185 name: arg.name.clone(),
186 description: arg.description.clone(),
187 required: Some(arg.required),
188 })
189 .collect(),
190 )
191 };
192
193 Prompt {
194 name: name.into(),
195 description: self.description.clone(),
196 arguments,
197 }
198 }
199}
200
201impl Default for PromptMeta {
202 fn default() -> Self {
203 Self::new()
204 }
205}
206
207#[derive(Debug, Clone)]
209pub struct EndpointMeta {
210 route: String,
211 method: String,
212 description: Option<String>,
213}
214
215impl EndpointMeta {
216 pub fn new() -> Self {
217 Self {
218 route: String::new(),
219 method: "GET".to_string(),
220 description: None,
221 }
222 }
223
224 pub fn route(mut self, route: impl Into<String>) -> Self {
225 self.route = route.into();
226 self
227 }
228
229 pub fn method(mut self, method: impl Into<String>) -> Self {
230 self.method = method.into().to_uppercase();
231 self
232 }
233
234 pub fn description(mut self, desc: impl Into<String>) -> Self {
235 self.description = Some(desc.into());
236 self
237 }
238
239 pub fn get_route(&self) -> &str {
240 &self.route
241 }
242
243 pub fn get_method(&self) -> &str {
244 &self.method
245 }
246
247 pub fn get_description(&self) -> Option<&str> {
248 self.description.as_deref()
249 }
250}
251
252impl Default for EndpointMeta {
253 fn default() -> Self {
254 Self::new()
255 }
256}