From 52b37b9a0cdf5b80e054529bd2cf7168ab25d2bc Mon Sep 17 00:00:00 2001 From: Jeremiah Lowin <153965+jlowin@users.noreply.github.com> Date: Mon, 20 Jul 2026 16:34:42 -0400 Subject: [PATCH] Mark transforming single-server config wrapper legacy-only --- fastmcp_slim/fastmcp/mcp_config.py | 11 ++++++++++- tests/test_mcp_config.py | 17 +++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/fastmcp_slim/fastmcp/mcp_config.py b/fastmcp_slim/fastmcp/mcp_config.py index 6882c06e7..c09d9f3c6 100644 --- a/fastmcp_slim/fastmcp/mcp_config.py +++ b/fastmcp_slim/fastmcp/mcp_config.py @@ -164,7 +164,16 @@ class _TransformingMCPServerMixin(BaseModel): ) ) from exc - return FastMCPTransport(mcp=self._to_server_and_underlying_transport()[0]) + transport = FastMCPTransport(mcp=self._to_server_and_underlying_transport()[0]) + # The wrapped proxy talks to its upstream over the legacy era (it pins + # the backend client to `mode="legacy"` to forward the initialize + # handshake and server-initiated features). Mark the wrapper legacy-only + # so a default `Client(config)` on `mode="auto"` negotiates legacy with + # it too, keeping both legs on the same era — otherwise a modern + # frontend would receive a forwarded server-initiated request that the + # modern era has no back-channel for. + transport.legacy_only = True + return transport class StdioMCPServer(BaseModel): diff --git a/tests/test_mcp_config.py b/tests/test_mcp_config.py index 3301fbfd8..a35af2287 100644 --- a/tests/test_mcp_config.py +++ b/tests/test_mcp_config.py @@ -140,6 +140,23 @@ class TestConfigTransportLegacyOnly: transport = MCPConfigTransport(config) assert transport.legacy_only is True + def test_transforming_single_server_wrapper_is_legacy_only(self): + """A single-server config that uses tool transforms or tag filters wraps + a legacy-pinned proxy; the wrapper transport must advertise legacy-only + so a default `mode="auto"` frontend negotiates the same era as the + backend rather than negotiating modern against a legacy upstream.""" + config = { + "mcpServers": { + "a": { + "url": "https://a.example.com/mcp", + "include_tags": ["public"], + }, + }, + } + mcp_config = MCPConfig.from_dict(config) + transport = mcp_config.mcpServers["a"].to_transport() + assert transport.legacy_only is True + def test_parse_single_stdio_config(): config = {