Incorporate enabled property

This commit is contained in:
Jeremiah Lowin 2025-06-10 19:32:31 -04:00
commit 7224295f93
2 changed files with 32 additions and 32 deletions

View file

@ -555,7 +555,7 @@ class FastMCP(Generic[LifespanResultT]):
# Get tool, checking first from our tools, then from the mounted servers
if self._tool_manager.has_tool(key):
tool = self._tool_manager.get_tool(key)
if not tool.enabled:
if not self._should_enable_component(tool):
raise DisabledError(f"Tool {key!r} is disabled")
return await self._tool_manager.call_tool(key, arguments)
@ -592,7 +592,7 @@ class FastMCP(Generic[LifespanResultT]):
"""
if self._resource_manager.has_resource(uri):
resource = await self._resource_manager.get_resource(uri)
if not resource.enabled:
if not self._should_enable_component(resource):
raise DisabledError(f"Resource {str(uri)!r} is disabled")
content = await self._resource_manager.read_resource(uri)
return [
@ -646,7 +646,7 @@ class FastMCP(Generic[LifespanResultT]):
# Get prompt, checking first from our prompts, then from the mounted servers
if self._prompt_manager.has_prompt(name):
prompt = self._prompt_manager.get_prompt(name)
if not prompt.enabled:
if not self._should_enable_component(prompt):
raise DisabledError(f"Prompt {name!r} is disabled")
return await self._prompt_manager.render_prompt(name, arguments)

View file

@ -1242,7 +1242,7 @@ class TestShouldIncludeComponent:
"""Test that when no include or exclude filters are provided, always returns True."""
tool = Tool(name="test_tool", tags={"tag1", "tag2"}, parameters={})
mcp = FastMCP(tools=[tool])
result = mcp.should_include_component(tool)
result = mcp._should_enable_component(tool)
assert result is True
def test_exclude_string_tag_present_returns_false(self):
@ -1251,28 +1251,28 @@ class TestShouldIncludeComponent:
name="test_tool", tags={"tag1", "tag2", "exclude_me"}, parameters={}
)
mcp = FastMCP(tools=[tool], exclude_tags={"exclude_me"})
result = mcp.should_include_component(tool)
result = mcp._should_enable_component(tool)
assert result is False
def test_exclude_string_tag_absent_returns_true(self):
"""Test that when an exclude string tag is not present in tags, returns True."""
tool = Tool(name="test_tool", tags={"tag1", "tag2"}, parameters={})
mcp = FastMCP(tools=[tool], exclude_tags={"exclude_me"})
result = mcp.should_include_component(tool)
result = mcp._should_enable_component(tool)
assert result is True
def test_exclude_tuple_all_present_returns_false(self):
"""Test that when all tags in exclude tuple are present, returns False."""
tool = Tool(name="test_tool", tags={"tag1", "tag2", "tag3"}, parameters={})
mcp = FastMCP(tools=[tool], exclude_tags={("tag1", "tag2")})
result = mcp.should_include_component(tool)
result = mcp._should_enable_component(tool)
assert result is False
def test_exclude_tuple_partial_present_returns_true(self):
"""Test that when only some tags in exclude tuple are present, returns True."""
tool = Tool(name="test_tool", tags={"tag1", "tag3"}, parameters={})
mcp = FastMCP(tools=[tool], exclude_tags={("tag1", "tag2")})
result = mcp.should_include_component(tool)
result = mcp._should_enable_component(tool)
assert result is True
def test_multiple_exclude_tags_any_match_returns_false(self):
@ -1281,7 +1281,7 @@ class TestShouldIncludeComponent:
mcp = FastMCP(
tools=[tool], exclude_tags={"not_present", "tag2", "also_not_present"}
)
result = mcp.should_include_component(tool)
result = mcp._should_enable_component(tool)
assert result is False
def test_include_string_tag_present_returns_true(self):
@ -1290,28 +1290,28 @@ class TestShouldIncludeComponent:
name="test_tool", tags={"tag1", "include_me", "tag2"}, parameters={}
)
mcp = FastMCP(tools=[tool], include_tags={"include_me"})
result = mcp.should_include_component(tool)
result = mcp._should_enable_component(tool)
assert result is True
def test_include_string_tag_absent_returns_false(self):
"""Test that when an include string tag is not present in tags, returns False."""
tool = Tool(name="test_tool", tags={"tag1", "tag2"}, parameters={})
mcp = FastMCP(tools=[tool], include_tags={"include_me"})
result = mcp.should_include_component(tool)
result = mcp._should_enable_component(tool)
assert result is False
def test_include_tuple_all_present_returns_true(self):
"""Test that when all tags in include tuple are present, returns True."""
tool = Tool(name="test_tool", tags={"tag1", "tag2", "tag3"}, parameters={})
mcp = FastMCP(tools=[tool], include_tags={("tag1", "tag2")})
result = mcp.should_include_component(tool)
result = mcp._should_enable_component(tool)
assert result is True
def test_include_tuple_partial_present_returns_false(self):
"""Test that when only some tags in include tuple are present, returns False."""
tool = Tool(name="test_tool", tags={"tag1", "tag3"}, parameters={})
mcp = FastMCP(tools=[tool], include_tags={("tag1", "tag2")})
result = mcp.should_include_component(tool)
result = mcp._should_enable_component(tool)
assert result is False
def test_multiple_include_tags_any_match_returns_true(self):
@ -1320,14 +1320,14 @@ class TestShouldIncludeComponent:
mcp = FastMCP(
tools=[tool], include_tags={"not_present", "tag2", "also_not_present"}
)
result = mcp.should_include_component(tool)
result = mcp._should_enable_component(tool)
assert result is True
def test_multiple_include_tags_none_match_returns_false(self):
"""Test that when no include tags match, returns False."""
tool = Tool(name="test_tool", tags={"tag1", "tag2", "tag3"}, parameters={})
mcp = FastMCP(tools=[tool], include_tags={"not_present", "also_not_present"})
result = mcp.should_include_component(tool)
result = mcp._should_enable_component(tool)
assert result is False
def test_exclude_takes_precedence_over_include(self):
@ -1336,7 +1336,7 @@ class TestShouldIncludeComponent:
name="test_tool", tags={"tag1", "tag2", "exclude_me"}, parameters={}
)
mcp = FastMCP(tools=[tool], include_tags={"tag1"}, exclude_tags={"exclude_me"})
result = mcp.should_include_component(tool)
result = mcp._should_enable_component(tool)
assert result is False
def test_mixed_string_and_tuple_exclude_tags(self):
@ -1346,13 +1346,13 @@ class TestShouldIncludeComponent:
name="test_tool", tags={"tag1", "tag2", "tag3", "tag4"}, parameters={}
)
mcp1 = FastMCP(tools=[tool1], exclude_tags={"tag1", ("tag2", "tag3")})
result = mcp1.should_include_component(tool1)
result = mcp1._should_enable_component(tool1)
assert result is False
# Remove tag1, should still be excluded because both tag2 and tag3 are present
tool2 = Tool(name="test_tool", tags={"tag2", "tag3", "tag4"}, parameters={})
mcp2 = FastMCP(tools=[tool2], exclude_tags={"tag1", ("tag2", "tag3")})
result = mcp2.should_include_component(tool2)
result = mcp2._should_enable_component(tool2)
assert result is False
# Remove tag2, should not be excluded
@ -1360,7 +1360,7 @@ class TestShouldIncludeComponent:
name="test_tool", tags={"tag1_removed", "tag3", "tag4"}, parameters={}
)
mcp3 = FastMCP(tools=[tool3], exclude_tags={("tag2", "tag3")})
result = mcp3.should_include_component(tool3)
result = mcp3._should_enable_component(tool3)
assert result is True
def test_mixed_string_and_tuple_include_tags(self):
@ -1368,7 +1368,7 @@ class TestShouldIncludeComponent:
# Should be included because both tag1 and tag2 are present (tuple match)
tool1 = Tool(name="test_tool", tags={"tag1", "tag2"}, parameters={})
mcp1 = FastMCP(tools=[tool1], include_tags={"not_present", ("tag1", "tag2")})
result = mcp1.should_include_component(tool1)
result = mcp1._should_enable_component(tool1)
assert result is True
# Should be included because tag1 is present (string match)
@ -1376,7 +1376,7 @@ class TestShouldIncludeComponent:
mcp2 = FastMCP(
tools=[tool2], include_tags={"tag1", ("not_present1", "not_present2")}
)
result = mcp2.should_include_component(tool2)
result = mcp2._should_enable_component(tool2)
assert result is True
# Should not be included because no conditions are met
@ -1385,7 +1385,7 @@ class TestShouldIncludeComponent:
tools=[tool3],
include_tags={"not_present", ("not_present1", "not_present2")},
)
result = mcp3.should_include_component(tool3)
result = mcp3._should_enable_component(tool3)
assert result is False
def test_complex_scenario_with_both_filters(self):
@ -1399,7 +1399,7 @@ class TestShouldIncludeComponent:
include_tags={"api", ("read", "admin")},
exclude_tags={"sensitive"},
)
result = mcp1.should_include_component(tool1)
result = mcp1._should_enable_component(tool1)
assert result is False
# Remove sensitive tag, should now be included
@ -1409,7 +1409,7 @@ class TestShouldIncludeComponent:
include_tags={"api", ("read", "admin")},
exclude_tags={"sensitive"},
)
result = mcp2.should_include_component(tool2)
result = mcp2._should_enable_component(tool2)
assert result is True
def test_empty_include_exclude_sets(self):
@ -1417,13 +1417,13 @@ class TestShouldIncludeComponent:
# Empty include set means nothing matches
tool1 = Tool(name="test_tool", tags={"tag1", "tag2"}, parameters={})
mcp1 = FastMCP(tools=[tool1], include_tags=set())
result = mcp1.should_include_component(tool1)
result = mcp1._should_enable_component(tool1)
assert result is False
# Empty exclude set means nothing excluded
tool2 = Tool(name="test_tool", tags={"tag1", "tag2"}, parameters={})
mcp2 = FastMCP(tools=[tool2], exclude_tags=set())
result = mcp2.should_include_component(tool2)
result = mcp2._should_enable_component(tool2)
assert result is True
def test_empty_tags_with_filters(self):
@ -1431,24 +1431,24 @@ class TestShouldIncludeComponent:
# With include filters, empty tags should not match
tool1 = Tool(name="test_tool", tags=set(), parameters={})
mcp1 = FastMCP(tools=[tool1], include_tags={"required_tag"})
result = mcp1.should_include_component(tool1)
result = mcp1._should_enable_component(tool1)
assert result is False
# With exclude filters but no include, empty tags should pass
tool2 = Tool(name="test_tool", tags=set(), parameters={})
mcp2 = FastMCP(tools=[tool2], exclude_tags={"bad_tag"})
result = mcp2.should_include_component(tool2)
result = mcp2._should_enable_component(tool2)
assert result is True
# Tuple filters with empty tags
tool3 = Tool(name="test_tool", tags=set(), parameters={})
mcp3 = FastMCP(tools=[tool3], include_tags={("tag1", "tag2")})
result = mcp3.should_include_component(tool3)
result = mcp3._should_enable_component(tool3)
assert result is False
tool4 = Tool(name="test_tool", tags=set(), parameters={})
mcp4 = FastMCP(tools=[tool4], exclude_tags={("tag1", "tag2")})
result = mcp4.should_include_component(tool4)
result = mcp4._should_enable_component(tool4)
assert result is True
def test_single_element_tuples(self):
@ -1456,10 +1456,10 @@ class TestShouldIncludeComponent:
# Single-element tuple should behave like a string
tool1 = Tool(name="test_tool", tags={"tag1", "tag2"}, parameters={})
mcp1 = FastMCP(tools=[tool1], include_tags={("tag1",)})
result = mcp1.should_include_component(tool1)
result = mcp1._should_enable_component(tool1)
assert result is True
tool2 = Tool(name="test_tool", tags={"tag1", "tag2"}, parameters={})
mcp2 = FastMCP(tools=[tool2], exclude_tags={("tag1",)})
result = mcp2.should_include_component(tool2)
result = mcp2._should_enable_component(tool2)
assert result is False