Forward upstream instructions through create_proxy (#4512)

Co-authored-by: Mistral Vibe <vibe@mistral.ai>
This commit is contained in:
Grégoire 2026-07-17 23:29:15 +02:00 committed by GitHub
commit 977f02347b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 50 additions and 1 deletions

View file

@ -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
# -----------------------------------------------------------------------------

View file

@ -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/")