mirror of
https://github.com/PrefectHQ/fastmcp.git
synced 2026-08-09 15:19:10 +02:00
Remove deprecated fastmcp.server.openapi shim + FastMCPOpenAPI (3.0)
This commit is contained in:
parent
e89763d709
commit
497ed2ea00
7 changed files with 9 additions and 488 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
]
|
||||
|
|
@ -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",
|
||||
]
|
||||
|
|
@ -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,
|
||||
)
|
||||
|
|
@ -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",
|
||||
]
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
Loading…
Add table
Add a link
Reference in a new issue