rust_mcp_sdk/mcp_macros/tool_box.rs
1#[macro_export]
2/// Generates an enum representing a toolbox with mcp tool variants and associated functionality.
3///
4/// **Note:** The macro assumes that tool types provided are annotated with the mcp_tool() macro.
5///
6/// This macro creates:
7/// - An enum with the specified name containing variants for each mcp tool
8/// - A `tools()` function returning a vector of supported tools
9/// - A `TryFrom<CallToolRequestParams>` implementation for converting requests to tool instances
10///
11/// # Arguments
12/// * `$enum_name` - The name to give the generated enum
13/// * `[$($tool:ident),*]` - A comma-separated list of tool types to include in the enum
14///
15///
16/// # Example
17/// ```ignore
18/// tool_box!(FileSystemTools, [ReadFileTool, EditFileTool, SearchFilesTool]);
19/// // Creates:
20/// // pub enum FileSystemTools {
21/// // ReadFileTool(ReadFileTool),
22/// // EditFileTool(EditFileTool),
23/// // SearchFilesTool(SearchFilesTool),
24/// // }
25/// // pub fn tools() -> Vec<Tool> {
26/// // vec![ReadFileTool::tool(), EditFileTool::tool(), SearchFilesTool::tool()]
27/// // }
28///
29/// // impl TryFrom<CallToolRequestParams> for FileSystemTools {
30/// // //.......
31/// // }
32macro_rules! tool_box {
33 ($enum_name:ident, [$($tool:ident),*]) => {
34 #[derive(Debug)]
35 pub enum $enum_name {
36 $(
37 // Just create enum variants for each tool
38 $tool($tool),
39 )*
40 }
41
42 /// Returns the name of the tool as a String
43 impl $enum_name {
44 pub fn tool_name(&self) -> String {
45 match self {
46 $(
47 $enum_name::$tool(_) => $tool::tool_name(),
48 )*
49 }
50 }
51
52 /// Returns a vector containing instances of all supported tools
53 pub fn tools() -> Vec<rust_mcp_sdk::schema::Tool> {
54 vec![
55 $(
56 $tool::tool(),
57 )*
58 ]
59 }
60
61 #[deprecated(since = "0.2.0", note = "Use `tools()` instead.")]
62 pub fn get_tools() -> Vec<rust_mcp_sdk::schema::Tool> {
63 vec![
64 $(
65 $tool::tool(),
66 )*
67 ]
68 }
69 }
70
71
72
73
74 impl TryFrom<rust_mcp_sdk::schema::CallToolRequestParams> for $enum_name {
75 type Error = rust_mcp_sdk::schema::schema_utils::CallToolError;
76
77 /// Attempts to convert a tool request into the appropriate tool variant
78 fn try_from(value: rust_mcp_sdk::schema::CallToolRequestParams) -> Result<Self, Self::Error> {
79 let v = serde_json::to_value(value.arguments.unwrap())
80 .map_err(rust_mcp_sdk::schema::schema_utils::CallToolError::new)?;
81 match value.name {
82 $(
83 name if name == $tool::tool_name().as_str() => {
84 Ok(Self::$tool(serde_json::from_value(v).map_err(rust_mcp_sdk::schema::schema_utils::CallToolError::new)?))
85 }
86 )*
87 _ => {
88 Err(
89 rust_mcp_sdk::schema::schema_utils::CallToolError::unknown_tool(value.name.to_string())
90 )
91 }
92 }
93
94 }
95 }
96 }
97}