mirror of
https://github.com/PrefectHQ/fastmcp.git
synced 2026-08-09 07:09:11 +02:00
* Initialize 2.14 deprecation removal branch * Remove deprecated FASTMCP_SERVER_ environment variable prefix (#2330) * Remove deprecated Context.get_http_request method (#2332) * Remove fastmcp.Image top-level import (deprecated 2.8.1) (#2334) * Remove test warnings (#2331) * Create new branch and fix issue * Remove deprecated client parameter from FastMCPProxy (#2333) * Remove deprecated run_streamable_http_async method (#2338) * Remove deprecated sse_app method (#2337) * Remove deprecated run_sse_async method (#2335) * Remove deprecated run_sse_async method * Update CLI and tests to use run_http_async(transport="sse") - Change CLI to call run_http_async with transport="sse" instead of run_sse_async - Update test to mock run_http_async with create=True for v1 servers * Revert CLI changes - v1 servers do have run_sse_async - Keep CLI calling run_sse_async() for v1 compatibility - Update test to mock run_sse_async (which exists on v1) * Remove unnecessary type ignore for run_sse_async Method exists on v1 FastMCP class, no type error * Remove unused imports after test deletion * Remove deprecated streamable_http_app method (#2336) * Remove deprecated dependencies parameter from FastMCP constructor (#2340) * Remove output_schema=False support (deprecated 2.11.4) (#2339) * Remove deprecated client parameter from FastMCPProxy (#2333) * Delete deprecated test_output_schema_false.py Tests functionality that has been removed * Remove deprecated BearerAuthProvider module (#2341) * Remove resource_prefix_format="protocol" support (deprecated 2.4.0) (#2342) * Remove resource_prefix_format="protocol" support (fixes #2195) Removes deprecated protocol format (prefix+resource://path) and keeps only path format (resource://prefix/path). Since only one format remains: - Removed resource_prefix_format from settings, FastMCP.__init__, and helpers - Simplified add_resource_prefix, remove_resource_prefix, has_resource_prefix - Removed MountedServer.resource_prefix_format field - Deleted tests for protocol format All resource prefixes now use path format exclusively. * Clean up resource_prefix_format references - Remove from test files - Update documentation to remove protocol format section - Move custom HTTP routes note to mounting section - Remove resource_prefix_format from settings docs * Use inline version note instead of badge for prefix format * Remove obsolete test functions and update docs - Delete test functions that no longer assert anything - Remove proxy.mdx reference to deleted prefix format section * Format error messages per ruff * Remove from_client classmethod (deprecated 2.8.0) (#2343) * Remove deprecated from_client classmethod (fixes #2192) * Remove unused Client import * Remove add_resource_fn method (deprecated 2.7.0) (#2345) * Update SDK * Add missing imports for exclude_args deprecation warning
326 lines
14 KiB
Python
326 lines
14 KiB
Python
import warnings
|
|
from unittest.mock import patch
|
|
|
|
import pytest
|
|
|
|
from fastmcp import FastMCP
|
|
from fastmcp.settings import Settings
|
|
from fastmcp.utilities.tests import caplog_for_fastmcp
|
|
|
|
# reset deprecation warnings for this module
|
|
pytestmark = pytest.mark.filterwarnings("default::DeprecationWarning")
|
|
|
|
|
|
class TestDeprecatedServerInitKwargs:
|
|
"""Test deprecated server initialization keyword arguments."""
|
|
|
|
def test_log_level_deprecation_warning(self):
|
|
"""Test that log_level raises a deprecation warning."""
|
|
with pytest.warns(
|
|
DeprecationWarning,
|
|
match=r"Providing `log_level` when creating a server is deprecated\. Provide it when calling `run` or as a global setting instead\.",
|
|
):
|
|
server = FastMCP("TestServer", log_level="DEBUG")
|
|
|
|
# Verify the setting is still applied
|
|
assert server._deprecated_settings.log_level == "DEBUG"
|
|
|
|
def test_debug_deprecation_warning(self):
|
|
"""Test that debug raises a deprecation warning."""
|
|
with pytest.warns(
|
|
DeprecationWarning,
|
|
match=r"Providing `debug` when creating a server is deprecated\. Provide it when calling `run` or as a global setting instead\.",
|
|
):
|
|
server = FastMCP("TestServer", debug=True)
|
|
|
|
# Verify the setting is still applied
|
|
assert server._deprecated_settings.debug is True
|
|
|
|
def test_host_deprecation_warning(self):
|
|
"""Test that host raises a deprecation warning."""
|
|
with pytest.warns(
|
|
DeprecationWarning,
|
|
match=r"Providing `host` when creating a server is deprecated\. Provide it when calling `run` or as a global setting instead\.",
|
|
):
|
|
server = FastMCP("TestServer", host="0.0.0.0")
|
|
|
|
# Verify the setting is still applied
|
|
assert server._deprecated_settings.host == "0.0.0.0"
|
|
|
|
def test_port_deprecation_warning(self):
|
|
"""Test that port raises a deprecation warning."""
|
|
with pytest.warns(
|
|
DeprecationWarning,
|
|
match=r"Providing `port` when creating a server is deprecated\. Provide it when calling `run` or as a global setting instead\.",
|
|
):
|
|
server = FastMCP("TestServer", port=8080)
|
|
|
|
# Verify the setting is still applied
|
|
assert server._deprecated_settings.port == 8080
|
|
|
|
def test_sse_path_deprecation_warning(self):
|
|
"""Test that sse_path raises a deprecation warning."""
|
|
with pytest.warns(
|
|
DeprecationWarning,
|
|
match=r"Providing `sse_path` when creating a server is deprecated\. Provide it when calling `run` or as a global setting instead\.",
|
|
):
|
|
server = FastMCP("TestServer", sse_path="/custom-sse")
|
|
|
|
# Verify the setting is still applied
|
|
assert server._deprecated_settings.sse_path == "/custom-sse"
|
|
|
|
def test_message_path_deprecation_warning(self):
|
|
"""Test that message_path raises a deprecation warning."""
|
|
with pytest.warns(
|
|
DeprecationWarning,
|
|
match=r"Providing `message_path` when creating a server is deprecated\. Provide it when calling `run` or as a global setting instead\.",
|
|
):
|
|
server = FastMCP("TestServer", message_path="/custom-message")
|
|
|
|
# Verify the setting is still applied
|
|
assert server._deprecated_settings.message_path == "/custom-message"
|
|
|
|
def test_streamable_http_path_deprecation_warning(self):
|
|
"""Test that streamable_http_path raises a deprecation warning."""
|
|
with pytest.warns(
|
|
DeprecationWarning,
|
|
match=r"Providing `streamable_http_path` when creating a server is deprecated\. Provide it when calling `run` or as a global setting instead\.",
|
|
):
|
|
server = FastMCP("TestServer", streamable_http_path="/custom-http")
|
|
|
|
# Verify the setting is still applied
|
|
assert server._deprecated_settings.streamable_http_path == "/custom-http"
|
|
|
|
def test_json_response_deprecation_warning(self):
|
|
"""Test that json_response raises a deprecation warning."""
|
|
with pytest.warns(
|
|
DeprecationWarning,
|
|
match=r"Providing `json_response` when creating a server is deprecated\. Provide it when calling `run` or as a global setting instead\.",
|
|
):
|
|
server = FastMCP("TestServer", json_response=True)
|
|
|
|
# Verify the setting is still applied
|
|
assert server._deprecated_settings.json_response is True
|
|
|
|
def test_stateless_http_deprecation_warning(self):
|
|
"""Test that stateless_http raises a deprecation warning."""
|
|
with pytest.warns(
|
|
DeprecationWarning,
|
|
match=r"Providing `stateless_http` when creating a server is deprecated\. Provide it when calling `run` or as a global setting instead\.",
|
|
):
|
|
server = FastMCP("TestServer", stateless_http=True)
|
|
|
|
# Verify the setting is still applied
|
|
assert server._deprecated_settings.stateless_http is True
|
|
|
|
def test_multiple_deprecated_kwargs_warnings(self):
|
|
"""Test that multiple deprecated kwargs each raise their own warning."""
|
|
with warnings.catch_warnings(record=True) as recorded_warnings:
|
|
warnings.simplefilter("always")
|
|
server = FastMCP(
|
|
"TestServer",
|
|
log_level="INFO",
|
|
debug=False,
|
|
host="127.0.0.1",
|
|
port=9999,
|
|
sse_path="/sse/",
|
|
message_path="/msg",
|
|
streamable_http_path="/http",
|
|
json_response=False,
|
|
stateless_http=False,
|
|
)
|
|
|
|
# Should have 9 deprecation warnings (one for each deprecated parameter)
|
|
deprecation_warnings = [
|
|
w for w in recorded_warnings if issubclass(w.category, DeprecationWarning)
|
|
]
|
|
assert len(deprecation_warnings) == 9
|
|
|
|
# Verify all expected parameters are mentioned in warnings
|
|
expected_params = {
|
|
"log_level",
|
|
"debug",
|
|
"host",
|
|
"port",
|
|
"sse_path",
|
|
"message_path",
|
|
"streamable_http_path",
|
|
"json_response",
|
|
"stateless_http",
|
|
}
|
|
mentioned_params = set()
|
|
for warning in deprecation_warnings:
|
|
message = str(warning.message)
|
|
for param in expected_params:
|
|
if f"Providing `{param}`" in message:
|
|
mentioned_params.add(param)
|
|
|
|
assert mentioned_params == expected_params
|
|
|
|
# Verify all settings are still applied
|
|
assert server._deprecated_settings.log_level == "INFO"
|
|
assert server._deprecated_settings.debug is False
|
|
assert server._deprecated_settings.host == "127.0.0.1"
|
|
assert server._deprecated_settings.port == 9999
|
|
assert server._deprecated_settings.sse_path == "/sse/"
|
|
assert server._deprecated_settings.message_path == "/msg"
|
|
assert server._deprecated_settings.streamable_http_path == "/http"
|
|
assert server._deprecated_settings.json_response is False
|
|
assert server._deprecated_settings.stateless_http is False
|
|
|
|
def test_non_deprecated_kwargs_no_warnings(self):
|
|
"""Test that non-deprecated kwargs don't raise warnings."""
|
|
with warnings.catch_warnings(record=True) as recorded_warnings:
|
|
warnings.simplefilter("always")
|
|
server = FastMCP(
|
|
name="TestServer",
|
|
instructions="Test instructions",
|
|
on_duplicate_tools="warn",
|
|
on_duplicate_resources="error",
|
|
on_duplicate_prompts="replace",
|
|
mask_error_details=True,
|
|
)
|
|
|
|
# Should have no deprecation warnings
|
|
deprecation_warnings = [
|
|
w for w in recorded_warnings if issubclass(w.category, DeprecationWarning)
|
|
]
|
|
assert len(deprecation_warnings) == 0
|
|
|
|
# Verify server was created successfully
|
|
assert server.name == "TestServer"
|
|
assert server.instructions == "Test instructions"
|
|
|
|
def test_none_values_no_warnings(self):
|
|
"""Test that None values for deprecated kwargs don't raise warnings."""
|
|
with warnings.catch_warnings(record=True) as recorded_warnings:
|
|
warnings.simplefilter("always")
|
|
FastMCP(
|
|
"TestServer",
|
|
log_level=None,
|
|
debug=None,
|
|
host=None,
|
|
port=None,
|
|
sse_path=None,
|
|
message_path=None,
|
|
streamable_http_path=None,
|
|
json_response=None,
|
|
stateless_http=None,
|
|
)
|
|
|
|
# Should have no deprecation warnings for None values
|
|
deprecation_warnings = [
|
|
w for w in recorded_warnings if issubclass(w.category, DeprecationWarning)
|
|
]
|
|
assert len(deprecation_warnings) == 0
|
|
|
|
def test_deprecated_settings_inheritance_from_global(self):
|
|
"""Test that deprecated settings inherit from global settings when not provided."""
|
|
# Mock fastmcp.settings to test inheritance
|
|
with patch("fastmcp.settings") as mock_settings:
|
|
mock_settings.model_dump.return_value = {
|
|
"log_level": "WARNING",
|
|
"debug": True,
|
|
"host": "0.0.0.0",
|
|
"port": 3000,
|
|
"sse_path": "/events",
|
|
"message_path": "/messages",
|
|
"streamable_http_path": "/stream",
|
|
"json_response": True,
|
|
"stateless_http": True,
|
|
}
|
|
mock_settings.server_auth = None # Add server_auth attribute
|
|
|
|
server = FastMCP("TestServer")
|
|
|
|
# Verify settings are inherited from global settings
|
|
assert server._deprecated_settings.log_level == "WARNING"
|
|
assert server._deprecated_settings.debug is True
|
|
assert server._deprecated_settings.host == "0.0.0.0"
|
|
assert server._deprecated_settings.port == 3000
|
|
assert server._deprecated_settings.sse_path == "/events"
|
|
assert server._deprecated_settings.message_path == "/messages"
|
|
assert server._deprecated_settings.streamable_http_path == "/stream"
|
|
assert server._deprecated_settings.json_response is True
|
|
assert server._deprecated_settings.stateless_http is True
|
|
|
|
def test_deprecated_settings_override_global(self):
|
|
"""Test that deprecated settings override global settings when provided."""
|
|
# Mock fastmcp.settings to test override behavior
|
|
with patch("fastmcp.settings") as mock_settings:
|
|
mock_settings.model_dump.return_value = {
|
|
"log_level": "WARNING",
|
|
"debug": True,
|
|
"host": "0.0.0.0",
|
|
"port": 3000,
|
|
"sse_path": "/events",
|
|
"message_path": "/messages",
|
|
"streamable_http_path": "/stream",
|
|
"json_response": True,
|
|
"stateless_http": True,
|
|
}
|
|
mock_settings.server_auth = None # Add server_auth attribute
|
|
|
|
with warnings.catch_warnings():
|
|
warnings.simplefilter("ignore") # Ignore warnings for this test
|
|
server = FastMCP(
|
|
"TestServer",
|
|
log_level="ERROR",
|
|
debug=False,
|
|
host="127.0.0.1",
|
|
port=8080,
|
|
)
|
|
|
|
# Verify provided settings override global settings
|
|
assert server._deprecated_settings.log_level == "ERROR"
|
|
assert server._deprecated_settings.debug is False
|
|
assert server._deprecated_settings.host == "127.0.0.1"
|
|
assert server._deprecated_settings.port == 8080
|
|
# Non-overridden settings should still come from global
|
|
assert server._deprecated_settings.sse_path == "/events"
|
|
assert server._deprecated_settings.message_path == "/messages"
|
|
assert server._deprecated_settings.streamable_http_path == "/stream"
|
|
assert server._deprecated_settings.json_response is True
|
|
assert server._deprecated_settings.stateless_http is True
|
|
|
|
def test_stacklevel_points_to_constructor_call(self):
|
|
"""Test that deprecation warnings point to the FastMCP constructor call."""
|
|
with warnings.catch_warnings(record=True) as recorded_warnings:
|
|
warnings.simplefilter("always")
|
|
|
|
FastMCP("TestServer", log_level="DEBUG")
|
|
|
|
# Should have exactly one deprecation warning
|
|
deprecation_warnings = [
|
|
w for w in recorded_warnings if issubclass(w.category, DeprecationWarning)
|
|
]
|
|
assert len(deprecation_warnings) == 1
|
|
|
|
# The warning should point to the server.py file where FastMCP.__init__ is called
|
|
# This verifies the stacklevel is working as intended (pointing to constructor)
|
|
warning = deprecation_warnings[0]
|
|
assert "server.py" in warning.filename
|
|
|
|
|
|
class TestDeprecatedSettingsProperty:
|
|
"""Test deprecated settings property access."""
|
|
|
|
def test_settings_property_deprecation_warning(self, caplog):
|
|
"""Test that accessing fastmcp.settings.settings logs a deprecation warning."""
|
|
from fastmcp import settings
|
|
|
|
with caplog_for_fastmcp(caplog):
|
|
# Access the deprecated property
|
|
deprecated_settings = settings.settings
|
|
|
|
# Check that a warning was logged
|
|
assert any(
|
|
"Using fastmcp.settings.settings is deprecated. Use fastmcp.settings instead."
|
|
in record.message
|
|
for record in caplog.records
|
|
if record.levelname == "WARNING"
|
|
)
|
|
|
|
# Verify it still returns the same settings object
|
|
assert deprecated_settings is settings
|
|
assert isinstance(deprecated_settings, Settings)
|