diff --git a/docs/getting-started/upgrading/from-fastmcp-2.mdx b/docs/getting-started/upgrading/from-fastmcp-2.mdx index dc6a0fced..a8acad175 100644 --- a/docs/getting-started/upgrading/from-fastmcp-2.mdx +++ b/docs/getting-started/upgrading/from-fastmcp-2.mdx @@ -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 diff --git a/fastmcp_slim/fastmcp/server/openapi/__init__.py b/fastmcp_slim/fastmcp/server/openapi/__init__.py deleted file mode 100644 index 3ea81d109..000000000 --- a/fastmcp_slim/fastmcp/server/openapi/__init__.py +++ /dev/null @@ -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", -] diff --git a/fastmcp_slim/fastmcp/server/openapi/components.py b/fastmcp_slim/fastmcp/server/openapi/components.py deleted file mode 100644 index ce1eeaf7d..000000000 --- a/fastmcp_slim/fastmcp/server/openapi/components.py +++ /dev/null @@ -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", -] diff --git a/fastmcp_slim/fastmcp/server/openapi/routing.py b/fastmcp_slim/fastmcp/server/openapi/routing.py deleted file mode 100644 index 309e503ca..000000000 --- a/fastmcp_slim/fastmcp/server/openapi/routing.py +++ /dev/null @@ -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, -) diff --git a/fastmcp_slim/fastmcp/server/openapi/server.py b/fastmcp_slim/fastmcp/server/openapi/server.py deleted file mode 100644 index a7292129d..000000000 --- a/fastmcp_slim/fastmcp/server/openapi/server.py +++ /dev/null @@ -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", -] diff --git a/tests/deprecated/openapi/test_openapi.py b/tests/deprecated/openapi/test_openapi.py deleted file mode 100644 index 36ad0b6bf..000000000 --- a/tests/deprecated/openapi/test_openapi.py +++ /dev/null @@ -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 diff --git a/tests/deprecated/test_openapi_deprecations.py b/tests/deprecated/test_openapi_deprecations.py deleted file mode 100644 index ee561a376..000000000 --- a/tests/deprecated/test_openapi_deprecations.py +++ /dev/null @@ -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