mirror of
https://github.com/PrefectHQ/fastmcp.git
synced 2026-08-09 07:09:11 +02:00
Forward upstream instructions through create_proxy (#4512)
Co-authored-by: Mistral Vibe <vibe@mistral.ai>
This commit is contained in:
parent
6202008cf3
commit
977f02347b
2 changed files with 50 additions and 1 deletions
|
|
@ -106,6 +106,7 @@ class ProxyInitializeMiddleware(Middleware):
|
|||
],
|
||||
) -> mcp_types.InitializeResult | None:
|
||||
client = await self.proxy._get_client()
|
||||
upstream_instructions: str | None = None
|
||||
try:
|
||||
if isinstance(client, ProxyClient):
|
||||
ctx = context.fastmcp_context
|
||||
|
|
@ -116,6 +117,11 @@ class ProxyInitializeMiddleware(Middleware):
|
|||
)
|
||||
async with client:
|
||||
await client.initialize()
|
||||
# Capture the upstream's instructions while the session is live;
|
||||
# `initialize_result` clears once the client context exits.
|
||||
init_result = client.initialize_result
|
||||
if init_result is not None:
|
||||
upstream_instructions = init_result.instructions
|
||||
except MCPError:
|
||||
raise
|
||||
except (
|
||||
|
|
@ -128,7 +134,20 @@ class ProxyInitializeMiddleware(Middleware):
|
|||
) as error:
|
||||
raise _proxy_upstream_error(error) from error
|
||||
|
||||
return await call_next(context)
|
||||
result = await call_next(context)
|
||||
|
||||
# Forward the upstream server's instructions unless the proxy defines its
|
||||
# own. `instructions` is part of the MCP InitializeResult and is meant to
|
||||
# steer the model, so a proxy that dropped it would silently degrade any
|
||||
# downstream consumer relying on upstream guidance.
|
||||
if (
|
||||
result is not None
|
||||
and self.proxy.instructions is None
|
||||
and upstream_instructions is not None
|
||||
):
|
||||
result.instructions = upstream_instructions
|
||||
|
||||
return result
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -189,6 +189,36 @@ async def test_create_proxy_with_transport(fastmcp_server):
|
|||
assert result.data == "Hello, Test!"
|
||||
|
||||
|
||||
async def test_proxy_forwards_upstream_instructions():
|
||||
"""A proxy should surface the upstream server's instructions in the handshake."""
|
||||
upstream = FastMCP(name="upstream", instructions="USE_THIS_MARKER_123")
|
||||
proxy = create_proxy(upstream, name="proxy")
|
||||
|
||||
async with Client(proxy) as client:
|
||||
assert client.initialize_result is not None
|
||||
assert client.initialize_result.instructions == "USE_THIS_MARKER_123"
|
||||
|
||||
|
||||
async def test_proxy_own_instructions_take_precedence():
|
||||
"""Instructions explicitly set on the proxy override the upstream's."""
|
||||
upstream = FastMCP(name="upstream", instructions="upstream instructions")
|
||||
proxy = create_proxy(upstream, name="proxy", instructions="proxy instructions")
|
||||
|
||||
async with Client(proxy) as client:
|
||||
assert client.initialize_result is not None
|
||||
assert client.initialize_result.instructions == "proxy instructions"
|
||||
|
||||
|
||||
async def test_proxy_instructions_none_when_upstream_has_none():
|
||||
"""A proxy over an upstream without instructions reports no instructions."""
|
||||
upstream = FastMCP(name="upstream")
|
||||
proxy = create_proxy(upstream, name="proxy")
|
||||
|
||||
async with Client(proxy) as client:
|
||||
assert client.initialize_result is not None
|
||||
assert client.initialize_result.instructions is None
|
||||
|
||||
|
||||
def test_create_proxy_with_url():
|
||||
"""create_proxy should accept a URL without connecting."""
|
||||
proxy = create_proxy("http://example.com/mcp/")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue