chore(mcp): remove dead client code and fix stale MCP docs - #14624
Draft
ogabrielluiz wants to merge 1 commit into
Draft
chore(mcp): remove dead client code and fix stale MCP docs#14624ogabrielluiz wants to merge 1 commit into
ogabrielluiz wants to merge 1 commit into
Conversation
Pre-work ahead of the MCP protocol 2026-07-28 upgrade. Everything here is
correct against the current mcp<2.0 pin and does not depend on the bump.
Dead code:
- Delete _terminate_remote_session and its only call. It has never sent the
Mcp-Session-Id header it exists to send: it probes the session for
`session_id` / `id`, and neither ClientSession nor BaseSession defines
either attribute, so the DELETE always went out bare. The SDK already sends
the real terminate from streamablehttp_client's finally block.
- Delete the aclose/close/iscoroutinefunction probing in
_cleanup_session_by_id. ClientSession has neither method, so no branch could
match. Cancelling the background task unwinds the transport context
managers, which is the only correct close path.
- Delete _validate_session_connectivity. It had no production callers left,
and with it the now-unused get_session_validation_timeout helper.
- Drop the write-only "output_schema" tool metadata key. Nothing reads it.
Behaviour fix:
- Move ValueError out of the fatal except tuple in the tool-building loop and
into the per-tool one. create_input_schema_from_json_schema raises
ValueError("Root schema must be type 'object'") for any tool whose
inputSchema is empty or not an object, which is a shape real servers ship.
In the fatal tuple, one such tool aborted the listing and dropped every
other tool on that server. It now skips that tool, like every other
schema-processing failure. Covered by a new regression test.
The guarded block does no I/O, so this cannot mask a connection or auth
failure: those are raised above the loop and still propagate. The one cost
is that a server whose tools *all* fail conversion now yields an empty
toolset rather than an exception, with the cause only in the logs.
Docs:
- mcp-server.mdx told users to select SSE while giving a /streamable URL.
- troubleshooting.mdx ran supergateway --sse against a /streamable endpoint.
- LFX_MCP.md credited the third-party FastMCP package; the code imports
mcp.server.fastmcp from the SDK.
- api-reference presented SSE as an equal option despite the (LEGACY) markers
on the routes just below it. mcp-server.mdx and mcp-client.mdx carried the
same sentence and are updated to match.
Also drop two extras nothing imports, langchain-mcp-adapters and fastmcp.
Contributor
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Contributor
|
Build successful! ✅ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Pre-work ahead of the MCP protocol 2026-07-28 / python-sdk 2.0 upgrade. Everything here is correct against the current
mcp<2.0pin and none of it depends on the bump, so it can land on its own.Net -224 / +51.
Dead code
Four things that cannot do what they claim to do:
_terminate_remote_sessionreadssession_id/idoff the session to build anMcp-Session-Idheader. NeitherClientSessionnorBaseSessiondefines either attribute in 1.28.1, so the DELETE has always gone out bare. The SDK already sends the real terminate fromstreamablehttp_client'sfinally. Deleted, along with its only call indisconnect().aclose/close/iscoroutinefunctionprobing in_cleanup_session_by_id.ClientSessionhas neither method, so no branch could ever match. Thetask.cancel()that follows unwinds the session and transport context managers, which is the only correct close path._validate_session_connectivityhad no production callers left, and with it the now-unusedget_session_validation_timeouthelper."output_schema"tool metadata key is written and never read.Also drops the
langchain-mcp-adaptersandfastmcpextras. Nothing insrcimports either package.One behaviour change
ValueErrormoves out of the fatalexcepttuple in the tool-building loop ofupdate_toolsand into the per-tool one.create_input_schema_from_json_schemaraisesValueError("Root schema must be type 'object'")for any tool whoseinputSchemais{}or not an object, which is a shape real servers ship (an empty schema is the natural spelling for a no-argument tool). Sitting in the fatal tuple, one such tool aborted the whole listing and dropped every other tool on that server. It now skips that one tool, exactly like every other schema-processing failure already did.New regression test covers it. It fails on
mainwithValueError: Failed to create tool 'bad_empty_schema'and passes here.Known gap, stated honestly: a server whose tools all fail conversion now returns an empty toolset instead of raising, so
/api/v2/mcpreports the generic "No tools found" rather than the specific cause, which survives only in the logs. That is a widening of behaviourTypeError/KeyError/ friends already had, not a new failure class, and the mixed-tool case this targets is a strict improvement. Worth a follow-up on the endpoint's error reporting rather than re-introducing a fatal path here.The guarded block does no I/O, so this cannot mask a connection or auth failure.
connect_to_server, the SSRF and stdio validation, and_validate_connection_paramsall run above the loop and still propagate. TheValueErrors the retry loops re-raise originate outside thistryas well.Docs
Four fixes for things that are wrong today, independent of the upgrade:
mcp-server.mdxtold users to select SSE while giving them a/streamableURL.troubleshooting.mdxransupergateway --sseagainst a/streamableendpoint. Now--streamableHttp.LFX_MCP.mdcredited jlowin's third-party FastMCP package; the code importsmcp.server.fastmcpfrom the SDK.api-reference-api-examples.mdxpresented SSE as an equal option despite the(LEGACY)markers on the routes right below it.mcp-server.mdxandmcp-client.mdxcarried the same sentence and are updated to match, so the three pages agree.Versioned docs under
docs/versioned_docs/are deliberately left alone. They describe what those releases shipped.Verification
src/lfx/tests/unit/mcpsrc/backend/tests/unit/base/mcpsrc/backend/tests/unit/api/v1/test_mcp*.pytest_run_starter_projects_backward_compatibility.pyruff check src/The starter-projects test matters here: a frozen 1.6.0 flow imports
MCPSseClientand passesmcp_sse_client=, so the alias and that kwarg are deliberately kept.Notes for review
deactivated/mcp_sse.py,mcp_stdio.py) were on the chopping block and are not deleted.test_mcp_runtime_config_validation.pyimportsMCPStdioand asserts the stdio command policy is enforced before connecting, so deleting it would delete security coverage.mcp_sse.pygenuinely has no coverage and could go, but splitting the pair for that seemed worse than leaving both._validate_session_connectivitymeant two regression tests lost thepatch.object(...)/assert_not_called()scaffolding they used to proveget_sessionstays off the hot path. Both now assertlist_tools.assert_not_awaited()directly, which is the property they were really guarding.