William Easton commited on
Commit
c9434ed
·
unverified ·
1 Parent(s): 246086f

Manually set _key after model_copy (#1357)

Browse files
src/fastmcp/utilities/components.py CHANGED
@@ -92,7 +92,12 @@ class FastMCPComponent(FastMCPBaseModel):
92
  return meta or None
93
 
94
  def with_key(self, key: str) -> Self:
95
- return self.model_copy(update={"_key": key})
 
 
 
 
 
96
 
97
  def __eq__(self, other: object) -> bool:
98
  if type(self) is not type(other):
 
92
  return meta or None
93
 
94
  def with_key(self, key: str) -> Self:
95
+ # `model_copy` has an `update` parameter but it doesn't work for certain private attributes
96
+ # https://github.com/pydantic/pydantic/issues/12116
97
+ # So we manually set the private attribute here instead
98
+ copy = self.model_copy()
99
+ copy._key = key
100
+ return copy
101
 
102
  def __eq__(self, other: object) -> bool:
103
  if type(self) is not type(other):
tests/server/test_mount.py CHANGED
@@ -8,6 +8,8 @@ from fastmcp import FastMCP
8
  from fastmcp.client import Client
9
  from fastmcp.client.transports import FastMCPTransport, SSETransport
10
  from fastmcp.server.proxy import FastMCPProxy
 
 
11
  from fastmcp.utilities.tests import caplog_for_fastmcp
12
 
13
 
@@ -18,22 +20,29 @@ class TestBasicMount:
18
  """Test mounting a simple server and accessing its tool."""
19
  # Create main app and sub-app
20
  main_app = FastMCP("MainApp")
21
- sub_app = FastMCP("SubApp")
22
 
23
  # Add a tool to the sub-app
24
- @sub_app.tool
25
- def sub_tool() -> str:
26
  return "This is from the sub app"
27
 
 
 
 
 
 
 
 
 
28
  # Mount the sub-app to the main app
29
  main_app.mount(sub_app, "sub")
30
 
31
  # Get tools from main app, should include sub_app's tools
32
  tools = await main_app.get_tools()
33
- assert "sub_sub_tool" in tools
 
34
 
35
  async with Client(main_app) as client:
36
- result = await client.call_tool("sub_sub_tool", {})
37
  assert result.data == "This is from the sub app"
38
 
39
  async def test_mount_with_custom_separator(self):
 
8
  from fastmcp.client import Client
9
  from fastmcp.client.transports import FastMCPTransport, SSETransport
10
  from fastmcp.server.proxy import FastMCPProxy
11
+ from fastmcp.tools.tool import Tool
12
+ from fastmcp.tools.tool_transform import TransformedTool
13
  from fastmcp.utilities.tests import caplog_for_fastmcp
14
 
15
 
 
20
  """Test mounting a simple server and accessing its tool."""
21
  # Create main app and sub-app
22
  main_app = FastMCP("MainApp")
 
23
 
24
  # Add a tool to the sub-app
25
+ def tool() -> str:
 
26
  return "This is from the sub app"
27
 
28
+ sub_tool = Tool.from_function(tool)
29
+
30
+ transformed_tool = TransformedTool.from_tool(
31
+ name="transformed_tool", tool=sub_tool
32
+ )
33
+
34
+ sub_app = FastMCP("SubApp", tools=[transformed_tool, sub_tool])
35
+
36
  # Mount the sub-app to the main app
37
  main_app.mount(sub_app, "sub")
38
 
39
  # Get tools from main app, should include sub_app's tools
40
  tools = await main_app.get_tools()
41
+ assert "sub_tool" in tools
42
+ assert "sub_transformed_tool" in tools
43
 
44
  async with Client(main_app) as client:
45
+ result = await client.call_tool("sub_tool", {})
46
  assert result.data == "This is from the sub app"
47
 
48
  async def test_mount_with_custom_separator(self):