refactor: replace OAuth2 token-expired text matching with errors.Is and preserve last-known tool map on disconnect - #5910
Conversation
|
|
oauth_configs to new mcp_oauth_flows table
#5709
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@core/mcp/clientmanager.go`:
- Around line 2015-2023: Preserve last-known tool mappings across every failed
reconnect: in core/mcp/clientmanager.go lines 2015-2023, avoid clearing ToolMap
and ToolNameMapping during close-first initialization and replace them only
after successful tool discovery; in core/mcp/makebeforebreak_test.go lines
360-367, add a second failed reconnect and assert both mappings still equal
their original last-known values.
In `@core/mcp/exec.go`:
- Around line 158-169: Move the NeedsReauth and Disconnected checks in the tool
execution flow after the global, client, tool, and request authorization
filters, including MCPContextKeyIncludeClients, ToolsToExecute, and
MCPContextKeyIncludeTools. Ensure the state-specific errors in the relevant
exec.go function are returned only after the tool invocation is authorized,
while preserving their existing messages and behavior.
In `@core/mcp/makebeforebreak_test.go`:
- Around line 360-367: Add a second reconnect attempt in the existing
make-before-break failure test, exercising the close-first path, and configure
it to fail. Capture the tool map and tool-name mapping before this attempt, then
assert afterward that both ToolMap and ToolNameMapping are unchanged from those
pre-failure values.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 4fe94bca-fc74-460c-bf85-cdd5ad3cc9bc
📒 Files selected for processing (7)
core/mcp/auth_retry_test.gocore/mcp/clientmanager.gocore/mcp/exec.gocore/mcp/makebeforebreak_test.gocore/mcp/pluginpipeline.gocore/mcp/reauth_state_test.gocore/mcp/utils.go
💤 Files with no reviewable changes (1)
- core/mcp/reauth_state_test.go
acafca2 to
c65f7f1
Compare
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@core/mcp/clientmanager.go`:
- Around line 2021-2029: Update EnableClient to call beginExclusiveClientOp
before clearing ExecutionConfig.Disabled, and retain the exclusive-operation
guard through the entire enable flow. Ensure concurrent ReconnectClient calls
cannot observe or connect a client while it remains disabled, while preserving
the existing “already in progress” error behavior.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 610512b6-35db-4571-8e05-745ad62a8745
📒 Files selected for processing (7)
core/mcp/auth_retry_test.gocore/mcp/clientmanager.gocore/mcp/exec.gocore/mcp/makebeforebreak_test.gocore/mcp/pluginpipeline.gocore/mcp/reauth_state_test.gocore/mcp/utils.go
💤 Files with no reviewable changes (1)
- core/mcp/reauth_state_test.go
🚧 Files skipped from review as they are similar to previous changes (5)
- core/mcp/exec.go
- core/mcp/makebeforebreak_test.go
- core/mcp/utils.go
- core/mcp/auth_retry_test.go
- core/mcp/pluginpipeline.go
c65f7f1 to
513a1f2
Compare
1179fbb to
0468d13
Compare
0468d13 to
ab1b6a5
Compare
2f57baa to
895272f
Compare
ab1b6a5 to
1ef7197
Compare
Merge activity
|
The base branch was changed.
…ck client/tool authorization before state-specific errors
895272f to
7feec2f
Compare
Summary
When an MCP client connection fails, the tool map was being cleared, making a dead connection indistinguishable from a tool that never existed. This caused callers to receive a generic "not available or not permitted" error rather than an actionable "client needs re-authorization" or "client is disconnected" message. Additionally, the OAuth2 token expiry detection relied on fragile substring matching against a flattened error string because
runConnectWithPluginPipelinewas not preserving the original Go error onErrorField.Error. This PR fixes both issues.Changes
Preserve last-known tool map on connection failure:
failConnectAttemptno longer clearsToolMap/ToolNameMappingwhen a connection fails. The maps are left as last-known-good soGetClientForToolcan still resolve the tool and route it to the correct client.GetToolPerClientalready filters onStatedirectly, so disconnected clients' tools are not re-advertised.Add explicit state checks in
prepareToolExecution: Before falling through toAcquireClientConn, the execution path now checks forNeedsReauthandDisconnectedstates and returns specific, actionable error messages rather than a generic "no active connection" error.Preserve the original error on
BifrostErrorinrunConnectWithPluginPipeline: Both early-return and late-return error paths now setErrorField.ErroralongsideErrorField.Message, enablingerrors.Is/errors.Asclassification by callers.Replace text-matching OAuth2 expiry detection with
errors.Is:connectToMCPClientnow useserrors.Is(gateErr.Error.Error, schemas.ErrOAuth2TokenExpired)instead of theisOAuth2TokenExpiredErrorTextsubstring matcher, which was only necessary because the original error was being discarded.Remove
isOAuth2TokenExpiredErrorTextand its tests: The function and its associated test coverage are deleted now that the typed error is preserved through the pipeline. TheTestIsAuthFailureErrorText_DoesNotOverlapOAuth2TokenExpiredSentineltest is simplified to only assert the negative case, since there is no longer a separate text-matching function to validate the positive case for.Update make-before-break test assertions: The reconnect failure test now asserts that the tool map is retained (
NotEmpty) rather than cleared (Empty), reflecting the new intended behavior.Type of change
Affected areas
How to test
go version go test ./...The
makebeforebreak_test.goandreauth_state_test.gotests directly cover the changed behavior. After a simulated dial failure, verify that:NeedsReauthclient returns a message containing "needs re-authorization".Disconnectedclient returns a message containing "is disconnected".Breaking changes
Security considerations
None. The change improves error message clarity for expired OAuth2 credentials but does not alter authentication logic or expose new information externally.
Checklist
docs/contributing/README.mdand followed the guidelines