mirror of
https://github.com/PrefectHQ/fastmcp.git
synced 2026-08-23 14:04:18 +02:00
Remove OpenAPI timeout parameter, make client optional, surface timeout errors (#3067)
* Remove OpenAPI timeout param, make client optional, surface timeout errors * Close auto-created httpx client via provider lifespan
This commit is contained in:
parent
fe432de156
commit
5fd41b2e15
7 changed files with 102 additions and 43 deletions
|
|
@ -739,3 +739,27 @@ class TestOpenAPIComprehensive:
|
|||
assert provider is not None
|
||||
assert hasattr(provider, "_director")
|
||||
assert hasattr(provider, "_spec")
|
||||
|
||||
async def test_timeout_error_produces_useful_message(
|
||||
self, comprehensive_openapi_spec
|
||||
):
|
||||
"""ReadTimeout should surface a clear error, not an empty string."""
|
||||
mock_client = Mock(spec=httpx.AsyncClient)
|
||||
mock_client.base_url = "https://api.example.com"
|
||||
mock_client.headers = None
|
||||
|
||||
# httpx internally raises ReadTimeout with an empty message
|
||||
mock_client.send = AsyncMock(side_effect=httpx.ReadTimeout(""))
|
||||
|
||||
server = create_openapi_server(
|
||||
openapi_spec=comprehensive_openapi_spec,
|
||||
client=mock_client,
|
||||
)
|
||||
|
||||
async with Client(server) as mcp_client:
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
await mcp_client.call_tool("get_user", {"id": 1})
|
||||
|
||||
error_message = str(exc_info.value)
|
||||
assert "timed out" in error_message
|
||||
assert "ReadTimeout" in error_message
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import pytest
|
|||
from fastmcp import FastMCP
|
||||
from fastmcp.client import Client
|
||||
from fastmcp.server.providers.openapi import OpenAPIProvider
|
||||
from fastmcp.server.providers.openapi.provider import DEFAULT_TIMEOUT
|
||||
|
||||
|
||||
class TestOpenAPIProviderBasicFunctionality:
|
||||
|
|
@ -146,16 +147,21 @@ class TestOpenAPIProviderBasicFunctionality:
|
|||
assert get_user_tool is not None
|
||||
assert get_user_tool.description is not None
|
||||
|
||||
def test_provider_with_timeout(self, simple_openapi_spec):
|
||||
"""Test provider initialization with timeout setting."""
|
||||
client = httpx.AsyncClient(base_url="https://api.example.com")
|
||||
provider = OpenAPIProvider(
|
||||
openapi_spec=simple_openapi_spec,
|
||||
client=client,
|
||||
timeout=30.0,
|
||||
)
|
||||
def test_provider_creates_default_client_from_spec(self, simple_openapi_spec):
|
||||
"""Test that omitting client creates one from the spec's servers URL."""
|
||||
provider = OpenAPIProvider(openapi_spec=simple_openapi_spec)
|
||||
assert str(provider._client.base_url).rstrip("/") == "https://api.example.com"
|
||||
assert provider._client.timeout == httpx.Timeout(DEFAULT_TIMEOUT)
|
||||
|
||||
assert provider._timeout == 30.0
|
||||
def test_provider_default_client_requires_servers(self):
|
||||
"""Test that omitting client without servers in spec raises."""
|
||||
spec = {
|
||||
"openapi": "3.0.0",
|
||||
"info": {"title": "No Servers", "version": "1.0.0"},
|
||||
"paths": {},
|
||||
}
|
||||
with pytest.raises(ValueError, match="No server URL"):
|
||||
OpenAPIProvider(openapi_spec=spec)
|
||||
|
||||
def test_provider_with_empty_spec(self):
|
||||
"""Test provider with minimal OpenAPI spec."""
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue