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
62
63
64
65 impl TryFrom<rust_mcp_sdk::schema::CallToolRequestParams> for $enum_name {
66 type Error = rust_mcp_sdk::schema::schema_utils::CallToolError;
67
68 /// Attempts to convert a tool request into the appropriate tool variant
69 fn try_from(value: rust_mcp_sdk::schema::CallToolRequestParams) -> Result<Self, Self::Error> {
70 let v = serde_json::to_value(value.arguments.unwrap())
71 .map_err(rust_mcp_sdk::schema::schema_utils::CallToolError::new)?;
72 match value.name {
73 $(
74 name if name == $tool::tool_name().as_str() => {
75 Ok(Self::$tool(serde_json::from_value(v).map_err(rust_mcp_sdk::schema::schema_utils::CallToolError::new)?))
76 }
77 )*
78 _ => {
79 Err(
80 rust_mcp_sdk::schema::schema_utils::CallToolError::unknown_tool(value.name.to_string())
81 )
82 }
83 }
84
85 }
86 }
87 }
88}