mirror of
https://github.com/PrefectHQ/fastmcp.git
synced 2026-08-22 13:34:17 +02:00
Simplify proxy negotiation middleware API
🤖 Generated with OpenAI Codex
This commit is contained in:
parent
ebf8d648da
commit
e227a28c02
4 changed files with 14 additions and 33 deletions
|
|
@ -390,13 +390,13 @@ Only reuse sessions when you know the backend is stateless (e.g. stateless HTTP)
|
|||
|
||||
### Forwarding Negotiation Metadata
|
||||
|
||||
Add `ProxyNegotiationMetadataMiddleware` when a gateway built with `ProxyProvider` should also expose backend instructions and namespaced `_meta`:
|
||||
Add `ProxyNegotiationMiddleware` when a gateway built with `ProxyProvider` should also expose backend instructions and namespaced `_meta`:
|
||||
|
||||
```python
|
||||
from fastmcp import FastMCP
|
||||
from fastmcp.server.providers.proxy import (
|
||||
ProxyClient,
|
||||
ProxyNegotiationMetadataMiddleware,
|
||||
ProxyNegotiationMiddleware,
|
||||
ProxyProvider,
|
||||
)
|
||||
|
||||
|
|
@ -404,7 +404,7 @@ backend = ProxyProvider(lambda: ProxyClient("http://backend:8000/mcp", mode="aut
|
|||
gateway = FastMCP(
|
||||
"Controlled Gateway",
|
||||
providers=[backend],
|
||||
middleware=[ProxyNegotiationMetadataMiddleware(backend)],
|
||||
middleware=[ProxyNegotiationMiddleware(backend)],
|
||||
)
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
from typing import TYPE_CHECKING
|
||||
|
||||
from .authorization import AuthMiddleware
|
||||
from .middleware import (
|
||||
CallNext,
|
||||
|
|
@ -8,24 +6,10 @@ from .middleware import (
|
|||
)
|
||||
from .ping import PingMiddleware
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from fastmcp.server.providers.proxy import (
|
||||
ProxyNegotiationMetadataMiddleware as ProxyNegotiationMetadataMiddleware,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"AuthMiddleware",
|
||||
"CallNext",
|
||||
"Middleware",
|
||||
"MiddlewareContext",
|
||||
"PingMiddleware",
|
||||
"ProxyNegotiationMetadataMiddleware",
|
||||
]
|
||||
|
||||
|
||||
def __getattr__(name: str) -> object:
|
||||
if name == "ProxyNegotiationMetadataMiddleware":
|
||||
from fastmcp.server.providers.proxy import ProxyNegotiationMetadataMiddleware
|
||||
|
||||
return ProxyNegotiationMetadataMiddleware
|
||||
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
||||
|
|
|
|||
|
|
@ -1045,7 +1045,7 @@ class _NegotiationMetadata:
|
|||
)
|
||||
|
||||
|
||||
class ProxyNegotiationMetadataMiddleware(Middleware):
|
||||
class ProxyNegotiationMiddleware(Middleware):
|
||||
"""Forward optional negotiation metadata from a ``ProxyProvider`` backend.
|
||||
|
||||
The frontend always owns protocol versions, capabilities, cache policy, and
|
||||
|
|
@ -1344,9 +1344,7 @@ class FastMCPProxy(FastMCP):
|
|||
self.client_factory = client_factory
|
||||
provider = ProxyProvider(client_factory)
|
||||
self.add_provider(provider)
|
||||
self.middleware.append(
|
||||
ProxyNegotiationMetadataMiddleware(provider, identity=identity)
|
||||
)
|
||||
self.middleware.append(ProxyNegotiationMiddleware(provider, identity=identity))
|
||||
self._setup_proxy_ping_handler()
|
||||
|
||||
async def _get_client(self) -> Client:
|
||||
|
|
|
|||
|
|
@ -11,13 +11,12 @@ from mcp_types.version import MODERN_PROTOCOL_VERSIONS
|
|||
from fastmcp import Client, FastMCP
|
||||
from fastmcp.client.transports import StreamableHttpTransport
|
||||
from fastmcp.server import create_proxy
|
||||
from fastmcp.server.middleware import (
|
||||
CallNext,
|
||||
Middleware,
|
||||
MiddlewareContext,
|
||||
ProxyNegotiationMetadataMiddleware,
|
||||
from fastmcp.server.middleware import CallNext, Middleware, MiddlewareContext
|
||||
from fastmcp.server.providers.proxy import (
|
||||
ProxyClient,
|
||||
ProxyNegotiationMiddleware,
|
||||
ProxyProvider,
|
||||
)
|
||||
from fastmcp.server.providers.proxy import ProxyClient, ProxyProvider
|
||||
from fastmcp.utilities.http import find_available_port
|
||||
|
||||
ResultT = TypeVar("ResultT", bound=mcp_types.Result)
|
||||
|
|
@ -132,7 +131,7 @@ def make_gateway(
|
|||
frontend_metadata: bool = False,
|
||||
) -> FastMCP:
|
||||
provider = ProxyProvider(lambda: ProxyClient(upstream, mode=backend_mode))
|
||||
negotiation = ProxyNegotiationMetadataMiddleware(provider, identity=identity)
|
||||
negotiation = ProxyNegotiationMiddleware(provider, identity=identity)
|
||||
middleware: list[Middleware] = [negotiation]
|
||||
if frontend_metadata:
|
||||
middleware.append(FrontendMetadataMiddleware())
|
||||
|
|
@ -235,7 +234,7 @@ async def test_unavailable_backend_does_not_fail_negotiation(frontend_mode: str)
|
|||
gateway = FastMCP(
|
||||
"available-gateway",
|
||||
providers=[provider],
|
||||
middleware=[ProxyNegotiationMetadataMiddleware(provider)],
|
||||
middleware=[ProxyNegotiationMiddleware(provider)],
|
||||
)
|
||||
gateway.provider_error_strategy = "raise"
|
||||
|
||||
|
|
@ -258,7 +257,7 @@ def test_gateway_construction_does_not_create_backend_client():
|
|||
FastMCP(
|
||||
"lazy-gateway",
|
||||
providers=[provider],
|
||||
middleware=[ProxyNegotiationMetadataMiddleware(provider)],
|
||||
middleware=[ProxyNegotiationMiddleware(provider)],
|
||||
)
|
||||
|
||||
assert calls == 0
|
||||
|
|
@ -268,7 +267,7 @@ async def test_fastmcp_proxy_uses_public_negotiation_middleware():
|
|||
proxy = create_proxy(make_upstream(), name="convenience", identity="upstream")
|
||||
|
||||
assert any(
|
||||
isinstance(middleware, ProxyNegotiationMetadataMiddleware)
|
||||
isinstance(middleware, ProxyNegotiationMiddleware)
|
||||
for middleware in proxy.middleware
|
||||
)
|
||||
async with Client(proxy, mode="auto") as client:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue