Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions src/itential_mcp/server/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,10 +152,17 @@ def parse_tags(tags: str | None) -> list[str] | None:
instructions=inspect.cleandoc(INSTRUCTIONS),
lifespan=lifespan,
auth=auth_provider,
include_tags=parse_tags(self.config.server.include_tags),
exclude_tags=parse_tags(self.config.server.exclude_tags),
)

# Apply tag filtering after server creation (FastMCP 3.x API)
include_tags = parse_tags(self.config.server.include_tags)
exclude_tags = parse_tags(self.config.server.exclude_tags)

if include_tags:
self.mcp.enable(tags=set(include_tags), only=True)
if exclude_tags:
self.mcp.disable(tags=set(exclude_tags))

logger = logging.get_logger()

self.mcp.add_middleware(ErrorHandlingMiddleware(logger=logger))
Expand Down
21 changes: 15 additions & 6 deletions tests/test_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -685,11 +685,13 @@ async def empty_aiter():
name="Itential Platform MCP",
instructions=server_module.inspect.cleandoc(server_module.INSTRUCTIONS),
lifespan=server_module.lifespan,
include_tags=["system"],
exclude_tags=["deprecated"],
auth=None,
)

# Verify tag filtering was applied after creation
mock_mcp.enable.assert_called_once_with(tags={"system"}, only=True)
mock_mcp.disable.assert_called_once_with(tags={"deprecated"})

# Verify tool registration
mock_mcp.tool.assert_called_once_with(
mock_func, tags={"system", "test", "default"}
Expand Down Expand Up @@ -1026,7 +1028,7 @@ async def test_init_server_auth_transport_incompatibility(
@pytest.mark.asyncio
@patch("itential_mcp.server.auth.build_auth_provider")
async def test_init_server_parse_tags_with_none(self, mock_auth_builder):
"""Test __init_server__ with None tags returns None"""
"""Test __init_server__ with None tags does not call enable/disable"""
from itential_mcp.config.models import Config, ServerConfig, AuthConfig

mock_config = Config(
Expand All @@ -1044,12 +1046,19 @@ async def test_init_server_parse_tags_with_none(self, mock_auth_builder):
server_instance = server_module.Server(mock_config)

with patch("itential_mcp.server.server.FastMCP") as mock_fastmcp:
mock_mcp = MagicMock()
mock_fastmcp.return_value = mock_mcp

await server_instance.__init_server__()

# Verify FastMCP was called with None for tags
# Verify tags are not passed to FastMCP constructor
call_kwargs = mock_fastmcp.call_args.kwargs
assert call_kwargs["include_tags"] is None
assert call_kwargs["exclude_tags"] is None
assert "include_tags" not in call_kwargs
assert "exclude_tags" not in call_kwargs

# Verify enable/disable were not called when tags are None
mock_mcp.enable.assert_not_called()
mock_mcp.disable.assert_not_called()

@pytest.mark.asyncio
@patch("itential_mcp.server.auth.build_auth_provider")
Expand Down