fix(bridge): gate capability-dependent LSP requests before dispatch - #260
Merged
Conversation
There was a problem hiding this comment.
Pull request overview
This PR strengthens the MCP↔LSP bridge by proactively gating capability-dependent LSP requests using the negotiated ServerCapabilities, and reduces boilerplate in MCP tool handlers by centralizing result-to-JSON/error mapping.
Changes:
- Add a new bridge-layer
Error::CapabilityNotSupported { server_id, capability }and use it to gate capability-dependent LSP requests before dispatch (and beforedidOpenfor document-opening tools). - Refactor
Translator’s dispatch preparation to split “resolve client/path” from “ensure document open”, enabling pre-open capability checks. - Deduplicate MCP tool handler result mapping via a shared
to_tool_resulthelper.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| crates/mcpls-core/src/mcp/server.rs | Introduces to_tool_result helper and updates tool handlers to use it. |
| crates/mcpls-core/src/lsp/lifecycle.rs | Adds a test-only LspServer::new_for_test fixture for capability-gate tests. |
| crates/mcpls-core/src/error.rs | Adds Error::CapabilityNotSupported and a display test. |
| crates/mcpls-core/src/bridge/translator.rs | Implements capability gating + pre-didOpen ordering and adds extensive tests. |
| CHANGELOG.md | Documents the new error and behavior changes under [Unreleased]. |
bug-ops
enabled auto-merge (squash)
August 4, 2026 19:14
bug-ops
force-pushed
the
fix/230-240-capability-gate
branch
from
August 4, 2026 19:15
9c8ca49 to
9fdeb2b
Compare
Check the routed server's negotiated ServerCapabilities before dispatching capability-gated requests (rename, format, code actions, call hierarchy, signature help, inlay hints, hover, definition, references, completions, document/workspace symbols, implementation, type definition) and return a typed CapabilityNotSupported error instead of sending the request and opaquely relaying whatever the server does with an unsupported method. diagnostics stays unguarded since it falls back to the push-notification cache on failure. Also extract the Result-to-JSON mapping repeated across all 20 tool handlers in mcp/server.rs into a single to_tool_result helper. Closes #240 Closes #230
Document that the capability check relies solely on the initialize- time ServerCapabilities snapshot and does not account for dynamic client/registerCapability. Simplify LspServer::new_for_test to use LspClient::new instead of LspClient::from_transport, dropping two of the three spawned placeholder processes and the dependency on from_transport's background tokio::spawn.
bug-ops
force-pushed
the
fix/230-240-capability-gate
branch
from
August 4, 2026 19:19
9fdeb2b to
02a08a5
Compare
7 tasks
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.
Summary
ServerCapabilitiesbefore dispatching capability-gated requests (rename, format_document, code_actions, call_hierarchy_prepare/incoming_calls/outgoing_calls, signature_help, inlay_hints, hover, definition, references, completions, document_symbols, workspace_symbol, implementation, type_definition), returning a new typedError::CapabilityNotSupported { server_id, capability }instead of sending the request and opaquely relaying whatever the server does with an unsupported method.handle_diagnosticsis deliberately left unguarded — it falls back to the push-notification cache on pull-request failure.textDocument/didOpenis sent for gated handlers (newresolve_client_for_file/prepare_gated_documentsplit).McpErrormapping repeated across all 20 tool handlers inmcp/server.rsinto a singleto_tool_resulthelper.Closes #240
Closes #230
Test plan
cargo +nightly fmt --all -- --checkcargo clippy --all-targets --all-features --workspace -- -D warningscargo nextest run --workspace --all-features --lib --bins(490 passed, 0 failed)RUSTDOCFLAGS="-D warnings" cargo doc --no-deps --all-featuresSome(OneOf::Left(false))(capability explicitly unsupported, not just absent) negative test