feat: extend mcp plugin interface for list tools, ping and connections - #3389
Conversation
|
|
This stack of pull requests is managed by Graphite. Learn more about stacking. |
📝 WalkthroughSummary by CodeRabbit
WalkthroughThis PR centralizes MCP tool execution and connection lifecycle behind a plugin pipeline gate: it adds typed MCP envelopes/hooks (connect/ping/list_tools/execute_tool), moves plugin pipeline lifecycle ownership to ClientManager/MCPManager, implements gate wrappers for pre/post hooks and short-circuiting, refactors client connect/OAuth/tool discovery through the gate, and updates tests to the new agent-mode contract. ChangesMCP Plugin Gate Architecture and Lifecycle Hooks
🎯 4 (Complex) | ⏱️ ~60 minutes
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
|
4f3b528 to
d2eb077
Compare
Confidence Score: 5/5The change is safe to merge; previously reported runtime bugs are addressed and the new gate functions are well-tested. The previously reported nil-context panic (SSE/STDIO), unconditional ping error return, and nil-dereference on gateErr.Error.Message are all corrected in this PR. The two remaining findings are a misleading trace span status (always reported Ok even on error) and a small dead-code branch in GetErrorString; neither affects correctness or data integrity. core/mcp/pluginpipeline.go — span status reporting; core/schemas/bifrost.go — GetErrorString dead code Important Files Changed
Reviews (2): Last reviewed commit: "feat: extend mcp plugin interface for li..." | Re-trigger Greptile |
There was a problem hiding this comment.
Actionable comments posted: 7
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
core/mcp/toolsync.go (1)
133-154:⚠️ Potential issue | 🟠 Major | 🏗️ Heavy liftDon’t treat hook-suppressed list results as a successful sync.
This new path can now return empty maps when the hook pipeline removes the
list_toolspayload, butperformSyncstill overwritesclientState.ToolMapandToolNameMappingunconditionally. That lets one bad hook invocation temporarily erase every discovered tool for the client. Preserve the previous maps unless the hook path positively reports a real list-tools payload.🤖 Prompt for 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. In `@core/mcp/toolsync.go` around lines 133 - 154, The current sync unconditionally overwrites clientState.ToolMap and clientState.ToolNameMapping with newTools/newMapping returned by cts.manager.runListToolsWithHooks, which lets hook-suppressed (empty) payloads erase the existing maps; change the logic after the runListToolsWithHooks call to only update the maps when the hook path returned a real list (e.g., newTools or newMapping is non-empty/non-nil). Concretely: after obtaining newTools, newMapping, err from cts.manager.runListToolsWithHooks, if err != nil keep existing maps as you already do; else if both len(newTools) == 0 and (newMapping == nil || len(newMapping) == 0) skip the write/update and log/debug that hooks suppressed the payload; otherwise proceed to acquire cts.manager.mu and atomically assign clientState.ToolMap = newTools and clientState.ToolNameMapping = newMapping. Ensure you reference runListToolsWithHooks, clientState.ToolMap and clientState.ToolNameMapping when making the change.
🧹 Nitpick comments (2)
core/utils.go (1)
412-414: ⚡ Quick winUse Go’s standard
Deprecated:doc format here.The wrapper is fine, but the current comment won’t be picked up by
gopls/godoc as a real deprecation marker. Prefer the standard form so callers actually see the migration hint.♻️ Proposed fix
-// // [Deprecated] use err.GetErrorString() instead. Will be removed in a future release. +// Deprecated: use (*schemas.BifrostError).GetErrorString instead. func GetErrorMessage(err *schemas.BifrostError) string { return err.GetErrorString() }🤖 Prompt for 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. In `@core/utils.go` around lines 412 - 414, Replace the nonstandard deprecation comment above GetErrorMessage with Go's recognized form by prefixing the sentence with "Deprecated:" (e.g., "Deprecated: use err.GetErrorString() instead; will be removed in a future release."), so gopls/godoc will surface the migration hint for callers of GetErrorMessage (which wraps schemas.BifrostError.GetErrorString).core/bifrost.go (1)
6547-6568: ⚡ Quick winSkip non-connection plugins before opening connect spans.
These branches start a connect pre/post span and update
BifrostContextKeySpanIDeven when the plugin does not implementschemas.MCPConnectionPlugin. That creates synthetic "skipped" spans and can incorrectly make later real connection hooks children of a plugin that never actually ran.♻️ Suggested adjustment
func (p *PluginPipeline) RunMCPPreConnectionHooks(ctx *schemas.BifrostContext, req *schemas.BifrostMCPConnectRequest) (*schemas.BifrostMCPConnectRequest, *schemas.MCPConnectionShortCircuit, int) { ... for i, plugin := range p.mcpPlugins { + cp, ok := plugin.(schemas.MCPConnectionPlugin) + if !ok { + continue + } + pluginName := plugin.GetName() p.logger.Debug("running MCP connect pre-hook for plugin %s", pluginName) spanCtx, handle := p.tracer.StartSpan(ctx, fmt.Sprintf("plugin.%s.mcp_connect_prehook", sanitizeSpanName(pluginName)), schemas.SpanKindPlugin) ... - - if cp, ok := plugin.(schemas.MCPConnectionPlugin); ok { - req, shortCircuit, err = cp.PreMCPConnectionHook(pluginCtx, req) - } else { - // Plugin only implements MCPPlugin — Connect is invisible to it. - pluginCtx.ReleasePluginScope() - p.tracer.EndSpan(handle, schemas.SpanStatusOk, "skipped (not MCPConnectionPlugin)") - p.executedPreHooks = i + 1 - continue - } + req, shortCircuit, err = cp.PreMCPConnectionHook(pluginCtx, req) ... p.executedPreHooks = i + 1 } } func (p *PluginPipeline) RunMCPPostConnectionHooks(ctx *schemas.BifrostContext, resp *schemas.BifrostMCPConnectResponse, bifrostErr *schemas.BifrostError, runFrom int) (*schemas.BifrostMCPConnectResponse, *schemas.BifrostError) { ... for i := runFrom - 1; i >= 0; i-- { plugin := p.mcpPlugins[i] + cp, ok := plugin.(schemas.MCPConnectionPlugin) + if !ok { + continue + } + pluginName := plugin.GetName() p.logger.Debug("running MCP connect post-hook for plugin %s", pluginName) spanCtx, handle := p.tracer.StartSpan(ctx, fmt.Sprintf("plugin.%s.mcp_connect_posthook", sanitizeSpanName(pluginName)), schemas.SpanKindPlugin) ... - cp, ok := plugin.(schemas.MCPConnectionPlugin) - if !ok { - pluginCtx.ReleasePluginScope() - p.tracer.EndSpan(handle, schemas.SpanStatusOk, "skipped (not MCPConnectionPlugin)") - continue - } resp, bifrostErr, err = cp.PostMCPConnectionHook(pluginCtx, resp, bifrostErr) ... } }Also applies to: 6609-6627
🤖 Prompt for 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. In `@core/bifrost.go` around lines 6547 - 6568, The code currently starts a connect span and writes BifrostContextKeySpanID for every plugin before checking whether it implements schemas.MCPConnectionPlugin, producing synthetic "skipped" spans; to fix, only call p.tracer.StartSpan (and read/set BifrostContextKeySpanID) after you assert the plugin implements schemas.MCPConnectionPlugin (the type check on plugin.(schemas.MCPConnectionPlugin)) and just before invoking PreMCPConnectionHook/OnMCPConnectionHook; move the span creation, span-id extraction (sanitizeSpanName, p.tracer.StartSpan, ctx.SetValue(schemas.BifrostContextKeySpanID,...)) and corresponding p.tracer.EndSpan into the branches that run PreMCPConnectionHook and OnMCPConnectionHook so non-connection plugins keep being skipped without creating spans (apply the same change to the corresponding post-hook block around OnMCPConnectionHook).
🤖 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/agent.go`:
- Around line 318-323: The current branch only handles mcpResponse.ChatMessage
and falls back to createToolResultMessage when no ChatMessage exists; update the
branch to explicitly check for mcpResponse.ResponsesMessage (in addition to
ChatMessage) and forward that to channelToolResults (or convert it into the same
tool-result shape as ChatMessage if types differ) before falling back to
createToolResultMessage(toolCall, "", nil); ensure you reference mcpResponse,
ResponsesMessage, ChatMessage, channelToolResults, createToolResultMessage, and
toolCall when making the change so ResponsesMessage results are not lost.
In `@core/mcp/clientmanager.go`:
- Around line 1011-1020: The per-attempt context assignment for STDIO/SSE was
removed causing externalClient.Start to be called with a nil/incorrect context;
restore the assignment perAttemptCtx = longLivedCtx inside the branch that
checks config.ConnectionType == schemas.MCPConnectionTypeSSE ||
config.ConnectionType == schemas.MCPConnectionTypeSTDIO so that
externalClient.Start(perAttemptCtx) uses the long-lived context for subprocess
lifetime, and keep the existing comment about not deferring cancel (leave
m.logger.Debug(...) in place).
- Around line 212-221: VerifyPerUserOAuthConnection() currently creates
connectReq.Headers as an empty map which drops static headers in config.Headers;
update the function to initialize connectReq.Headers by copying config.Headers
into it, but filter out any Authorization/authorization keys so the OAuth flow
supplies its own token (i.e., for each k,v in config.Headers set
connectReq.Headers[k]=v unless strings.EqualFold(k,"authorization")), ensuring
the headers map is non-nil before PreHooks run so verification sees the same
tenant/custom headers as normal connects.
In `@core/mcp/healthmonitor.go`:
- Around line 149-155: When preparing the clientName used for hook-aware probes
(e.g., ping/list_tools) in healthmonitor.go, fall back to stable identifiers
when ExecutionConfig.Name is nil or empty: if clientState.ExecutionConfig == nil
or clientState.ExecutionConfig.Name == "", set clientName = clientState.Name
(and if that is empty too, set clientName = chm.clientID) so plugin-side
filtering/logging receives a non-empty identifier; apply the same fallback logic
in the other occurrence mentioned (the block around the 181-187 region) to
ensure both probe paths always pass a stable clientName.
In `@core/mcp/pluginpipeline.go`:
- Around line 342-362: runPingWithHooks always returns an error string
unconditionally which causes successes to be reported as failures and may panic
when bErr is nil; update the function (around the use of bErr from
manager.runWithPluginPipeline in runPingWithHooks) to check if bErr == nil and
return nil on success, otherwise return a formatted error (e.g.,
fmt.Errorf("ping failed: %s", bErr.GetErrorString())) so you don't call
GetErrorString on a nil bErr or report success as failure.
In `@plugins/governance/main.go`:
- Around line 1509-1512: The PostMCPHook is currently only skipping early when
resp != nil && resp.ChatMessage == nil && resp.ResponsesMessage == nil, which
misses cases where resp == nil for non-tool errors (e.g., failed
list_tools/ping/connect) and allows UpdateUsage to charge usage; modify the
PostMCPHook to use the same gate as PreMCPHook by treating nil resp or non-tool
envelopes as non-tool executions and returning before calling UpdateUsage—i.e.,
check if resp == nil OR (resp.ChatMessage == nil && resp.ResponsesMessage ==
nil) and return (resp, bifrostErr, nil) to avoid charging virtual keys for those
paths.
In `@plugins/logging/main.go`:
- Around line 1262-1271: The PostMCPHook currently only gates logging by
inspecting resp (and calling bifrost.IsCodemodeTool(resp.ExtraFields.ToolName)),
which lets resp==nil error paths fall through and create synthetic MCP tool
logs; update PostMCPHook to use the same tool-execution gate used in PreMCPHook
by checking the original request classification or the presence of the pending
MCP log entry before early-returning—e.g., use the pending entry flag created in
PreMCPHook (or the original request's tool name/type) instead of relying solely
on resp and bifrost.IsCodemodeTool, and skip logging/error-path synthetic-entry
creation when no pending entry exists.
---
Outside diff comments:
In `@core/mcp/toolsync.go`:
- Around line 133-154: The current sync unconditionally overwrites
clientState.ToolMap and clientState.ToolNameMapping with newTools/newMapping
returned by cts.manager.runListToolsWithHooks, which lets hook-suppressed
(empty) payloads erase the existing maps; change the logic after the
runListToolsWithHooks call to only update the maps when the hook path returned a
real list (e.g., newTools or newMapping is non-empty/non-nil). Concretely: after
obtaining newTools, newMapping, err from cts.manager.runListToolsWithHooks, if
err != nil keep existing maps as you already do; else if both len(newTools) == 0
and (newMapping == nil || len(newMapping) == 0) skip the write/update and
log/debug that hooks suppressed the payload; otherwise proceed to acquire
cts.manager.mu and atomically assign clientState.ToolMap = newTools and
clientState.ToolNameMapping = newMapping. Ensure you reference
runListToolsWithHooks, clientState.ToolMap and clientState.ToolNameMapping when
making the change.
---
Nitpick comments:
In `@core/bifrost.go`:
- Around line 6547-6568: The code currently starts a connect span and writes
BifrostContextKeySpanID for every plugin before checking whether it implements
schemas.MCPConnectionPlugin, producing synthetic "skipped" spans; to fix, only
call p.tracer.StartSpan (and read/set BifrostContextKeySpanID) after you assert
the plugin implements schemas.MCPConnectionPlugin (the type check on
plugin.(schemas.MCPConnectionPlugin)) and just before invoking
PreMCPConnectionHook/OnMCPConnectionHook; move the span creation, span-id
extraction (sanitizeSpanName, p.tracer.StartSpan,
ctx.SetValue(schemas.BifrostContextKeySpanID,...)) and corresponding
p.tracer.EndSpan into the branches that run PreMCPConnectionHook and
OnMCPConnectionHook so non-connection plugins keep being skipped without
creating spans (apply the same change to the corresponding post-hook block
around OnMCPConnectionHook).
In `@core/utils.go`:
- Around line 412-414: Replace the nonstandard deprecation comment above
GetErrorMessage with Go's recognized form by prefixing the sentence with
"Deprecated:" (e.g., "Deprecated: use err.GetErrorString() instead; will be
removed in a future release."), so gopls/godoc will surface the migration hint
for callers of GetErrorMessage (which wraps
schemas.BifrostError.GetErrorString).
🪄 Autofix (Beta)
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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 59f04791-47af-4652-b4f3-43dd1b197311
📒 Files selected for processing (48)
core/bifrost.gocore/internal/mcptests/agent_adapter_test.gocore/internal/mcptests/agent_basic_test.gocore/internal/mcptests/agent_context_filtering_test.gocore/internal/mcptests/agent_error_handling_test.gocore/internal/mcptests/agent_filtering_test.gocore/internal/mcptests/agent_limits_test.gocore/internal/mcptests/agent_mixed_permissions_test.gocore/internal/mcptests/agent_multiconnection_test.gocore/internal/mcptests/agent_parallel_execution_test.gocore/internal/mcptests/agent_request_id_test.gocore/internal/mcptests/agent_state_transitions_test.gocore/internal/mcptests/agent_test_helpers.gocore/internal/mcptests/agent_test_helpers_example_test.gocore/internal/mcptests/codemode_agent_multiturn_test.gocore/internal/mcptests/codemode_agent_singleturn_test.gocore/internal/mcptests/codemode_agent_test.gocore/internal/mcptests/codemode_vs_noncodemode_test.gocore/internal/mcptests/connect_ping_listtools_test.gocore/internal/mcptests/context_propagation_test.gocore/internal/mcptests/test_plugins.gocore/internal/mcptests/tool_call_id_test.gocore/mcp/agent.gocore/mcp/agent_test.gocore/mcp/clientmanager.gocore/mcp/codemode.gocore/mcp/codemode/starlark/executecode.gocore/mcp/codemode/starlark/starlark.gocore/mcp/codemode/starlark/starlark_test.gocore/mcp/exec.gocore/mcp/healthmonitor.gocore/mcp/interface.gocore/mcp/mcp.gocore/mcp/pluginpipeline.gocore/mcp/toolmanager.gocore/mcp/toolmanager_test.gocore/mcp/toolsync.gocore/mcp/utils.gocore/schemas/bifrost.gocore/schemas/plugin.gocore/schemas/plugin_native.gocore/schemas/trace.gocore/utils.goframework/plugins/soloader.goframework/plugins/soplugin.goplugins/governance/main.goplugins/logging/main.goui/app/workspace/config/views/mcpView.tsx
💤 Files with no reviewable changes (19)
- core/mcp/codemode.go
- core/internal/mcptests/agent_test_helpers_example_test.go
- core/internal/mcptests/agent_multiconnection_test.go
- core/internal/mcptests/agent_test_helpers.go
- core/internal/mcptests/codemode_agent_multiturn_test.go
- core/internal/mcptests/tool_call_id_test.go
- core/internal/mcptests/codemode_vs_noncodemode_test.go
- core/internal/mcptests/agent_state_transitions_test.go
- core/internal/mcptests/agent_error_handling_test.go
- core/internal/mcptests/agent_context_filtering_test.go
- core/internal/mcptests/agent_adapter_test.go
- core/internal/mcptests/context_propagation_test.go
- core/internal/mcptests/agent_request_id_test.go
- core/internal/mcptests/codemode_agent_singleturn_test.go
- core/internal/mcptests/agent_mixed_permissions_test.go
- core/internal/mcptests/agent_parallel_execution_test.go
- core/internal/mcptests/agent_filtering_test.go
- core/internal/mcptests/codemode_agent_test.go
- core/internal/mcptests/agent_basic_test.go
d2eb077 to
576df36
Compare
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/utils.go`:
- Around line 413-414: GetErrorMessage currently calls err.GetErrorString()
unconditionally which can panic if a legacy caller passes nil; modify
GetErrorMessage to guard against nil by checking if err == nil and returning an
empty string (or another safe default) when nil, otherwise return
err.GetErrorString(); reference function GetErrorMessage, type
schemas.BifrostError, and method GetErrorString to locate the change.
🪄 Autofix (Beta)
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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 9734f582-796d-40f5-86fb-6ca212c3029b
📒 Files selected for processing (48)
core/bifrost.gocore/internal/mcptests/agent_adapter_test.gocore/internal/mcptests/agent_basic_test.gocore/internal/mcptests/agent_context_filtering_test.gocore/internal/mcptests/agent_error_handling_test.gocore/internal/mcptests/agent_filtering_test.gocore/internal/mcptests/agent_limits_test.gocore/internal/mcptests/agent_mixed_permissions_test.gocore/internal/mcptests/agent_multiconnection_test.gocore/internal/mcptests/agent_parallel_execution_test.gocore/internal/mcptests/agent_request_id_test.gocore/internal/mcptests/agent_state_transitions_test.gocore/internal/mcptests/agent_test_helpers.gocore/internal/mcptests/agent_test_helpers_example_test.gocore/internal/mcptests/codemode_agent_multiturn_test.gocore/internal/mcptests/codemode_agent_singleturn_test.gocore/internal/mcptests/codemode_agent_test.gocore/internal/mcptests/codemode_vs_noncodemode_test.gocore/internal/mcptests/connect_ping_listtools_test.gocore/internal/mcptests/context_propagation_test.gocore/internal/mcptests/test_plugins.gocore/internal/mcptests/tool_call_id_test.gocore/mcp/agent.gocore/mcp/agent_test.gocore/mcp/clientmanager.gocore/mcp/codemode.gocore/mcp/codemode/starlark/executecode.gocore/mcp/codemode/starlark/starlark.gocore/mcp/codemode/starlark/starlark_test.gocore/mcp/exec.gocore/mcp/healthmonitor.gocore/mcp/interface.gocore/mcp/mcp.gocore/mcp/pluginpipeline.gocore/mcp/toolmanager.gocore/mcp/toolmanager_test.gocore/mcp/toolsync.gocore/mcp/utils.gocore/schemas/bifrost.gocore/schemas/plugin.gocore/schemas/plugin_native.gocore/schemas/trace.gocore/utils.goframework/plugins/soloader.goframework/plugins/soplugin.goplugins/governance/main.goplugins/logging/main.goui/app/workspace/config/views/mcpView.tsx
💤 Files with no reviewable changes (19)
- core/internal/mcptests/agent_test_helpers.go
- core/mcp/codemode.go
- core/internal/mcptests/tool_call_id_test.go
- core/internal/mcptests/codemode_vs_noncodemode_test.go
- core/internal/mcptests/codemode_agent_singleturn_test.go
- core/internal/mcptests/agent_request_id_test.go
- core/internal/mcptests/agent_filtering_test.go
- core/internal/mcptests/agent_adapter_test.go
- core/internal/mcptests/codemode_agent_multiturn_test.go
- core/internal/mcptests/agent_context_filtering_test.go
- core/internal/mcptests/agent_basic_test.go
- core/internal/mcptests/codemode_agent_test.go
- core/internal/mcptests/agent_parallel_execution_test.go
- core/internal/mcptests/agent_multiconnection_test.go
- core/internal/mcptests/agent_error_handling_test.go
- core/internal/mcptests/agent_test_helpers_example_test.go
- core/internal/mcptests/agent_state_transitions_test.go
- core/internal/mcptests/context_propagation_test.go
- core/internal/mcptests/agent_mixed_permissions_test.go
✅ Files skipped from review due to trivial changes (3)
- core/mcp/codemode/starlark/starlark_test.go
- core/schemas/trace.go
- ui/app/workspace/config/views/mcpView.tsx
🚧 Files skipped from review as they are similar to previous changes (21)
- core/mcp/toolsync.go
- core/mcp/codemode/starlark/starlark.go
- core/schemas/plugin_native.go
- core/mcp/codemode/starlark/executecode.go
- core/mcp/interface.go
- core/mcp/pluginpipeline.go
- framework/plugins/soloader.go
- core/mcp/utils.go
- core/schemas/plugin.go
- core/mcp/agent.go
- core/mcp/healthmonitor.go
- core/internal/mcptests/agent_limits_test.go
- core/mcp/toolmanager_test.go
- core/internal/mcptests/connect_ping_listtools_test.go
- core/schemas/bifrost.go
- core/internal/mcptests/test_plugins.go
- core/mcp/toolmanager.go
- core/mcp/exec.go
- core/mcp/mcp.go
- core/bifrost.go
- core/mcp/clientmanager.go
Merge activity
|
#3389) ## Summary Briefly explain the purpose of this PR and the problem it solves. ## Changes - What was changed and why - Any notable design decisions or trade-offs ## Type of change - [ ] Bug fix - [ ] Feature - [ ] Refactor - [ ] Documentation - [ ] Chore/CI ## Affected areas - [ ] Core (Go) - [ ] Transports (HTTP) - [ ] Providers/Integrations - [ ] Plugins - [ ] UI (React) - [ ] Docs ## How to test Describe the steps to validate this change. Include commands and expected outcomes. ```sh # Core/Transports go version go test ./... # UI cd ui pnpm i || npm i pnpm test || npm test pnpm build || npm run build ``` If adding new configs or environment variables, document them here. ## Screenshots/Recordings If UI changes, add before/after screenshots or short clips. ## Breaking changes - [ ] Yes - [ ] No If yes, describe impact and migration instructions. ## Related issues Link related issues and discussions. Example: Closes #123 ## Security considerations Note any security implications (auth, secrets, PII, sandboxing, etc.). ## Checklist - [ ] I read `docs/contributing/README.md` and followed the guidelines - [ ] I added/updated tests where appropriate - [ ] I updated documentation where needed - [ ] I verified builds succeed (Go and UI) - [ ] I verified the CI pipeline passes locally if applicable
#3389) ## Summary Briefly explain the purpose of this PR and the problem it solves. ## Changes - What was changed and why - Any notable design decisions or trade-offs ## Type of change - [ ] Bug fix - [ ] Feature - [ ] Refactor - [ ] Documentation - [ ] Chore/CI ## Affected areas - [ ] Core (Go) - [ ] Transports (HTTP) - [ ] Providers/Integrations - [ ] Plugins - [ ] UI (React) - [ ] Docs ## How to test Describe the steps to validate this change. Include commands and expected outcomes. ```sh # Core/Transports go version go test ./... # UI cd ui pnpm i || npm i pnpm test || npm test pnpm build || npm run build ``` If adding new configs or environment variables, document them here. ## Screenshots/Recordings If UI changes, add before/after screenshots or short clips. ## Breaking changes - [ ] Yes - [ ] No If yes, describe impact and migration instructions. ## Related issues Link related issues and discussions. Example: Closes #123 ## Security considerations Note any security implications (auth, secrets, PII, sandboxing, etc.). ## Checklist - [ ] I read `docs/contributing/README.md` and followed the guidelines - [ ] I added/updated tests where appropriate - [ ] I updated documentation where needed - [ ] I verified builds succeed (Go and UI) - [ ] I verified the CI pipeline passes locally if applicable
…hropic (#3420) * feat: add granular RBAC checks for API keys, inference, metrics, and filter inaccessible sidebar items (#3295) ## Summary This PR improves RBAC granularity in the sidebar by introducing dedicated resource types for `APIKeys`, `Inference`, and `Metrics`, and fixes sidebar visibility logic so that items and groups are hidden when the user lacks access rather than relying on broader, less specific permissions. ## Changes - Added three new `RbacResource` enum values: `APIKeys`, `Inference`, and `Metrics` to the fallback RBAC context. - The API Keys sidebar item now gates access via the new `hasAPIKeyAccess` (`RbacResource.APIKeys`) check instead of the generic `hasSettingsAccess`. - The MCP Logs sidebar item now correctly gates access via `hasMCPGatewayAccess` instead of the unrelated `hasLogsAccess`. - Introduced an `accessibleItems` memoized computation that filters out sidebar items and entire groups whose sub-items are all inaccessible, ensuring users never see empty navigation sections. Previously, access filtering only happened during search. - Removed unused imports (`PanelLeft`, `PanelRight`, `cn`). ## Type of change - [ ] Bug fix - [x] Feature - [x] Refactor - [ ] Documentation - [ ] Chore/CI ## Affected areas - [ ] Core (Go) - [ ] Transports (HTTP) - [ ] Providers/Integrations - [ ] Plugins - [x] UI (React) - [ ] Docs ## How to test 1. Log in as a user with restricted RBAC permissions that exclude `APIKeys` and/or `Settings`. 2. Verify the API Keys entry under the Config section is hidden for users without `APIKeys` view permission. 3. Verify the MCP Logs entry is hidden for users without `MCPGateway` view permission. 4. Verify that sidebar groups with no accessible sub-items are hidden entirely rather than showing an empty group. 5. Verify that users with full access see no change in sidebar behavior. ```sh cd ui pnpm i || npm i pnpm build || npm run build ``` ## Screenshots/Recordings _Add before/after screenshots showing sidebar items hidden for restricted users._ ## Breaking changes - [ ] Yes - [x] No ## Related issues _Link related issues here._ ## Security considerations Access control checks for API Keys management are now scoped to a dedicated `APIKeys` RBAC resource rather than the broader `Settings` resource, reducing the risk of unintended access to key management for users who have settings visibility but should not manage API keys. ## Checklist - [ ] I read `docs/contributing/README.md` and followed the guidelines - [ ] I added/updated tests where appropriate - [ ] I updated documentation where needed - [ ] I verified builds succeed (Go and UI) - [ ] I verified the CI pipeline passes locally if applicable * fix: hide provider and key action buttons based on RBAC permissions (#3296) ## Summary Improves RBAC enforcement across the configuration and providers UI by hiding action controls entirely when the user lacks the required permissions, rather than rendering them in a disabled state. ## Changes - The config layout now checks the current route to determine which RBAC resource to evaluate — `APIKeys` for `/workspace/config/api-keys` routes and `Settings` for all others, so users without API key access are not incorrectly blocked from other config pages. - The "Add Provider" dropdown is now conditionally rendered only when the user has provider create access, instead of always rendering with a disabled state. - The "Add new key" button in the model provider keys table is now hidden entirely when the user lacks update access, rather than being rendered as disabled. - The per-row actions dropdown menu (Edit/Delete) in the model provider keys table is now hidden entirely when the user has neither update nor delete access. ## Type of change - [ ] Bug fix - [x] Feature - [ ] Refactor - [ ] Documentation - [ ] Chore/CI ## Affected areas - [ ] Core (Go) - [ ] Transports (HTTP) - [ ] Providers/Integrations - [ ] Plugins - [x] UI (React) - [ ] Docs ## How to test 1. Log in as a user with restricted RBAC permissions (no `APIKeys` view access, no provider create/update/delete access). 2. Navigate to `/workspace/config/api-keys` — the no-permission view should be shown. 3. Navigate to another config page — it should load normally. 4. Navigate to the Providers page — the "Add Provider" dropdown should not be visible. 5. Open a provider's key table — the "Add new key" button and the per-row actions menu should not be visible. 6. Log in as a user with full access and verify all controls appear and function as expected. ```sh cd ui pnpm i || npm i pnpm build || npm run build ``` ## Screenshots/Recordings If UI changes, add before/after screenshots or short clips. ## Breaking changes - [ ] Yes - [x] No ## Related issues Link related issues and discussions. ## Security considerations These changes tighten UI-level RBAC enforcement by ensuring that action controls are not rendered at all for unauthorized users, reducing the surface area for accidental or misleading interactions. Server-side authorization remains the authoritative enforcement layer. ## Checklist - [ ] I read `docs/contributing/README.md` and followed the guidelines - [ ] I added/updated tests where appropriate - [ ] I updated documentation where needed - [ ] I verified builds succeed (Go and UI) - [ ] I verified the CI pipeline passes locally if applicable * fix: hide delete log button instead of disabling it when user lacks delete access (#3314) ## Summary The delete button in log tables was always rendered (just disabled) for users without delete access. This PR hides the actions column entirely when the user lacks delete permissions, and fixes the RBAC resource check for MCP logs to use the correct `MCPGateway` resource instead of `Logs`. ## Changes - The actions column in both the workspace logs and MCP logs tables is now conditionally included in the column definitions only when `hasDeleteAccess` is `true`, rather than always rendering a disabled button. - The delete button styling was updated to use more visible destructive colors (`text-destructive/60 border-destructive/60`) instead of the previous muted secondary foreground styles. - The RBAC resource used to gate delete access on the MCP logs page was corrected from `RbacResource.Logs` to `RbacResource.MCPGateway`. ## Type of change - [x] Bug fix - [ ] Feature - [ ] Refactor - [ ] Documentation - [ ] Chore/CI ## Affected areas - [ ] Core (Go) - [ ] Transports (HTTP) - [ ] Providers/Integrations - [ ] Plugins - [x] UI (React) - [ ] Docs ## How to test 1. Log in as a user **without** delete access on Logs or MCPGateway resources. 2. Navigate to the workspace logs page and the MCP logs page. 3. Verify the delete button/column is not visible. 4. Log in as a user **with** delete access. 5. Verify the delete button appears and is functional. ```sh cd ui pnpm i pnpm test pnpm build ``` ## Screenshots/Recordings Before: Delete button rendered but disabled for users without access. After: Delete column is hidden entirely for users without delete access. ## Breaking changes - [ ] Yes - [x] No ## Related issues ## Security considerations The RBAC fix ensures MCP log deletion is gated on the correct `MCPGateway` resource permission, preventing users with only `Logs` delete access from incorrectly being granted delete access to MCP logs. ## Checklist - [ ] I read `docs/contributing/README.md` and followed the guidelines - [ ] I added/updated tests where appropriate - [ ] I updated documentation where needed - [ ] I verified builds succeed (Go and UI) - [ ] I verified the CI pipeline passes locally if applicable * feat: add `MCPLogs` RBAC resource and enforce access control on MCP logs route and sidebar (#3316) ## Summary Introduces a dedicated `MCPLogs` RBAC resource, decoupling MCP log access control from the `MCPGateway` resource. This allows permissions for viewing and deleting MCP logs to be managed independently from gateway-level permissions. ## Changes - Added `MCPLogs` as a new `RbacResource` enum value in the fallback RBAC context. - The MCP Logs route now checks `MCPLogs` view permission and renders a `NoPermissionView` when access is denied, rather than rendering the page unconditionally. - Delete access on the MCP Logs page now checks `RbacResource.MCPLogs` instead of `RbacResource.MCPGateway`. - The sidebar MCP Logs entry now uses `hasMCPLogsAccess` (derived from `RbacResource.MCPLogs`) to control visibility, rather than reusing `hasMCPGatewayAccess`. ## Type of change - [ ] Bug fix - [x] Feature - [ ] Refactor - [ ] Documentation - [ ] Chore/CI ## Affected areas - [ ] Core (Go) - [ ] Transports (HTTP) - [ ] Providers/Integrations - [ ] Plugins - [x] UI (React) - [ ] Docs ## How to test 1. Configure a role that has `MCPGateway` access but **no** `MCPLogs` access. 2. Log in as a user with that role and navigate to the MCP Logs page — the `NoPermissionView` should be displayed and the sidebar entry should be hidden. 3. Grant the role `MCPLogs` view access and confirm the page and sidebar entry become accessible. 4. Verify that delete functionality on the MCP Logs page is gated by `MCPLogs` delete permission independently of `MCPGateway` delete permission. ```sh cd ui pnpm i || npm i pnpm test || npm test pnpm build || npm run build ``` ## Screenshots/Recordings N/A ## Breaking changes - [x] Yes - [ ] No Any role configuration that previously relied on `MCPGateway` permissions to grant access to MCP Logs will need to be updated to explicitly grant `MCPLogs` permissions. ## Related issues N/A ## Security considerations Access to MCP log data (which may contain sensitive tool execution details) is now enforced by a dedicated RBAC resource, reducing the risk of unintended access through overly broad `MCPGateway` permissions. ## Checklist - [ ] I read `docs/contributing/README.md` and followed the guidelines - [ ] I added/updated tests where appropriate - [ ] I updated documentation where needed - [ ] I verified builds succeed (Go and UI) - [ ] I verified the CI pipeline passes locally if applicable * feat: add `MCPToolGroups` RBAC resource and separate access control from `MCPGateway` (#3319) ## Summary Introduces a dedicated `MCPToolGroups` RBAC resource to allow fine-grained access control over the MCP Tool Groups section, independent of the broader `MCPGateway` resource. ## Changes - Added `MCPToolGroups` as a new `RbacResource` enum value in the fallback RBAC context. - Updated the MCP Tool Groups route layout to check `MCPToolGroups` view permission instead of `MCPGateway`. - Updated the sidebar so the "Tool Groups" sub-item uses `hasMCPToolGroupsAccess`, while the parent MCP nav item remains visible if the user has access to either `MCPGateway` or `MCPToolGroups`. ## Type of change - [ ] Bug fix - [x] Feature - [ ] Refactor - [ ] Documentation - [ ] Chore/CI ## Affected areas - [ ] Core (Go) - [ ] Transports (HTTP) - [ ] Providers/Integrations - [ ] Plugins - [x] UI (React) - [ ] Docs ## How to test 1. Configure a role that has access to `MCPGateway` but not `MCPToolGroups`. Verify the "Tool Groups" sidebar item is hidden and navigating to `/workspace/mcp-tool-groups` shows the no-permission view. 2. Configure a role with access to `MCPToolGroups` but not `MCPGateway`. Verify the "Tool Groups" sidebar item is visible and accessible, while other MCP Gateway sections remain restricted. 3. Configure a role with access to both. Verify all MCP sub-items are visible and accessible. ```sh cd ui pnpm i || npm i pnpm build || npm run build ``` ## Breaking changes - [ ] Yes - [x] No ## Related issues ## Security considerations Access to the MCP Tool Groups page is now governed by its own RBAC resource (`MCPToolGroups`), allowing enterprise deployments to restrict tool group management independently from MCP Gateway configuration. ## Checklist - [ ] I read `docs/contributing/README.md` and followed the guidelines - [ ] I added/updated tests where appropriate - [ ] I updated documentation where needed - [ ] I verified builds succeed (Go and UI) - [ ] I verified the CI pipeline passes locally if applicable * fix: remove 100-item upper limit on paginated teams query (#3323) ## Summary Removes the upper bound limit cap of 100 on paginated team queries, allowing callers to request more than 100 teams per page. ## Changes - Removed the `limit > 100` guard in `GetTeamsPaginated` that was silently capping the page size to 100. This allows consumers to specify larger page sizes when needed. ## Type of change - [ ] Bug fix - [x] Feature - [ ] Refactor - [ ] Documentation - [ ] Chore/CI ## Affected areas - [x] Core (Go) - [ ] Transports (HTTP) - [ ] Providers/Integrations - [ ] Plugins - [ ] UI (React) - [ ] Docs ## How to test ```sh go test ./... ``` Verify that a call to `GetTeamsPaginated` with a `limit` greater than 100 returns the expected number of results rather than being silently truncated to 100. ## Screenshots/Recordings N/A ## Breaking changes - [ ] Yes - [x] No ## Related issues ## Security considerations Removing the page size cap could allow large queries that put additional load on the database. Callers should ensure reasonable limits are enforced at the API layer if unbounded queries are a concern. ## Checklist - [ ] I read `docs/contributing/README.md` and followed the guidelines - [ ] I added/updated tests where appropriate - [ ] I updated documentation where needed - [ ] I verified builds succeed (Go and UI) - [ ] I verified the CI pipeline passes locally if applicable * feat: extend mcp plugin interface for list tools, ping and connections (#3389) ## Summary Briefly explain the purpose of this PR and the problem it solves. ## Changes - What was changed and why - Any notable design decisions or trade-offs ## Type of change - [ ] Bug fix - [ ] Feature - [ ] Refactor - [ ] Documentation - [ ] Chore/CI ## Affected areas - [ ] Core (Go) - [ ] Transports (HTTP) - [ ] Providers/Integrations - [ ] Plugins - [ ] UI (React) - [ ] Docs ## How to test Describe the steps to validate this change. Include commands and expected outcomes. ```sh # Core/Transports go version go test ./... # UI cd ui pnpm i || npm i pnpm test || npm test pnpm build || npm run build ``` If adding new configs or environment variables, document them here. ## Screenshots/Recordings If UI changes, add before/after screenshots or short clips. ## Breaking changes - [ ] Yes - [ ] No If yes, describe impact and migration instructions. ## Related issues Link related issues and discussions. Example: Closes #123 ## Security considerations Note any security implications (auth, secrets, PII, sandboxing, etc.). ## Checklist - [ ] I read `docs/contributing/README.md` and followed the guidelines - [ ] I added/updated tests where appropriate - [ ] I updated documentation where needed - [ ] I verified builds succeed (Go and UI) - [ ] I verified the CI pipeline passes locally if applicable * package bumps (#3422) ## Summary Bumps several Go dependencies to their latest patch versions across all modules in the repository. ## Changes - `github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream` upgraded from `v1.7.8` → `v1.7.10` - `github.com/aws/smithy-go` upgraded from `v1.24.2` → `v1.25.1` - `github.com/jackc/pgx/v5` upgraded from `v5.9.1` → `v5.9.2` ## Type of change - [ ] Bug fix - [ ] Feature - [ ] Refactor - [ ] Documentation - [x] Chore/CI ## Affected areas - [x] Core (Go) - [x] Transports (HTTP) - [ ] Providers/Integrations - [x] Plugins - [ ] UI (React) - [ ] Docs ## How to test ```sh go test ./... ``` ## Breaking changes - [ ] Yes - [x] No ## Security considerations No security implications. These are routine patch-level dependency upgrades with no API surface changes. ## Checklist - [ ] I read `docs/contributing/README.md` and followed the guidelines - [ ] I added/updated tests where appropriate - [ ] I updated documentation where needed - [x] I verified builds succeed (Go and UI) - [ ] I verified the CI pipeline passes locally if applicable * fix: fixes model passthrough prefix stripping in advisor tool for anthropic --------- Co-authored-by: Suresh Chaudhary <83772622+impoiler@users.noreply.github.com> Co-authored-by: Pratham Mishra <99235987+Pratham-Mishra04@users.noreply.github.com> Co-authored-by: Akshay Deo <akshay@akshaydeo.com>

Summary
Briefly explain the purpose of this PR and the problem it solves.
Changes
Type of change
Affected areas
How to test
Describe the steps to validate this change. Include commands and expected outcomes.
If adding new configs or environment variables, document them here.
Screenshots/Recordings
If UI changes, add before/after screenshots or short clips.
Breaking changes
If yes, describe impact and migration instructions.
Related issues
Link related issues and discussions. Example: Closes #123
Security considerations
Note any security implications (auth, secrets, PII, sandboxing, etc.).
Checklist
docs/contributing/README.mdand followed the guidelines