Remove deprecated fastmcp.server.openapi shim + FastMCPOpenAPI (3.0)

This commit is contained in:
Jeremiah Lowin 2026-07-06 21:22:49 -04:00
commit 497ed2ea00
No known key found for this signature in database
7 changed files with 9 additions and 488 deletions

View file

@ -355,10 +355,10 @@ main.mount(subserver)
**Module import paths for proxy and OpenAPI**
The proxy and OpenAPI modules have moved under `providers` to reflect v3's provider-based architecture:
The proxy and OpenAPI modules moved under `providers` to reflect v3's provider-based architecture. The old `fastmcp.server.proxy` and `fastmcp.server.openapi` compatibility shims were **removed in 4.0** — import from the `providers` location instead:
```python test="skip"
# Deprecated
# Removed in 4.0
from fastmcp.server.proxy import FastMCPProxy
from fastmcp.server.openapi import FastMCPOpenAPI
@ -367,10 +367,10 @@ from fastmcp.server.providers.proxy import FastMCPProxy
from fastmcp.server.providers.openapi import OpenAPIProvider
```
`FastMCPOpenAPI` itself is deprecated — use `FastMCP` with an `OpenAPIProvider` instead:
`FastMCPOpenAPI` was **removed in 4.0** — use `FastMCP` with an `OpenAPIProvider` instead:
```python test="skip"
# Deprecated
# Removed in 4.0
from fastmcp.server.openapi import FastMCPOpenAPI
server = FastMCPOpenAPI(spec, client)
@ -406,14 +406,16 @@ proxy = create_proxy("http://example.com/mcp")
### OpenAPI Parser Promotion
The experimental OpenAPI parser is now standard. Update imports:
The experimental OpenAPI parser is now standard. The `fastmcp.experimental.server.openapi` and `fastmcp.server.openapi` shims were both **removed in 4.0** — use `FastMCP` with an `OpenAPIProvider` instead:
```python test="skip"
# Before
from fastmcp.experimental.server.openapi import FastMCPOpenAPI
# After
from fastmcp.server.openapi import FastMCPOpenAPI
# After (removed in 4.0 — use OpenAPIProvider)
from fastmcp import FastMCP
from fastmcp.server.providers.openapi import OpenAPIProvider
server = FastMCP("my_api", providers=[OpenAPIProvider(spec, client)])
```
### Removed Deprecated Features

View file

@ -1,57 +0,0 @@
"""OpenAPI server implementation for FastMCP.
.. deprecated::
This module is deprecated. Import from fastmcp.server.providers.openapi instead.
The recommended approach is to use OpenAPIProvider with FastMCP:
from fastmcp import FastMCP
from fastmcp.server.providers.openapi import OpenAPIProvider
import httpx
client = httpx.AsyncClient(base_url="https://api.example.com")
provider = OpenAPIProvider(openapi_spec=spec, client=client)
mcp = FastMCP("My API Server")
mcp.add_provider(provider)
FastMCPOpenAPI is still available but deprecated.
"""
import warnings
from fastmcp.exceptions import FastMCPDeprecationWarning
warnings.warn(
"fastmcp.server.openapi is deprecated. "
"Import from fastmcp.server.providers.openapi instead.",
FastMCPDeprecationWarning,
stacklevel=2,
)
# Re-export from new canonical location
from fastmcp.server.providers.openapi import ( # noqa: E402
ComponentFn as ComponentFn,
MCPType as MCPType,
OpenAPIProvider as OpenAPIProvider,
OpenAPIResource as OpenAPIResource,
OpenAPIResourceTemplate as OpenAPIResourceTemplate,
OpenAPITool as OpenAPITool,
RouteMap as RouteMap,
RouteMapFn as RouteMapFn,
)
# Keep FastMCPOpenAPI for backwards compat (it has its own deprecation warning)
from fastmcp.server.openapi.server import FastMCPOpenAPI as FastMCPOpenAPI # noqa: E402
__all__ = [
"ComponentFn",
"FastMCPOpenAPI",
"MCPType",
"OpenAPIProvider",
"OpenAPIResource",
"OpenAPIResourceTemplate",
"OpenAPITool",
"RouteMap",
"RouteMapFn",
]

View file

@ -1,30 +0,0 @@
"""OpenAPI component implementations - backwards compatibility stub.
This module is deprecated. Import from fastmcp.server.providers.openapi instead.
"""
from __future__ import annotations
import warnings
from fastmcp.exceptions import FastMCPDeprecationWarning
warnings.warn(
"fastmcp.server.openapi.components is deprecated. "
"Import from fastmcp.server.providers.openapi instead.",
FastMCPDeprecationWarning,
stacklevel=2,
)
from fastmcp.server.providers.openapi import ( # noqa: E402
OpenAPIResource,
OpenAPIResourceTemplate,
OpenAPITool,
)
# Export public symbols
__all__ = [
"OpenAPIResource",
"OpenAPIResourceTemplate",
"OpenAPITool",
]

View file

@ -1,48 +0,0 @@
"""Route mapping logic for OpenAPI operations.
.. deprecated::
This module is deprecated. Import from fastmcp.server.providers.openapi instead.
"""
# ruff: noqa: E402
import warnings
from fastmcp.exceptions import FastMCPDeprecationWarning
# Backwards compatibility - export everything that was previously public
__all__ = [
"DEFAULT_ROUTE_MAPPINGS",
"ComponentFn",
"MCPType",
"RouteMap",
"RouteMapFn",
"_determine_route_type",
]
warnings.warn(
"fastmcp.server.openapi.routing is deprecated. "
"Import from fastmcp.server.providers.openapi instead.",
FastMCPDeprecationWarning,
stacklevel=2,
)
# Re-export from new canonical location
from fastmcp.server.providers.openapi.routing import (
DEFAULT_ROUTE_MAPPINGS as DEFAULT_ROUTE_MAPPINGS,
)
from fastmcp.server.providers.openapi.routing import (
ComponentFn as ComponentFn,
)
from fastmcp.server.providers.openapi.routing import (
MCPType as MCPType,
)
from fastmcp.server.providers.openapi.routing import (
RouteMap as RouteMap,
)
from fastmcp.server.providers.openapi.routing import (
RouteMapFn as RouteMapFn,
)
from fastmcp.server.providers.openapi.routing import (
_determine_route_type as _determine_route_type,
)

View file

@ -1,125 +0,0 @@
"""FastMCPOpenAPI - backwards compatibility wrapper.
This class is deprecated. Use FastMCP with OpenAPIProvider instead:
from fastmcp import FastMCP
from fastmcp.server.providers.openapi import OpenAPIProvider
import httpx
client = httpx.AsyncClient(base_url="https://api.example.com")
provider = OpenAPIProvider(openapi_spec=spec, client=client)
mcp = FastMCP("My API Server", providers=[provider])
"""
from __future__ import annotations
import warnings
from typing import Any
import httpx
from fastmcp.exceptions import FastMCPDeprecationWarning
from fastmcp.server.providers.openapi import (
ComponentFn,
OpenAPIProvider,
RouteMap,
RouteMapFn,
)
from fastmcp.server.server import FastMCP
class FastMCPOpenAPI(FastMCP):
"""FastMCP server implementation that creates components from an OpenAPI schema.
.. deprecated::
Use FastMCP with OpenAPIProvider instead. This class will be
removed in a future version.
Example (deprecated):
```python
from fastmcp.server.openapi import FastMCPOpenAPI
import httpx
server = FastMCPOpenAPI(
openapi_spec=spec,
client=httpx.AsyncClient(),
)
```
New approach:
```python
from fastmcp import FastMCP
from fastmcp.server.providers.openapi import OpenAPIProvider
import httpx
client = httpx.AsyncClient(base_url="https://api.example.com")
provider = OpenAPIProvider(openapi_spec=spec, client=client)
mcp = FastMCP("API Server", providers=[provider])
```
"""
def __init__(
self,
openapi_spec: dict[str, Any],
client: httpx.AsyncClient | None = None,
name: str | None = None,
route_maps: list[RouteMap] | None = None,
route_map_fn: RouteMapFn | None = None,
mcp_component_fn: ComponentFn | None = None,
mcp_names: dict[str, str] | None = None,
tags: set[str] | None = None,
**settings: Any,
):
"""Initialize a FastMCP server from an OpenAPI schema.
.. deprecated::
Use FastMCP with OpenAPIProvider instead.
Args:
openapi_spec: OpenAPI schema as a dictionary
client: Optional httpx AsyncClient for making HTTP requests.
If not provided, a default client is created from the spec.
name: Optional name for the server
route_maps: Optional list of RouteMap objects defining route mappings
route_map_fn: Optional callable for advanced route type mapping
mcp_component_fn: Optional callable for component customization
mcp_names: Optional dictionary mapping operationId to component names
tags: Optional set of tags to add to all components
**settings: Additional settings for FastMCP
"""
warnings.warn(
"FastMCPOpenAPI is deprecated. Use FastMCP with OpenAPIProvider instead:\n"
" provider = OpenAPIProvider(openapi_spec=spec, client=client)\n"
" mcp = FastMCP('name', providers=[provider])",
FastMCPDeprecationWarning,
stacklevel=2,
)
super().__init__(name=name or "OpenAPI FastMCP", **settings)
# Store references for backwards compatibility
self._client = client
self._mcp_component_fn = mcp_component_fn
# Create provider with the client
provider = OpenAPIProvider(
openapi_spec=openapi_spec,
client=client,
route_maps=route_maps,
route_map_fn=route_map_fn,
mcp_component_fn=mcp_component_fn,
mcp_names=mcp_names,
tags=tags,
)
self.add_provider(provider)
# Expose internal attributes for backwards compatibility
self._spec = provider._spec
self._director = provider._director
# Export public symbols
__all__ = [
"FastMCPOpenAPI",
]

View file

@ -1,170 +0,0 @@
"""Tests for deprecated OpenAPI imports.
These tests verify that the old import paths still work and emit
deprecation warnings, ensuring backwards compatibility.
"""
import warnings
import httpx
class TestDeprecatedServerOpenAPIImports:
"""Test deprecated imports from fastmcp.server.openapi."""
def test_import_fastmcp_openapi_emits_warning(self):
"""Importing from fastmcp.server.openapi should emit deprecation warning."""
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter("always")
# Force reimport
import importlib
import fastmcp.server.openapi
importlib.reload(fastmcp.server.openapi)
deprecation_warnings = [
x for x in w if issubclass(x.category, DeprecationWarning)
]
assert len(deprecation_warnings) >= 1
assert "providers.openapi" in str(deprecation_warnings[0].message)
def test_import_routing_emits_warning(self):
"""Importing from fastmcp.server.openapi.routing should emit deprecation warning."""
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter("always")
import importlib
import fastmcp.server.openapi.routing
importlib.reload(fastmcp.server.openapi.routing)
deprecation_warnings = [
x for x in w if issubclass(x.category, DeprecationWarning)
]
assert len(deprecation_warnings) >= 1
assert "providers.openapi" in str(deprecation_warnings[0].message)
def test_fastmcp_openapi_class_emits_warning(self):
"""Using FastMCPOpenAPI should emit deprecation warning."""
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter("always")
from fastmcp.server.openapi.server import FastMCPOpenAPI
spec = {
"openapi": "3.0.0",
"info": {"title": "Test", "version": "1.0.0"},
"paths": {},
}
client = httpx.AsyncClient(base_url="https://example.com")
FastMCPOpenAPI(openapi_spec=spec, client=client)
deprecation_warnings = [
x for x in w if issubclass(x.category, DeprecationWarning)
]
assert len(deprecation_warnings) >= 1
assert "FastMCPOpenAPI" in str(deprecation_warnings[-1].message)
def test_deprecated_imports_still_work(self):
"""All expected symbols should be importable from deprecated locations."""
with warnings.catch_warnings():
warnings.simplefilter("ignore", DeprecationWarning)
from fastmcp.server.openapi import (
FastMCPOpenAPI,
MCPType,
OpenAPIProvider,
RouteMap,
)
# Verify they're the right types
assert FastMCPOpenAPI is not None
assert OpenAPIProvider is not None
assert MCPType.TOOL.value == "TOOL"
assert RouteMap is not None
def test_deprecated_routing_imports_still_work(self):
"""Routing symbols should be importable from deprecated location."""
with warnings.catch_warnings():
warnings.simplefilter("ignore", DeprecationWarning)
from fastmcp.server.openapi.routing import (
DEFAULT_ROUTE_MAPPINGS,
MCPType,
_determine_route_type,
)
assert DEFAULT_ROUTE_MAPPINGS is not None
assert len(DEFAULT_ROUTE_MAPPINGS) > 0
assert MCPType.TOOL.value == "TOOL"
assert _determine_route_type is not None
class TestDeprecatedExperimentalOpenAPIImports:
"""Test deprecated imports from fastmcp.experimental.server.openapi."""
def test_experimental_import_emits_warning(self):
"""Importing from experimental should emit deprecation warning."""
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter("always")
import importlib
import fastmcp.experimental.server.openapi
importlib.reload(fastmcp.experimental.server.openapi)
deprecation_warnings = [
x for x in w if issubclass(x.category, DeprecationWarning)
]
assert len(deprecation_warnings) >= 1
assert "providers.openapi" in str(deprecation_warnings[0].message)
def test_experimental_imports_still_work(self):
"""All expected symbols should be importable from experimental."""
with warnings.catch_warnings():
warnings.simplefilter("ignore", DeprecationWarning)
from fastmcp.experimental.server.openapi import (
DEFAULT_ROUTE_MAPPINGS,
FastMCPOpenAPI,
MCPType,
)
assert FastMCPOpenAPI is not None
assert DEFAULT_ROUTE_MAPPINGS is not None
assert MCPType.TOOL.value == "TOOL"
class TestDeprecatedComponentsImports:
"""Test deprecated imports from fastmcp.server.openapi.components."""
def test_components_import_emits_warning(self):
"""Importing from components should emit deprecation warning."""
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter("always")
import importlib
import fastmcp.server.openapi.components
importlib.reload(fastmcp.server.openapi.components)
deprecation_warnings = [
x for x in w if issubclass(x.category, DeprecationWarning)
]
assert len(deprecation_warnings) >= 1
assert "providers.openapi" in str(deprecation_warnings[0].message)
def test_components_imports_still_work(self):
"""Component classes should be importable from deprecated location."""
with warnings.catch_warnings():
warnings.simplefilter("ignore", DeprecationWarning)
from fastmcp.server.openapi.components import (
OpenAPIResource,
OpenAPIResourceTemplate,
OpenAPITool,
)
assert OpenAPITool is not None
assert OpenAPIResource is not None
assert OpenAPIResourceTemplate is not None

View file

@ -1,51 +0,0 @@
"""Tests for OpenAPI-related deprecations in 2.14."""
import importlib
import warnings
import pytest
class TestExperimentalOpenAPIImportDeprecation:
"""Test experimental OpenAPI import path deprecations."""
def test_experimental_server_openapi_import_warns(self):
"""Importing from fastmcp.experimental.server.openapi should warn."""
import fastmcp.experimental.server.openapi
with pytest.warns(
DeprecationWarning,
match=r"Importing from fastmcp\.experimental\.server\.openapi is deprecated",
):
importlib.reload(fastmcp.experimental.server.openapi)
def test_experimental_utilities_openapi_import_warns(self):
"""Importing from fastmcp.experimental.utilities.openapi should warn."""
import fastmcp.experimental.utilities.openapi
with pytest.warns(
DeprecationWarning,
match=r"Importing from fastmcp\.experimental\.utilities\.openapi is deprecated",
):
importlib.reload(fastmcp.experimental.utilities.openapi)
def test_experimental_imports_resolve_to_same_classes(self):
"""Experimental imports should resolve to the same classes as main imports."""
with warnings.catch_warnings():
warnings.simplefilter("ignore")
from fastmcp.experimental.server.openapi import (
FastMCPOpenAPI as ExpFastMCPOpenAPI,
)
from fastmcp.experimental.server.openapi import MCPType as ExpMCPType
from fastmcp.experimental.server.openapi import RouteMap as ExpRouteMap
from fastmcp.experimental.utilities.openapi import (
HTTPRoute as ExpHTTPRoute,
)
from fastmcp.server.openapi import FastMCPOpenAPI, MCPType, RouteMap
from fastmcp.utilities.openapi import HTTPRoute
assert FastMCPOpenAPI is ExpFastMCPOpenAPI
assert RouteMap is ExpRouteMap
assert MCPType is ExpMCPType
assert HTTPRoute is ExpHTTPRoute