Skip to content

Commit ce0cc4f

Browse files
authored
fix: allow optional trailing commas in tool_box macro (#58)
* fix: allow trailing commas in tool_box macro * chore: add tests * chore: add tests
1 parent 5594363 commit ce0cc4f

File tree

3 files changed

+81
-1
lines changed

3 files changed

+81
-1
lines changed

crates/rust-mcp-sdk/src/mcp_macros/tool_box.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
/// // //.......
3131
/// // }
3232
macro_rules! tool_box {
33-
($enum_name:ident, [$($tool:ident),*]) => {
33+
($enum_name:ident, [$($tool:ident),* $(,)?]) => {
3434
#[derive(Debug)]
3535
pub enum $enum_name {
3636
$(

crates/rust-mcp-sdk/tests/common/common.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,55 @@ pub fn sse_event(sse_raw: &str) -> String {
3434
pub fn sse_data(sse_raw: &str) -> String {
3535
sse_raw.replace("data: ", "")
3636
}
37+
38+
pub mod sample_tools {
39+
use rust_mcp_sdk::macros::{mcp_tool, JsonSchema};
40+
use rust_mcp_sdk::schema::{schema_utils::CallToolError, CallToolResult};
41+
42+
//****************//
43+
// SayHelloTool //
44+
//****************//
45+
#[mcp_tool(
46+
name = "say_hello",
47+
description = "Accepts a person's name and says a personalized \"Hello\" to that person",
48+
idempotent_hint = false,
49+
destructive_hint = false,
50+
open_world_hint = false,
51+
read_only_hint = false
52+
)]
53+
#[derive(Debug, ::serde::Deserialize, ::serde::Serialize, JsonSchema)]
54+
pub struct SayHelloTool {
55+
/// The name of the person to greet with a "Hello".
56+
name: String,
57+
}
58+
59+
impl SayHelloTool {
60+
pub fn call_tool(&self) -> Result<CallToolResult, CallToolError> {
61+
let hello_message = format!("Hello, {}!", self.name);
62+
Ok(CallToolResult::text_content(hello_message, None))
63+
}
64+
}
65+
66+
//******************//
67+
// SayGoodbyeTool //
68+
//******************//
69+
#[mcp_tool(
70+
name = "say_goodbye",
71+
description = "Accepts a person's name and says a personalized \"Goodbye\" to that person.",
72+
idempotent_hint = false,
73+
destructive_hint = false,
74+
open_world_hint = false,
75+
read_only_hint = false
76+
)]
77+
#[derive(Debug, ::serde::Deserialize, ::serde::Serialize, JsonSchema)]
78+
pub struct SayGoodbyeTool {
79+
/// The name of the person to say goodbye to.
80+
name: String,
81+
}
82+
impl SayGoodbyeTool {
83+
pub fn call_tool(&self) -> Result<CallToolResult, CallToolError> {
84+
let hello_message = format!("Goodbye, {}!", self.name);
85+
Ok(CallToolResult::text_content(hello_message, None))
86+
}
87+
}
88+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#[path = "common/common.rs"]
2+
pub mod common;
3+
4+
use common::sample_tools::{SayGoodbyeTool, SayHelloTool};
5+
use rust_mcp_sdk::tool_box;
6+
7+
// Define tool box without trailing comma
8+
tool_box!(FileSystemToolsNoComma, [SayHelloTool, SayGoodbyeTool]);
9+
10+
// Define tool box with trailing comma
11+
// Related Issue: https://github.com/rust-mcp-stack/rust-mcp-sdk/issues/57
12+
tool_box!(FileSystemTools, [SayHelloTool, SayGoodbyeTool,]);
13+
14+
#[test]
15+
fn test_tools_with_trailing_comma() {
16+
let tools = FileSystemTools::tools();
17+
assert_eq!(tools.len(), 2);
18+
assert_eq!(tools[0].name, "say_hello");
19+
assert_eq!(tools[1].name, "say_goodbye");
20+
}
21+
22+
#[test]
23+
fn test_tools_without_trailing_comma() {
24+
let tools = FileSystemToolsNoComma::tools();
25+
assert_eq!(tools.len(), 2);
26+
assert_eq!(tools[0].name, "say_hello");
27+
assert_eq!(tools[1].name, "say_goodbye");
28+
}

0 commit comments

Comments
 (0)