66
77from mcp .server .fastmcp import Context , FastMCP
88from mcp .server .fastmcp .exceptions import ToolError
9- from mcp .server .fastmcp .tools import ToolManager
9+ from mcp .server .fastmcp .tools import Tool , ToolManager
10+ from mcp .server .fastmcp .utilities .func_metadata import ArgModelBase , FuncMetadata
1011from mcp .server .session import ServerSessionT
1112from mcp .shared .context import LifespanContextT
1213from mcp .types import ToolAnnotations
@@ -31,6 +32,35 @@ def add(a: int, b: int) -> int:
3132 assert tool .parameters ["properties" ]["a" ]["type" ] == "integer"
3233 assert tool .parameters ["properties" ]["b" ]["type" ] == "integer"
3334
35+ def test_init_with_tools (self , caplog ):
36+ def add (a : int , b : int ) -> int :
37+ return a + b
38+
39+ class AddArguments (ArgModelBase ):
40+ a : int
41+ b : int
42+
43+ fn_metadata = FuncMetadata (arg_model = AddArguments )
44+
45+ original_tool = Tool (
46+ name = "add" ,
47+ description = "Add two numbers." ,
48+ fn = add ,
49+ fn_metadata = fn_metadata ,
50+ is_async = False ,
51+ parameters = AddArguments .model_json_schema (),
52+ context_kwarg = None ,
53+ annotations = None ,
54+ )
55+ manager = ToolManager (tools = [original_tool ])
56+ saved_tool = manager .get_tool ("add" )
57+ assert saved_tool == original_tool
58+
59+ # warn on duplicate tools
60+ with caplog .at_level (logging .WARNING ):
61+ manager = ToolManager (True , tools = [original_tool , original_tool ])
62+ assert "Tool already exists: add" in caplog .text
63+
3464 @pytest .mark .anyio
3565 async def test_async_function (self ):
3666 """Test registering and running an async function."""
0 commit comments