Jeremiah Lowin commited on
Commit
dce143d
·
1 Parent(s): 5a29d74

Update tool manager param to key

Browse files
src/fastmcp/server/server.py CHANGED
@@ -186,7 +186,7 @@ class FastMCP(Generic[LifespanResultT]):
186
  self._mcp_server.list_resource_templates()(self._mcp_list_resource_templates)
187
 
188
  def get_tools(self) -> dict[str, Tool]:
189
- """Get all registered tools, keyed by registered name."""
190
  return self._tool_manager.get_tools()
191
 
192
  def list_tools(self) -> list[Tool]:
 
186
  self._mcp_server.list_resource_templates()(self._mcp_list_resource_templates)
187
 
188
  def get_tools(self) -> dict[str, Tool]:
189
+ """Get all registered tools, indexed by registered key."""
190
  return self._tool_manager.get_tools()
191
 
192
  def list_tools(self) -> list[Tool]:
src/fastmcp/tools/tool_manager.py CHANGED
@@ -41,7 +41,7 @@ class ToolManager:
41
  return self._tools.get(name)
42
 
43
  def get_tools(self) -> dict[str, Tool]:
44
- """Get all registered tools, keyed by registered name."""
45
  return self._tools
46
 
47
  def list_tools(self) -> list[Tool]:
@@ -50,7 +50,7 @@ class ToolManager:
50
 
51
  def list_mcp_tools(self) -> list[MCPTool]:
52
  """List all registered tools in the format expected by the low-level MCP server."""
53
- return [tool.to_mcp_tool(name=name) for name, tool in self._tools.items()]
54
 
55
  def add_tool_from_fn(
56
  self,
@@ -63,34 +63,34 @@ class ToolManager:
63
  tool = Tool.from_function(fn, name=name, description=description, tags=tags)
64
  return self.add_tool(tool)
65
 
66
- def add_tool(self, tool: Tool, name: str | None = None) -> Tool:
67
  """Register a tool with the server."""
68
- name = name or tool.name
69
- existing = self._tools.get(name)
70
  if existing:
71
  if self.duplicate_behavior == "warn":
72
- logger.warning(f"Tool already exists: {name}")
73
- self._tools[name] = tool
74
  elif self.duplicate_behavior == "replace":
75
- self._tools[name] = tool
76
  elif self.duplicate_behavior == "error":
77
- raise ValueError(f"Tool already exists: {name}")
78
  elif self.duplicate_behavior == "ignore":
79
  return existing
80
  else:
81
- self._tools[name] = tool
82
  return tool
83
 
84
  async def call_tool(
85
  self,
86
- name: str,
87
  arguments: dict[str, Any],
88
  context: Context[ServerSessionT, LifespanContextT] | None = None,
89
  ) -> Any:
90
  """Call a tool by name with arguments."""
91
- tool = self.get_tool(name)
92
  if not tool:
93
- raise ToolError(f"Unknown tool: {name}")
94
 
95
  return await tool.run(arguments, context=context)
96
 
@@ -110,5 +110,5 @@ class ToolManager:
110
  """
111
  for name, tool in tool_manager._tools.items():
112
  prefixed_name = f"{prefix}{name}" if prefix else name
113
- self.add_tool(tool, name=prefixed_name)
114
  logger.debug(f'Imported tool "{tool.name}" as "{prefixed_name}"')
 
41
  return self._tools.get(name)
42
 
43
  def get_tools(self) -> dict[str, Tool]:
44
+ """Get all registered tools, indexed by registered key."""
45
  return self._tools
46
 
47
  def list_tools(self) -> list[Tool]:
 
50
 
51
  def list_mcp_tools(self) -> list[MCPTool]:
52
  """List all registered tools in the format expected by the low-level MCP server."""
53
+ return [tool.to_mcp_tool(name=key) for key, tool in self._tools.items()]
54
 
55
  def add_tool_from_fn(
56
  self,
 
63
  tool = Tool.from_function(fn, name=name, description=description, tags=tags)
64
  return self.add_tool(tool)
65
 
66
+ def add_tool(self, tool: Tool, key: str | None = None) -> Tool:
67
  """Register a tool with the server."""
68
+ key = key or tool.name
69
+ existing = self._tools.get(key)
70
  if existing:
71
  if self.duplicate_behavior == "warn":
72
+ logger.warning(f"Tool already exists: {key}")
73
+ self._tools[key] = tool
74
  elif self.duplicate_behavior == "replace":
75
+ self._tools[key] = tool
76
  elif self.duplicate_behavior == "error":
77
+ raise ValueError(f"Tool already exists: {key}")
78
  elif self.duplicate_behavior == "ignore":
79
  return existing
80
  else:
81
+ self._tools[key] = tool
82
  return tool
83
 
84
  async def call_tool(
85
  self,
86
+ key: str,
87
  arguments: dict[str, Any],
88
  context: Context[ServerSessionT, LifespanContextT] | None = None,
89
  ) -> Any:
90
  """Call a tool by name with arguments."""
91
+ tool = self.get_tool(key)
92
  if not tool:
93
+ raise ToolError(f"Unknown tool: {key}")
94
 
95
  return await tool.run(arguments, context=context)
96
 
 
110
  """
111
  for name, tool in tool_manager._tools.items():
112
  prefixed_name = f"{prefix}{name}" if prefix else name
113
+ self.add_tool(tool, key=prefixed_name)
114
  logger.debug(f'Imported tool "{tool.name}" as "{prefixed_name}"')
tests/tools/test_tool_manager.py CHANGED
@@ -585,7 +585,7 @@ class TestCustomToolNames:
585
  tool = Tool.from_function(fn, name="my_tool")
586
  manager = ToolManager()
587
  # Store it under a different name
588
- manager.add_tool(tool, name="proxy_tool")
589
  # The tool is accessible under the storage name
590
  stored = manager.get_tool("proxy_tool")
591
  assert stored is not None
@@ -682,7 +682,7 @@ class TestCustomToolNames:
682
 
683
  tool = Tool.from_function(fn, name="my_tool")
684
  manager = ToolManager()
685
- manager.add_tool(tool, name="proxy_tool")
686
  mcp_tools = manager.list_mcp_tools()
687
  assert len(mcp_tools) == 1
688
  assert mcp_tools[0].name == "proxy_tool"
 
585
  tool = Tool.from_function(fn, name="my_tool")
586
  manager = ToolManager()
587
  # Store it under a different name
588
+ manager.add_tool(tool, key="proxy_tool")
589
  # The tool is accessible under the storage name
590
  stored = manager.get_tool("proxy_tool")
591
  assert stored is not None
 
682
 
683
  tool = Tool.from_function(fn, name="my_tool")
684
  manager = ToolManager()
685
+ manager.add_tool(tool, key="proxy_tool")
686
  mcp_tools = manager.list_mcp_tools()
687
  assert len(mcp_tools) == 1
688
  assert mcp_tools[0].name == "proxy_tool"