1use serde_json::{json, Value};
7
8#[derive(Debug, Clone)]
10pub struct ToolParam {
11 pub name: String,
12 pub description: String,
13 pub param_type: ParamType,
14 pub required: bool,
15}
16
17#[derive(Debug, Clone)]
19pub enum ParamType {
20 String,
21 Integer,
22 Number,
23 Boolean,
24 Object,
25 Array,
26}
27
28impl ParamType {
29 pub fn to_json_type(&self) -> &'static str {
31 match self {
32 ParamType::String => "string",
33 ParamType::Integer => "integer",
34 ParamType::Number => "number",
35 ParamType::Boolean => "boolean",
36 ParamType::Object => "object",
37 ParamType::Array => "array",
38 }
39 }
40}
41
42pub type ToolHandler = fn(&Value) -> Result<Value, String>;
47
48#[derive(Debug, Clone)]
52pub struct Tool {
53 pub active: bool,
54 pub name: String,
55 pub description: String,
56 pub params: Vec<ToolParam>,
57 pub handler: ToolHandler,
58}
59
60impl Tool {
61 pub fn builder(name: &str, description: &str, active: bool) -> ToolBuilder {
71 ToolBuilder {
72 active,
73 name: name.to_string(),
74 description: description.to_string(),
75 params: Vec::new(),
76 }
77 }
78
79 pub fn to_json_schema(&self) -> Value {
94 let mut properties = serde_json::Map::new();
95 let mut required = Vec::new();
96
97 for param in &self.params {
98 properties.insert(
99 param.name.clone(),
100 json!({
101 "type": param.param_type.to_json_type(),
102 "description": param.description
103 })
104 );
105
106 if param.required {
107 required.push(param.name.clone());
108 }
109 }
110
111 json!({
112 "name": self.name,
113 "description": self.description,
114 "inputSchema": {
115 "type": "object",
116 "properties": properties,
117 "required": required
118 }
119 })
120 }
121}
122
123pub struct ToolBuilder {
125 active: bool,
126 name: String,
127 description: String,
128 params: Vec<ToolParam>,
129}
130
131impl ToolBuilder {
132 pub fn param_string(mut self, name: &str, description: &str, required: bool) -> Self {
139 self.params.push(ToolParam {
140 name: name.to_string(),
141 description: description.to_string(),
142 param_type: ParamType::String,
143 required,
144 });
145 self
146 }
147
148 pub fn param_i64(mut self, name: &str, description: &str, required: bool) -> Self {
150 self.params.push(ToolParam {
151 name: name.to_string(),
152 description: description.to_string(),
153 param_type: ParamType::Integer,
154 required,
155 });
156 self
157 }
158
159 pub fn param_f64(mut self, name: &str, description: &str, required: bool) -> Self {
161 self.params.push(ToolParam {
162 name: name.to_string(),
163 description: description.to_string(),
164 param_type: ParamType::Number,
165 required,
166 });
167 self
168 }
169
170 pub fn param_bool(mut self, name: &str, description: &str, required: bool) -> Self {
172 self.params.push(ToolParam {
173 name: name.to_string(),
174 description: description.to_string(),
175 param_type: ParamType::Boolean,
176 required,
177 });
178 self
179 }
180
181 pub fn param_object(mut self, name: &str, description: &str, required: bool) -> Self {
183 self.params.push(ToolParam {
184 name: name.to_string(),
185 description: description.to_string(),
186 param_type: ParamType::Object,
187 required,
188 });
189 self
190 }
191
192 pub fn param_array(mut self, name: &str, description: &str, required: bool) -> Self {
194 self.params.push(ToolParam {
195 name: name.to_string(),
196 description: description.to_string(),
197 param_type: ParamType::Array,
198 required,
199 });
200 self
201 }
202
203 pub fn handler(self, handler: ToolHandler) -> Tool {
207 Tool {
208 active: self.active,
209 name: self.name,
210 description: self.description,
211 params: self.params,
212 handler,
213 }
214 }
215}
216