Skip to content

Commit f18358b

Browse files
extend mcp tests
1 parent e11ab83 commit f18358b

File tree

1 file changed

+37
-0
lines changed

1 file changed

+37
-0
lines changed

tests/unit/test_mcp/test_mcp_server.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
1+
from __future__ import annotations
2+
3+
14
from unittest.mock import MagicMock, patch
25

36
import pytest
47

8+
from fastmcp.client import Client
9+
from fastapi.routing import APIRoute
10+
511
from src.api import app
612
from src.mcp.server import build_mcp
713

@@ -27,3 +33,34 @@ def test_build_mcp_uses_fastapi_adapter():
2733
again = build_mcp(app)
2834
assert again is mock_mcp
2935
mock_factory.assert_called_once()
36+
37+
38+
@pytest.mark.asyncio
39+
async def test_mcp_tools_cover_registered_routes():
40+
mcp_server = build_mcp(app)
41+
42+
async with Client(mcp_server) as client:
43+
tools = await client.list_tools()
44+
45+
tool_by_name = {tool.name: tool for tool in tools}
46+
47+
expected = {}
48+
for route in app.routes:
49+
if not isinstance(route, APIRoute) or not route.include_in_schema:
50+
continue
51+
tag = route.tags[0].lower()
52+
tool_name = f"{route.name}_{tag}s"
53+
expected[tool_name] = route
54+
55+
assert set(tool_by_name) == set(
56+
expected
57+
), "Every FastAPI route should be exported as an MCP tool"
58+
59+
for tool_name, route in expected.items():
60+
schema = tool_by_name[tool_name].inputSchema or {}
61+
required = set(schema.get('required', []))
62+
path_params = {param.name for param in route.dependant.path_params}
63+
# Path parameters must be represented as required MCP tool arguments
64+
assert path_params.issubset(
65+
required
66+
), f"{tool_name} missing path params {path_params - required}"

0 commit comments

Comments
 (0)