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}