feat: add ability to remove tools (#1322)
Co-authored-by: David Soria Parra <167242713+dsp-ant@users.noreply.github.com> Co-authored-by: Felix Weinberger <3823880+felixweinberger@users.noreply.github.com> Co-authored-by: Max Isbey <224885523+maxisbey@users.noreply.github.com> Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
parent
df3e428ee8
commit
b8e758b02b
1 changed files with 204 additions and 0 deletions
|
|
@ -603,6 +603,80 @@ class TestServerTools:
|
|||
assert result.isError is False
|
||||
assert result.structuredContent == {"theme": "dark", "language": "en", "timezone": "UTC"}
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_remove_tool(self):
|
||||
"""Test removing a tool from the server."""
|
||||
mcp = FastMCP()
|
||||
mcp.add_tool(tool_fn)
|
||||
|
||||
# Verify tool exists
|
||||
assert len(mcp._tool_manager.list_tools()) == 1
|
||||
|
||||
# Remove the tool
|
||||
mcp.remove_tool("tool_fn")
|
||||
|
||||
# Verify tool is removed
|
||||
assert len(mcp._tool_manager.list_tools()) == 0
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_remove_nonexistent_tool(self):
|
||||
"""Test that removing a non-existent tool raises ToolError."""
|
||||
from mcp.server.fastmcp.exceptions import ToolError
|
||||
|
||||
mcp = FastMCP()
|
||||
|
||||
with pytest.raises(ToolError, match="Unknown tool: nonexistent"):
|
||||
mcp.remove_tool("nonexistent")
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_remove_tool_and_list(self):
|
||||
"""Test that a removed tool doesn't appear in list_tools."""
|
||||
mcp = FastMCP()
|
||||
mcp.add_tool(tool_fn)
|
||||
mcp.add_tool(error_tool_fn)
|
||||
|
||||
# Verify both tools exist
|
||||
async with client_session(mcp._mcp_server) as client:
|
||||
tools = await client.list_tools()
|
||||
assert len(tools.tools) == 2
|
||||
tool_names = [t.name for t in tools.tools]
|
||||
assert "tool_fn" in tool_names
|
||||
assert "error_tool_fn" in tool_names
|
||||
|
||||
# Remove one tool
|
||||
mcp.remove_tool("tool_fn")
|
||||
|
||||
# Verify only one tool remains
|
||||
async with client_session(mcp._mcp_server) as client:
|
||||
tools = await client.list_tools()
|
||||
assert len(tools.tools) == 1
|
||||
assert tools.tools[0].name == "error_tool_fn"
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_remove_tool_and_call(self):
|
||||
"""Test that calling a removed tool fails appropriately."""
|
||||
mcp = FastMCP()
|
||||
mcp.add_tool(tool_fn)
|
||||
|
||||
# Verify tool works before removal
|
||||
async with client_session(mcp._mcp_server) as client:
|
||||
result = await client.call_tool("tool_fn", {"x": 1, "y": 2})
|
||||
assert not result.isError
|
||||
content = result.content[0]
|
||||
assert isinstance(content, TextContent)
|
||||
assert content.text == "3"
|
||||
|
||||
# Remove the tool
|
||||
mcp.remove_tool("tool_fn")
|
||||
|
||||
# Verify calling removed tool returns an error
|
||||
async with client_session(mcp._mcp_server) as client:
|
||||
result = await client.call_tool("tool_fn", {"x": 1, "y": 2})
|
||||
assert result.isError
|
||||
content = result.content[0]
|
||||
assert isinstance(content, TextContent)
|
||||
assert "Unknown tool" in content.text
|
||||
|
||||
|
||||
class TestServerResources:
|
||||
@pytest.mark.anyio
|
||||
|
|
|
|||
Loading…
Reference in a new issue