Remove deprecated client parameter from FastMCPProxy (#2333)

This commit is contained in:
Jeremiah Lowin 2025-11-01 12:13:09 -07:00 committed by GitHub
commit 440ea6130d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 2 additions and 138 deletions

View file

@ -317,7 +317,6 @@ proxy = FastMCPProxy(client_factory=create_client)
### Parameters
- **`client`**: **[DEPRECATED]** A `Client` instance. Use `client_factory` instead for explicit session management.
- **`client_factory`**: A callable that returns a `Client` instance when called. This gives you full control over session creation and reuse strategies.
### Explicit Session Management

View file

@ -1,7 +1,6 @@
from __future__ import annotations
import inspect
import warnings
from collections.abc import Awaitable, Callable
from pathlib import Path
from typing import TYPE_CHECKING, Any, cast
@ -20,7 +19,6 @@ from mcp.types import (
)
from pydantic.networks import AnyUrl
import fastmcp
from fastmcp.client.client import Client, FastMCP1Server
from fastmcp.client.elicitation import ElicitResult
from fastmcp.client.logging import LogMessage
@ -461,9 +459,8 @@ class FastMCPProxy(FastMCP):
def __init__(
self,
client: Client | None = None,
*,
client_factory: ClientFactoryT | None = None,
client_factory: ClientFactoryT,
**kwargs,
):
"""
@ -473,9 +470,6 @@ class FastMCPProxy(FastMCP):
Use FastMCP.as_proxy() for convenience with automatic session strategy.
Args:
client: [DEPRECATED] A Client instance. Use client_factory instead for explicit
session management. When provided, a client_factory will be automatically
created that provides session isolation for backwards compatibility.
client_factory: A callable that returns a Client instance when called.
This gives you full control over session creation and reuse.
Can be either a synchronous or asynchronous function.
@ -484,29 +478,7 @@ class FastMCPProxy(FastMCP):
super().__init__(**kwargs)
# Handle client and client_factory parameters
if client is not None and client_factory is not None:
raise ValueError("Cannot specify both 'client' and 'client_factory'")
if client is not None:
# Deprecated in 2.10.3
if fastmcp.settings.deprecation_warnings:
warnings.warn(
"Passing 'client' to FastMCPProxy is deprecated. Use 'client_factory' instead for explicit session management. "
"For automatic session strategy, use FastMCP.as_proxy().",
DeprecationWarning,
stacklevel=2,
)
# Create a factory that provides session isolation for backwards compatibility
def deprecated_client_factory():
return client.new()
self.client_factory = deprecated_client_factory
elif client_factory is not None:
self.client_factory = client_factory
else:
raise ValueError("Must specify 'client_factory'")
self.client_factory = client_factory
# Replace the default managers with our specialized proxy managers.
self._tool_manager = ProxyToolManager(

View file

@ -1,107 +0,0 @@
"""Tests for deprecated FastMCPProxy client parameter."""
import warnings
import pytest
from fastmcp import Client, FastMCP
from fastmcp.server.proxy import FastMCPProxy, ProxyClient
@pytest.fixture
def simple_server():
"""Create a simple FastMCP server for testing."""
server = FastMCP("TestServer")
@server.tool
def simple_tool() -> str:
return "test_result"
return server
class TestDeprecatedClientParameter:
"""Test the deprecated client parameter in FastMCPProxy."""
def test_client_parameter_deprecation_warning(self, simple_server):
"""Test that using the client parameter raises a deprecation warning."""
client = Client(simple_server)
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter("always") # Ensure all warnings are captured
FastMCPProxy(client=client)
# Verify a deprecation warning was raised
assert len(w) == 1
assert issubclass(w[0].category, DeprecationWarning)
assert "client' to FastMCPProxy is deprecated" in str(w[0].message)
assert "client_factory" in str(w[0].message)
def test_client_parameter_still_works(self, simple_server):
"""Test that the deprecated client parameter still functions."""
client = ProxyClient(simple_server)
with warnings.catch_warnings():
warnings.simplefilter("ignore") # Suppress warnings for functionality test
proxy = FastMCPProxy(client=client)
# Verify the proxy was created successfully
assert proxy is not None
assert hasattr(proxy, "client_factory")
assert callable(proxy.client_factory)
# Verify the factory returns a new client instance (session isolation for backwards compatibility)
returned_client = proxy.client_factory()
assert returned_client is not client
assert isinstance(returned_client, type(client))
def test_cannot_specify_both_client_and_factory(self, simple_server):
"""Test that specifying both client and client_factory raises an error."""
client = Client(simple_server)
def factory():
return Client(simple_server)
with pytest.raises(
ValueError, match="Cannot specify both 'client' and 'client_factory'"
):
FastMCPProxy(client=client, client_factory=factory)
def test_must_specify_client_factory_when_no_client(self):
"""Test that client_factory is required when client is not provided."""
with pytest.raises(ValueError, match="Must specify 'client_factory'"):
FastMCPProxy()
def test_client_factory_preferred_over_deprecated_client(self, simple_server):
"""Test that the recommended client_factory approach works without warnings."""
def factory():
return ProxyClient(simple_server)
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter("always")
proxy = FastMCPProxy(client_factory=factory)
# Verify no warnings were raised
assert len(w) == 0
# Verify the proxy works correctly
assert proxy is not None
assert proxy.client_factory is factory
async def test_deprecated_client_functional_test(self, simple_server):
"""End-to-end test that deprecated client parameter still works functionally."""
client = ProxyClient(simple_server)
with warnings.catch_warnings():
warnings.simplefilter("ignore")
proxy = FastMCPProxy(client=client)
# Test that the proxy can actually handle requests
async with Client(proxy) as proxy_client:
result = await proxy_client.call_tool("simple_tool", {})
assert result.data == "test_result"