Skip to content

feat: add connection_type, auth_type, state, and virtual_key filters to MCP clients list - #4839

Merged
Pratham-Mishra04 merged 1 commit into
devfrom
07-02-feat_mcp_clients_filters_support_backend
Jul 2, 2026
Merged

feat: add connection_type, auth_type, state, and virtual_key filters to MCP clients list#4839
Pratham-Mishra04 merged 1 commit into
devfrom
07-02-feat_mcp_clients_filters_support_backend

Conversation

@impoiler

@impoiler impoiler commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Summary

Extends the GET /api/mcp/clients endpoint with richer filtering capabilities, allowing callers to narrow MCP client results by connection type, auth type, code-mode flag, disabled state, runtime connection state (connected/disconnected), and virtual-key access — all within the same paginated database query.

Changes

  • Added ConnectionTypes, AuthTypes, IsCodeModeClient, Disabled, StateClientIDs, StateInclude, OnlyAllVirtualKeys, and VirtualKeyIDs fields to MCPClientsQueryParams.
  • Applied the new filters in GetMCPClientsPaginated: IN-list filters for connection/auth types, boolean column filters for code-mode and disabled, a runtime state filter that translates a connected-ID set into IN/NOT IN clauses, and a virtual-key access filter that ORs the allow_on_all_virtual_keys flag with an explicit-assignment subquery over the VK⇄MCP join table.
  • Moved the Bifrost engine call (GetMCPClients) to the top of getMCPClientsPaginated so the live connected-ID set is available before the DB query executes, enabling the state filter to be pushed into the paginated query rather than applied post-fetch.
  • Parsed the new query parameters (connection_type, auth_type, virtual_keys, all_virtual_keys, state, code_mode, disabled) in getMCPClients, with validation for limit/offset and a parseBoolQueryArg helper for optional boolean facets.
  • Selecting both connected and disconnected states simultaneously (or neither) is treated as a no-op, avoiding unnecessary constraints.

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

go test ./framework/configstore/... ./transports/bifrost-http/...

# Filter by connection type
curl "http://localhost:8080/api/mcp/clients?connection_type=http,sse"

# Filter by runtime state
curl "http://localhost:8080/api/mcp/clients?state=connected"
curl "http://localhost:8080/api/mcp/clients?state=disconnected"

# Filter by virtual-key access
curl "http://localhost:8080/api/mcp/clients?all_virtual_keys=true"
curl "http://localhost:8080/api/mcp/clients?virtual_keys=vk-1,vk-2"

# Filter by auth type and disabled state
curl "http://localhost:8080/api/mcp/clients?auth_type=oauth&disabled=false"

# Filter by code-mode
curl "http://localhost:8080/api/mcp/clients?code_mode=true"

Breaking changes

  • Yes
  • No

Related issues

Security considerations

The virtual-key access filter ensures clients are only surfaced when they are either open to all virtual keys or explicitly assigned to one of the requested VK IDs, preventing unintended cross-tenant visibility when filtering by VK.

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

@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 94b322f6-06c6-47e2-99ab-8e7ad7677cb8

📥 Commits

Reviewing files that changed from the base of the PR and between 7cdb87a and af49b62.

📒 Files selected for processing (3)
  • framework/configstore/rdb.go
  • framework/configstore/store.go
  • transports/bifrost-http/handlers/mcp.go
🚧 Files skipped from review as they are similar to previous changes (3)
  • framework/configstore/store.go
  • transports/bifrost-http/handlers/mcp.go
  • framework/configstore/rdb.go

📝 Walkthrough

Summary by CodeRabbit

  • New Features
    • Expanded MCP client listing filtering to support connection type, auth type, code-mode, disabled, connection state (connected/disconnected), and virtual-key access (all virtual keys vs explicitly assigned keys).
  • Bug Fixes
    • Improved MCP client listing pagination and query parsing with stricter limit/offset validation (invalid/negative now return HTTP 400).
    • Connection-state filtering is now applied consistently prior to pagination, using the requested state selection.
  • Other
    • Added clearer handling for optional boolean filters, distinguishing “not provided” from invalid values (invalid now return HTTP 400).

Walkthrough

This PR expands MCP client listing filters, adds stricter HTTP query parsing, and applies the new filters in the config store query path.

Changes

MCP Client Filtering

Layer / File(s) Summary
Query params contract expansion
framework/configstore/store.go
MCPClientsQueryParams gains connection/auth type lists, tri-state boolean filters, runtime state fields, and virtual-key access fields with documented match semantics.
HTTP handler wiring
transports/bifrost-http/handlers/mcp.go
getMCPClients builds MCPClientsQueryParams from query args with stricter pagination validation and bool parsing; getMCPClientsPaginated resolves runtime state into StateClientIDs and StateInclude using connected MCP clients.
SQL predicate implementation
framework/configstore/rdb.go
GetMCPClientsPaginated applies connection/auth type filters, code-mode and disabled filters, connected/disconnected client filters, and virtual-key accessibility predicates backed by TableVirtualKeyMCPConfig.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

  • maximhq/bifrost#4767: Both PRs modify MCP clients listing end-to-end by extending MCPClientsQueryParams and applying new filters through the handler and store path.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding new MCP client filters to the list endpoint.
Description check ✅ Passed The description follows the template well and covers summary, changes, type, affected areas, testing, breaking changes, security, and checklist.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 07-02-feat_mcp_clients_filters_support_backend

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.12.2)

level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain main module or its selected dependencies"


Comment @coderabbitai help to get the list of available commands.

impoiler commented Jul 2, 2026

Copy link
Copy Markdown
Contributor Author

@impoiler impoiler self-assigned this Jul 2, 2026
@impoiler impoiler changed the title feat: mcp clients filters support backend feat: add connection_type, auth_type, state, and virtual_key filters to MCP clients list Jul 2, 2026
@impoiler
impoiler marked this pull request as ready for review July 2, 2026 07:38
@greptile-apps

greptile-apps Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Confidence Score: 4/5

Safe to merge after confirming the default page size regression is intentional or restored.

The handler no longer pre-sets Limit:100, so any caller omitting the limit parameter now silently receives 25 rows instead of the original 100. All other new filters are implemented correctly with parameterized queries and proper 400 validation.

transports/bifrost-http/handlers/mcp.go — default limit changed from 100 to 25 for the MCP clients listing endpoint.

Important Files Changed

Filename Overview
framework/configstore/store.go Extends MCPClientsQueryParams with new filter fields (ConnectionTypes, AuthTypes, IsCodeModeClient, Disabled, StateClientIDs, StateInclude, OnlyAllVirtualKeys, VirtualKeyIDs); struct layout is clean with clear nil-pointer semantics for optional boolean filters.
framework/configstore/rdb.go Implements new filters in GetMCPClientsPaginated; logic is correct, but the OR-group for the VK filter uses s.DB() without WithContext(ctx), which can miss request-scoped GORM plugins (flagged in a previous thread).
transports/bifrost-http/handlers/mcp.go Parses new query parameters with solid validation, but the default page size for GET /api/mcp/clients silently regressed from 100 to 25 because the old Limit:100 default was removed and ClampPaginationParams defaults to 25.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant Client
    participant Handler as getMCPClients (mcp.go)
    participant Engine as Bifrost Engine
    participant Store as RDBConfigStore

    Client->>Handler: "GET /api/mcp/clients?state=connected&connection_type=http"
    Handler->>Handler: "Parse & validate query params (400 on bad values)"
    Handler->>Handler: Build MCPClientsQueryParams
    Handler->>Engine: GetMCPClients()
    Engine-->>Handler: []MCPClient (with State field)
    Handler->>Handler: "Filter connectedIDs where State==Connected"
    Handler->>Handler: "Set StateInclude=true, StateClientIDs=connectedIDs"
    Handler->>Handler: ClampPaginationParams(limit, offset)
    Handler->>Store: GetMCPClientsPaginated(ctx, params)
    Store->>Store: Apply filters (connection_type IN, client_id IN/NOT IN, VK subquery)
    Store->>Store: COUNT for total_count
    Store->>Store: SELECT + ORDER BY + LIMIT/OFFSET
    Store-->>Handler: ([]TableMCPClient, totalCount, err)
    Handler->>Handler: Merge live state/tools from connectedClientsMap
    Handler-->>Client: "JSON { clients, count, total_count, limit, offset }"
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant Client
    participant Handler as getMCPClients (mcp.go)
    participant Engine as Bifrost Engine
    participant Store as RDBConfigStore

    Client->>Handler: "GET /api/mcp/clients?state=connected&connection_type=http"
    Handler->>Handler: "Parse & validate query params (400 on bad values)"
    Handler->>Handler: Build MCPClientsQueryParams
    Handler->>Engine: GetMCPClients()
    Engine-->>Handler: []MCPClient (with State field)
    Handler->>Handler: "Filter connectedIDs where State==Connected"
    Handler->>Handler: "Set StateInclude=true, StateClientIDs=connectedIDs"
    Handler->>Handler: ClampPaginationParams(limit, offset)
    Handler->>Store: GetMCPClientsPaginated(ctx, params)
    Store->>Store: Apply filters (connection_type IN, client_id IN/NOT IN, VK subquery)
    Store->>Store: COUNT for total_count
    Store->>Store: SELECT + ORDER BY + LIMIT/OFFSET
    Store-->>Handler: ([]TableMCPClient, totalCount, err)
    Handler->>Handler: Merge live state/tools from connectedClientsMap
    Handler-->>Client: "JSON { clients, count, total_count, limit, offset }"
Loading

Reviews (4): Last reviewed commit: "feat: mcp clients filters support backen..." | Re-trigger Greptile

Comment thread transports/bifrost-http/handlers/mcp.go
Comment thread framework/configstore/rdb.go

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (3)
framework/configstore/store.go (1)

71-71: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

ConnectionTypes doc comment omits inprocess.

The comment documents connection types as (http | sse | stdio), but the schema (transports/config.schema.json) constrains connection_type to stdio|http|sse|inprocess. The missing inprocess value could mislead callers wiring this filter.

📝 Suggested fix
-	ConnectionTypes  []string // exact connection_type filter(s), OR semantics (http | sse | stdio)
+	ConnectionTypes  []string // exact connection_type filter(s), OR semantics (http | sse | stdio | inprocess)

As per path instructions, "mcp.client_configs[].connection_type is constrained to stdio|http|sse|inprocess... use these exact values when wiring request query params into DB filters."

🤖 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 `@framework/configstore/store.go` at line 71, Update the `ConnectionTypes`
field comment in `store.go` so it lists all valid `connection_type` values,
including `inprocess`, instead of only `(http | sse | stdio)`. Keep the comment
aligned with the schema used by `configstore` and
`mcp.client_configs[].connection_type`, and make sure any filter wiring
references the exact allowed set: `stdio`, `http`, `sse`, and `inprocess`.

Source: Path instructions

framework/configstore/rdb.go (1)

1619-1639: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Solid subquery/switch logic — consider adding table-driven tests.

The three-way switch correctly covers all reachable combinations (OnlyAllVirtualKeys alone, VK-subset alone, or both combined), and assignedSub is never nil where dereferenced. Given the non-trivial combinatorics (state in/out, code-mode/disabled tri-state, VK-access OR logic), consider adding table-driven test cases in rdb_test.go covering each filter combination to lock in behavior.

As per coding guidelines, **/*.go changes should apply "deterministic tests, and table-driven coverage for behavior changes."

🤖 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 `@framework/configstore/rdb.go` around lines 1619 - 1639, The VK access filter
logic in rdb.go is correct but lacks deterministic coverage for its
combinatorial cases. Add table-driven tests in rdb_test.go for the filter
behavior around OnlyAllVirtualKeys and VirtualKeyIDs, including each reachable
switch branch (all VKs only, subset only, and combined OR case) and any related
state/code-mode interactions. Use the existing query/filter entry points in
rdb.go and the VK access logic symbols to keep the tests aligned with the
implementation.

Source: Coding guidelines

transports/bifrost-http/handlers/mcp.go (1)

115-179: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Inconsistent validation for new filter facets vs. limit/offset.

limit/offset return 400 on invalid input, but the new facets don't:

  • parseBoolQueryArg (Lines 169-179) silently treats a malformed boolean (e.g., ?disabled=maybe) as "no filter" rather than erroring.
  • connection_type/auth_type (Lines 118-119) are passed straight into the SQL IN list with no validation against the schema-defined enum values, so a typo silently yields zero matching rows instead of a clear error.
  • state (Line 128) is similarly unvalidated — an unrecognized value silently no-ops the state filter.

Consider validating these against their known enum values (or at least returning 400 for unparseable booleans) for a clearer API contract, consistent with how limit/offset are already handled in this same function.

As per path instructions, "mcp.client_configs[].connection_type is constrained to stdio|http|sse|inprocess and auth_type to none|headers|oauth|per_user_oauth|per_user_headers; use these exact values when wiring request query params into DB filters."

🤖 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 `@transports/bifrost-http/handlers/mcp.go` around lines 115 - 179, The filter
parsing in getMCPClientsPaginated is too lenient compared with the existing
limit/offset handling. Update parseBoolQueryArg so malformed booleans for
code_mode/disabled return a 400 instead of silently becoming “no filter”, and
validate connection_type, auth_type, and state against their allowed enum values
before building MCPClientsQueryParams. Use the known enum sets in
mcp.client_configs and keep the query-to-filter mapping in handler logic so
typos surface as explicit bad-request errors rather than empty result sets.

Source: Path instructions

🤖 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.

Nitpick comments:
In `@framework/configstore/rdb.go`:
- Around line 1619-1639: The VK access filter logic in rdb.go is correct but
lacks deterministic coverage for its combinatorial cases. Add table-driven tests
in rdb_test.go for the filter behavior around OnlyAllVirtualKeys and
VirtualKeyIDs, including each reachable switch branch (all VKs only, subset
only, and combined OR case) and any related state/code-mode interactions. Use
the existing query/filter entry points in rdb.go and the VK access logic symbols
to keep the tests aligned with the implementation.

In `@framework/configstore/store.go`:
- Line 71: Update the `ConnectionTypes` field comment in `store.go` so it lists
all valid `connection_type` values, including `inprocess`, instead of only
`(http | sse | stdio)`. Keep the comment aligned with the schema used by
`configstore` and `mcp.client_configs[].connection_type`, and make sure any
filter wiring references the exact allowed set: `stdio`, `http`, `sse`, and
`inprocess`.

In `@transports/bifrost-http/handlers/mcp.go`:
- Around line 115-179: The filter parsing in getMCPClientsPaginated is too
lenient compared with the existing limit/offset handling. Update
parseBoolQueryArg so malformed booleans for code_mode/disabled return a 400
instead of silently becoming “no filter”, and validate connection_type,
auth_type, and state against their allowed enum values before building
MCPClientsQueryParams. Use the known enum sets in mcp.client_configs and keep
the query-to-filter mapping in handler logic so typos surface as explicit
bad-request errors rather than empty result sets.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: ceba6700-6bf9-4a45-b0af-de19b6a2385a

📥 Commits

Reviewing files that changed from the base of the PR and between 8493d18 and 1745ae6.

📒 Files selected for processing (3)
  • framework/configstore/rdb.go
  • framework/configstore/store.go
  • transports/bifrost-http/handlers/mcp.go

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 2, 2026
@impoiler
impoiler force-pushed the 07-02-feat_mcp_clients_filters_support_backend branch from 1745ae6 to 52f2fa1 Compare July 2, 2026 07:56
@coderabbitai
coderabbitai Bot requested a review from Pratham-Mishra04 July 2, 2026 07:57
@impoiler
impoiler force-pushed the 07-02-feat_mcp_clients_filters_support_backend branch from 52f2fa1 to 7cdb87a Compare July 2, 2026 09:38
@coderabbitai
coderabbitai Bot requested a review from akshaydeo July 2, 2026 09:40
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 2, 2026
Comment thread transports/bifrost-http/handlers/mcp.go
@impoiler
impoiler force-pushed the 07-02-feat_mcp_clients_filters_support_backend branch from 7cdb87a to af49b62 Compare July 2, 2026 10:01

Pratham-Mishra04 commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator

Merge activity

  • Jul 2, 10:09 AM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Jul 2, 10:09 AM UTC: @Pratham-Mishra04 merged this pull request with Graphite.

@Pratham-Mishra04
Pratham-Mishra04 merged commit 5214991 into dev Jul 2, 2026
15 checks passed
@Pratham-Mishra04
Pratham-Mishra04 deleted the 07-02-feat_mcp_clients_filters_support_backend branch July 2, 2026 10:09
yangtuooc added a commit to yangtuooc/bifrost that referenced this pull request Jul 2, 2026
* upstream/dev:
  feat: add pagination and filtering to MCP clients list endpoint (maximhq#4841)
  feat: add filter sidebar with faceted filtering to MCP clients page (maximhq#4840)
  feat: add connection_type, auth_type, state, and virtual_key filters to MCP clients list (maximhq#4839)

# Conflicts:
#	ui/app/workspace/mcp-registry/page.tsx
#	ui/app/workspace/mcp-registry/views/mcpClientsTable.tsx
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants