From df3d4e19ec77e775ab617c277e5a393ac51ba99d Mon Sep 17 00:00:00 2001 From: Taisei Mima Date: Tue, 30 Dec 2025 08:43:51 +0900 Subject: [PATCH] Fix base_url fallback when url is not set (#2776) --- .../server/providers/openapi/components.py | 6 +--- .../providers/openapi/test_comprehensive.py | 32 +++++++++++++++++++ 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/src/fastmcp/server/providers/openapi/components.py b/src/fastmcp/server/providers/openapi/components.py index 404daa82c..a671ff69f 100644 --- a/src/fastmcp/server/providers/openapi/components.py +++ b/src/fastmcp/server/providers/openapi/components.py @@ -108,11 +108,7 @@ class OpenAPITool(Tool): async def run(self, arguments: dict[str, Any]) -> ToolResult: """Execute the HTTP request using RequestDirector.""" try: - base_url = ( - str(self._client.base_url) - if self._client.base_url - else "http://localhost" - ) + base_url = str(self._client.base_url) or "http://localhost" # Build the request using RequestDirector request = self._director.build(self._route, arguments, base_url) diff --git a/tests/server/providers/openapi/test_comprehensive.py b/tests/server/providers/openapi/test_comprehensive.py index 57c81ead3..62b137af7 100644 --- a/tests/server/providers/openapi/test_comprehensive.py +++ b/tests/server/providers/openapi/test_comprehensive.py @@ -512,6 +512,38 @@ class TestOpenAPIComprehensive: assert "123" in str(request.url) assert "users/123" in str(request.url) + async def test_request_uses_localhost_fallback_when_no_base_url( + self, comprehensive_openapi_spec + ): + """Test that tool uses localhost fallback when client has no base_url.""" + mock_client = Mock(spec=httpx.AsyncClient) + mock_client.base_url = httpx.URL("") # Empty URL, same as httpx default + mock_client.headers = None + + mock_response = Mock(spec=Response) + mock_response.status_code = 200 + mock_response.json.return_value = { + "id": 123, + "name": "Test User", + "email": "test@example.com", + } + mock_response.raise_for_status = Mock() + + mock_client.send = AsyncMock(return_value=mock_response) + + server = create_openapi_server( + openapi_spec=comprehensive_openapi_spec, + client=mock_client, + ) + + async with Client(server) as mcp_client: + await mcp_client.call_tool("get_user", {"id": 123}) + + # Verify request was made to localhost fallback + mock_client.send.assert_called_once() + request = mock_client.send.call_args[0][0] + assert str(request.url).startswith("http://localhost") + async def test_complex_request_with_body_and_parameters( self, comprehensive_openapi_spec ):