PrefectHQ/fastmcp · error · ValueError
No server URL found in OpenAPI spec. Either add a 'servers'
Error message
No server URL found in OpenAPI spec. Either add a 'servers' entry to the spec or provide an httpx2.AsyncClient explicitly.
What it means
When no explicit httpx.AsyncClient is supplied, the provider tries to derive a base URL from the spec's first servers entry; if servers is missing/empty or the first entry has no url, it raises this ValueError telling you to add a servers entry or pass a client explicitly.
Source
Thrown at fastmcp_slim/fastmcp/server/providers/openapi/provider.py:193
route_tags = set(route.tags) | route_map.mcp_tags | (tags or set())
if route_type == MCPType.TOOL:
self._create_openapi_tool(route, component_name, tags=route_tags)
elif route_type == MCPType.RESOURCE:
self._create_openapi_resource(route, component_name, tags=route_tags)
elif route_type == MCPType.RESOURCE_TEMPLATE:
self._create_openapi_template(route, component_name, tags=route_tags)
elif route_type == MCPType.EXCLUDE:
logger.debug(f"Excluding route: {route.method} {route.path}")
logger.debug(f"Created OpenAPIProvider with {len(http_routes)} routes")
@classmethod
def _create_default_client(cls, openapi_spec: dict[str, Any]) -> httpx2.AsyncClient:
"""Create a default httpx client from the OpenAPI spec's server URL."""
servers = openapi_spec.get("servers", [])
if not servers or not servers[0].get("url"):
raise ValueError(
"No server URL found in OpenAPI spec. Either add a 'servers' "
"entry to the spec or provide an httpx2.AsyncClient explicitly."
)
base_url = servers[0]["url"]
variables = servers[0].get("variables", {})
for name, var in variables.items():
base_url = base_url.replace(f"{{{name}}}", var.get("default", ""))
return httpx2.AsyncClient(base_url=base_url, timeout=DEFAULT_TIMEOUT)
@asynccontextmanager
async def lifespan(self) -> AsyncIterator[None]:
"""Manage the lifecycle of the auto-created httpx client."""
if self._owns_client:
async with self._client:
yield
else:
yield
View on GitHub (pinned to 1f02114297)
Solutions
- Add a servers entry to the spec: spec['servers'] = [{'url': 'https://api.example.com'}]
- Pass an explicit client: FastMCPProvider(spec, client=httpx.AsyncClient(base_url='https://api.example.com'))
- Convert Swagger 2.0 host/basePath to an OpenAPI 3 servers entry
Example fix
// before
spec = {'openapi': '3.1.0', 'paths': {...}}
provider = FastMCPProvider(spec)
// after
spec = {'openapi': '3.1.0', 'servers': [{'url': 'https://api.example.com'}], 'paths': {...}}
provider = FastMCPProvider(spec) Defensive patterns
Strategy: validation
Validate before calling
def ensure_server_url(spec: dict) -> dict:
servers = spec.get('servers')
if not servers or not servers[0].get('url'):
raise ValueError('spec needs a servers[0].url before creating a provider')
return spec Type guard
def has_server_url(spec: object) -> bool:
return (
isinstance(spec, dict)
and bool(spec.get('servers'))
and bool(spec['servers'][0].get('url'))
) Try / catch
try:
provider = FastMCPProvider(spec)
except ValueError as e:
if 'No server URL found' in str(e):
provider = FastMCPProvider(spec, client=httpx.AsyncClient(base_url=DEFAULT_BASE_URL))
else:
raise Prevention
- Always include a servers entry in specs used with FastMCP
- Pass an explicit AsyncClient when the spec lacks servers
- Migrate Swagger 2.0 host/basePath to OpenAPI 3 servers
When it happens
Trigger: Constructing OpenAPIProvider/FastMCPProvider from a spec dict without a 'servers' key (or with servers: [{}]) and without providing a client.
Common situations: Specs written for Swagger 2.0 use 'host'/'basePath' instead of 'servers'; specs trimmed down for testing with servers removed; relative server URLs used with an assumed host.
Related errors
- HTTP error {response.status_code}: {response.reason_phrase}
- HTTP request timed out ({type(exc).__name__})
- Request error ({type(exc).__name__}): {exc!s}
- Invalid OpenAPI specification: {e}
- Horizon returned an invalid organization cursor
AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29).
Data as JSON: /api/errors/b34b50495bff1ee4.
Report an issue: GitHub.