feat: add tool-level filtering for MCP requests#133
Conversation
|
Caution Review failedThe pull request is closed. Summary by CodeRabbit
Summary by CodeRabbit
WalkthroughThis change introduces per-request filtering for MCP tools in addition to existing client filtering. It adds new context keys and HTTP headers to allow inclusion or exclusion of specific tools, updates the filtering logic in the MCP manager, and revises documentation to reflect these enhancements and the new configuration options. Changes
Sequence Diagram(s)sequenceDiagram
participant HTTP Client
participant Bifrost HTTP Transport
participant MCPManager
HTTP Client->>Bifrost HTTP Transport: Send request with X-BF-MCP-* headers
Bifrost HTTP Transport->>Bifrost HTTP Transport: Extract MCP headers, store in context
Bifrost HTTP Transport->>MCPManager: getAvailableTools(ctx)
MCPManager->>MCPManager: Filter clients (include/exclude)
MCPManager->>MCPManager: For each client, filter tools (include/exclude)
MCPManager-->>Bifrost HTTP Transport: Return filtered tools
Bifrost HTTP Transport-->>HTTP Client: Respond with results
Possibly related PRs
Suggested reviewers
Poem
📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (3)
✨ Finishing Touches
🧪 Generate Unit Tests
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (3)
core/mcp.go(3 hunks)docs/mcp.md(6 hunks)transports/bifrost-http/lib/ctx.go(3 hunks)
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/anthropic.go:358-388
Timestamp: 2025-06-04T05:37:59.699Z
Learning: User Pratham-Mishra04 prefers not to extract small code duplications (around 2 lines) into helper functions, considering the overhead not worth it for such minor repetition.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#102
File: README.md:62-66
Timestamp: 2025-06-19T17:03:03.639Z
Learning: Pratham-Mishra04 prefers using the implicit 'latest' tag for the maximhq/bifrost Docker image rather than pinning to specific versions.
transports/bifrost-http/lib/ctx.go (7)
Learnt from: connyay
PR: maximhq/bifrost#92
File: core/providers/utils.go:60-64
Timestamp: 2025-06-17T14:04:21.104Z
Learning: The bifrost codebase uses string alias types (like `type ContextKey string`) for context keys consistently across multiple packages including plugins/maxim/main.go and transports/bifrost-http/tracking/plugin.go. This pattern should be maintained for consistency rather than switching to the canonical struct{} approach.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#63
File: transports/bifrost-http/integrations/openai/router.go:62-64
Timestamp: 2025-06-09T11:27:00.925Z
Learning: The `lib.ConvertToBifrostContext` function in the bifrost HTTP transport never returns nil and handles the conversion internally, so nil checks are not needed when calling this function.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#63
File: transports/bifrost-http/integrations/openai/router.go:62-64
Timestamp: 2025-06-09T11:27:00.925Z
Learning: The `lib.ConvertToBifrostContext` function in the bifrost HTTP transport never returns nil and always returns a pointer to a valid context. It starts with context.Background() and only adds values to it, so nil checks are not needed when calling this function.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#131
File: transports/bifrost-http/lib/config.go:35-68
Timestamp: 2025-06-26T07:37:24.385Z
Learning: In the Bifrost project's MCP configuration handling, empty environment variables should be treated as missing/invalid rather than as valid empty values. The current implementation using `os.Getenv(envKey); envValue != ""` to check for non-empty values is the desired behavior.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#100
File: core/mcp.go:489-490
Timestamp: 2025-06-19T12:38:07.544Z
Learning: In the Bifrost MCP manager (core/mcp.go), the connectToMCPClient method is called during initialization/connection setup, not frequently during runtime. Logging operations like m.logger.Info inside critical sections in this context have negligible performance impact and don't require optimization for lock contention.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#65
File: transports/bifrost-http/integrations/anthropic/types.go:140-146
Timestamp: 2025-06-10T13:51:52.859Z
Learning: In Bifrost core v1.0.9, ImageContent.Type was a pointer type (*string accessed via bifrost.Ptr), but in v1.0.10 it was changed to a value type (ImageContentType). When reviewing code, check the core version being used to determine the correct assignment pattern.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#94
File: core/schemas/bifrost.go:20-23
Timestamp: 2025-06-18T15:16:23.127Z
Learning: In the Bifrost project, BifrostConfig struct is never marshaled/unmarshaled, so serialization tags (json, yaml) are not needed for its fields.
docs/mcp.md (14)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#100
File: core/mcp.go:489-490
Timestamp: 2025-06-19T12:38:07.544Z
Learning: In the Bifrost MCP manager (core/mcp.go), the connectToMCPClient method is called during initialization/connection setup, not frequently during runtime. Logging operations like m.logger.Info inside critical sections in this context have negligible performance impact and don't require optimization for lock contention.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#131
File: transports/bifrost-http/lib/config.go:35-68
Timestamp: 2025-06-26T07:37:24.385Z
Learning: In the Bifrost project's MCP configuration handling, empty environment variables should be treated as missing/invalid rather than as valid empty values. The current implementation using `os.Getenv(envKey); envValue != ""` to check for non-empty values is the desired behavior.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#54
File: core/schemas/provider.go:148-148
Timestamp: 2025-06-04T03:57:50.981Z
Learning: Breaking changes in the Bifrost codebase are managed by first merging and tagging core schema changes, then updating dependent code references in subsequent steps after the core version is released.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#103
File: .github/workflows/transport-dependency-update.yml:53-75
Timestamp: 2025-06-20T16:21:18.912Z
Learning: In the bifrost repository's transport dependency update workflow, when updating the core dependency to a new version using `go get`, the go.mod and go.sum files will always change in normal operation, making the safety check for changes more of a defensive programming practice rather than handling a common scenario.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#94
File: core/mcp.go:696-711
Timestamp: 2025-06-18T20:16:37.560Z
Learning: For the Bifrost MCP implementation, performance optimizations like caching tool discovery results should be deferred until after core functionality is complete. The author prefers to implement core features first and handle optimizations as follow-up work.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#83
File: core/schemas/bifrost.go:186-190
Timestamp: 2025-06-15T14:18:32.703Z
Learning: In core/schemas/bifrost.go, the ToolChoice UnmarshalJSON validation intentionally only checks for empty Type fields and lets providers handle validation of specific tool choice values. This architectural decision keeps schema validation focused on structure while allowing provider-specific semantic validation.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/anthropic.go:483-494
Timestamp: 2025-06-04T10:04:30.181Z
Learning: In the Anthropic provider (core/providers/anthropic.go), parallel tool calls support including the DisableParallelToolUse flag will be implemented in later commits as it's a relatively new feature that's not commonly used yet. The development approach prioritizes core functionality first.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/anthropic.go:483-494
Timestamp: 2025-06-04T09:36:27.956Z
Learning: In the Anthropic provider (core/providers/anthropic.go), the user has confirmed through practical experience that the tool_choice parameter should always use an object format with a "type" field (e.g., {"type": "auto"}, {"type": "tool", "name": "function_name"}), even though the official documentation examples sometimes show "auto" as a direct string. The current implementation correctly handles all tool choice types with the object format.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#65
File: transports/bifrost-http/integrations/utils.go:169-173
Timestamp: 2025-06-09T17:33:52.234Z
Learning: The ChatCompletionRequest method in the Bifrost client follows a contract where the result parameter will never be nil if the error parameter is nil. This means when error checking passes (err == nil), the result is guaranteed to be valid and can be safely used without additional nil checks.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#54
File: core/schemas/bifrost.go:46-49
Timestamp: 2025-06-04T09:22:18.123Z
Learning: In core/schemas/bifrost.go, the RequestInput struct uses ChatCompletionInput *[]BifrostMessage (pointer-to-slice) rather than []BifrostMessage to properly represent union type semantics. For text completion requests, ChatCompletionInput should be nil to indicate "no chat payload at all", while for chat completion requests it should be non-nil (even if empty slice). This distinguishes between different request types rather than just empty vs non-empty chat messages.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#81
File: tests/core-providers/scenarios/end_to_end_tool_calling.go:43-45
Timestamp: 2025-06-16T04:13:55.437Z
Learning: In the Bifrost codebase, errors returned from client methods like ChatCompletionRequest are of type BifrostError, not the standard error interface. For testing these errors, use require.Nilf instead of require.NoErrorf since BifrostError doesn't work with the standard error assertion methods.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#81
File: tests/core-providers/scenarios/simple_chat.go:39-41
Timestamp: 2025-06-16T04:13:42.755Z
Learning: In the Bifrost codebase, errors returned from methods like ChatCompletionRequest are of type BifrostError (a custom error type) rather than the standard Go error interface. Therefore, require.Nilf should be used for error assertions instead of require.NoErrorf.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#63
File: transports/bifrost-http/integrations/openai/router.go:62-64
Timestamp: 2025-06-09T11:27:00.925Z
Learning: The `lib.ConvertToBifrostContext` function in the bifrost HTTP transport never returns nil and handles the conversion internally, so nil checks are not needed when calling this function.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#65
File: transports/bifrost-http/integrations/anthropic/router.go:19-33
Timestamp: 2025-06-09T16:46:32.018Z
Learning: In the GenericRouter (transports/bifrost-http/integrations), ResponseFunc is not called if the BifrostResponse parameter is nil, providing built-in protection against nil response marshaling.
core/mcp.go (7)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#100
File: core/mcp.go:489-490
Timestamp: 2025-06-19T12:38:07.544Z
Learning: In the Bifrost MCP manager (core/mcp.go), the connectToMCPClient method is called during initialization/connection setup, not frequently during runtime. Logging operations like m.logger.Info inside critical sections in this context have negligible performance impact and don't require optimization for lock contention.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#131
File: transports/bifrost-http/lib/config.go:35-68
Timestamp: 2025-06-26T07:37:24.385Z
Learning: In the Bifrost project's MCP configuration handling, empty environment variables should be treated as missing/invalid rather than as valid empty values. The current implementation using `os.Getenv(envKey); envValue != ""` to check for non-empty values is the desired behavior.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#83
File: core/providers/cohere.go:327-335
Timestamp: 2025-06-15T13:46:24.869Z
Learning: For Cohere v1 API in core/providers/cohere.go, the tool_choice parameter formatting uses uppercase strings for the "type" field (e.g., "AUTO", "TOOL") and follows a different structure than initially assumed. The current implementation with strings.ToUpper() for the type field is correct for the v1 API.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#83
File: core/providers/cohere.go:327-335
Timestamp: 2025-06-15T13:46:24.869Z
Learning: Cohere v1 API tool_choice parameter accepts only uppercase string values: "REQUIRED" and "NONE". Unlike other providers, it doesn't use structured objects with "type" and "name" fields. The current implementation in core/providers/cohere.go correctly uses strings.ToUpper() to convert ToolChoiceStruct.Type to uppercase format as expected by the API.
Learnt from: connyay
PR: maximhq/bifrost#92
File: core/providers/utils.go:60-64
Timestamp: 2025-06-17T14:04:21.104Z
Learning: The bifrost codebase uses string alias types (like `type ContextKey string`) for context keys consistently across multiple packages including plugins/maxim/main.go and transports/bifrost-http/tracking/plugin.go. This pattern should be maintained for consistency rather than switching to the canonical struct{} approach.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/anthropic.go:483-494
Timestamp: 2025-06-04T10:04:30.181Z
Learning: In the Anthropic provider (core/providers/anthropic.go), parallel tool calls support including the DisableParallelToolUse flag will be implemented in later commits as it's a relatively new feature that's not commonly used yet. The development approach prioritizes core functionality first.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#83
File: core/schemas/bifrost.go:186-190
Timestamp: 2025-06-15T14:18:32.703Z
Learning: In core/schemas/bifrost.go, the ToolChoice UnmarshalJSON validation intentionally only checks for empty Type fields and lets providers handle validation of specific tool choice values. This architectural decision keeps schema validation focused on structure while allowing provider-specific semantic validation.
🧬 Code Graph Analysis (1)
transports/bifrost-http/lib/ctx.go (1)
plugins/maxim/main.go (1)
ContextKey(54-54)
🪛 LanguageTool
docs/mcp.md
[uncategorized] ~1062-~1062: Loose punctuation mark.
Context: ... Filtering:** - "mcp-include-clients": Whitelist specific clients for a reques...
(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~1067-~1067: Loose punctuation mark.
Context: ...ol Filtering:** - "mcp-include-tools": Whitelist specific tools for a request ...
(UNLIKELY_OPENING_PUNCTUATION)
[duplication] ~1146-~1146: Possible typo: you repeated a word.
Context: ...ry**: Only applies when include list is empty 3. Empty filters: All configured clients are a...
(ENGLISH_WORD_REPEAT_RULE)
[duplication] ~1152-~1152: Possible typo: you repeated a word.
Context: ...ry**: Only applies when include list is empty 3. Empty filters: All discovered tools (from a...
(ENGLISH_WORD_REPEAT_RULE)
[grammar] ~1216-~1216: Possible subject-verb agreement error detected: Did you mean to use the plural form here?
Context: ...** (mcp-exclude-clients) - Applied if no include list 3. Default: All config...
(SUBJECT_NUMBER)
[grammar] ~1222-~1222: Possible subject-verb agreement error detected: Did you mean to use the plural form here?
Context: ...de** (mcp-exclude-tools) - Applied if no include list 3. **Config-level tool whi...
(SUBJECT_NUMBER)
🔇 Additional comments (9)
transports/bifrost-http/lib/ctx.go (3)
50-50: LGTM: ContextKey type follows established pattern.The string alias type for context keys is consistent with the codebase pattern used across multiple packages, as noted in the retrieved learnings.
32-37: Well-documented MCP header integration.The documentation clearly explains the new MCP header functionality and follows the established format used for Prometheus and Maxim headers.
80-87: MCP header parsing implementation is correct.The implementation follows the established pattern for header processing and properly:
- Validates specific MCP header types
- Strips the prefix consistently
- Stores values using the ContextKey type
- Uses early return for efficiency
The logic correctly handles the four expected MCP headers for client and tool filtering.
core/mcp.go (2)
34-37: Context key format updated correctly.The rename from underscore to hyphen format (e.g.,
mcp_include_clients→mcp-include-clients) is consistent with the HTTP transport implementation and the new tool filtering keys follow the same pattern.
156-160: Clean integration of tool filtering.The tool filtering is properly integrated into the existing client filtering flow, applying tool-level filtering after client-level filtering as documented.
docs/mcp.md (4)
323-358: Comprehensive HTTP headers documentation for tool filtering.The documentation clearly explains the new tool filtering headers and provides practical examples showing how to combine client and tool filtering for granular control.
571-614: Well-structured examples demonstrating tool filtering capabilities.The context usage examples effectively show both individual and combined filtering approaches, making it clear how to use the new tool-level filtering alongside existing client filtering.
1058-1069: Context keys documentation updated correctly.The documentation accurately reflects the new hyphen-formatted context keys and clearly separates client filtering from tool filtering keys.
1112-1232: Excellent explanation of filtering priority and execution order.The documentation clearly explains:
- Priority rules for both client and tool filtering
- The execution order (client filtering first, then tool filtering)
- How the two types of filtering work together
This provides users with a clear understanding of how to achieve granular control over tool availability.
24fb518 to
a66e8da
Compare
# Add Tool-Level Filtering for MCP Clients
This PR adds the ability to filter specific tools across all active MCP clients, complementing the existing client-level filtering. This provides more granular control over which tools are available in a request.
## Changes:
- Added new context keys for tool filtering:
- `mcp-include-tools`: Whitelist specific tools
- `mcp-exclude-tools`: Blacklist specific tools
- Implemented `shouldSkipToolForRequest()` method to filter tools based on request context
- Updated HTTP transport to support new tool filtering headers:
- `X-BF-MCP-Include-Tools`
- `X-BF-MCP-Exclude-Tools`
- Renamed existing context keys for consistency:
- `mcp_include_clients` → `mcp-include-clients`
- `mcp_exclude_clients` → `mcp-exclude-clients`
- Updated documentation with examples of tool filtering and combined client/tool filtering approaches
## Usage:
```go
// Tool-level filtering
ctx = context.WithValue(ctx, "mcp-include-tools", []string{"read_file", "get_weather"})
ctx = context.WithValue(ctx, "mcp-exclude-tools", []string{"delete", "rm", "format"})
// HTTP headers
curl -H "X-BF-MCP-Include-Tools: read_file,list_files,get_weather" ...
```
This enhancement allows for more precise control over tool availability, improving security and reducing unnecessary tool exposure.

Add Tool-Level Filtering for MCP Clients
This PR adds the ability to filter specific tools across all active MCP clients, complementing the existing client-level filtering. This provides more granular control over which tools are available in a request.
Changes:
Added new context keys for tool filtering:
mcp-include-tools: Whitelist specific toolsmcp-exclude-tools: Blacklist specific toolsImplemented
shouldSkipToolForRequest()method to filter tools based on request contextUpdated HTTP transport to support new tool filtering headers:
X-BF-MCP-Include-ToolsX-BF-MCP-Exclude-ToolsRenamed existing context keys for consistency:
mcp_include_clients→mcp-include-clientsmcp_exclude_clients→mcp-exclude-clientsUpdated documentation with examples of tool filtering and combined client/tool filtering approaches
Usage:
This enhancement allows for more precise control over tool availability, improving security and reducing unnecessary tool exposure.