Skip to content

Conversation

@Pratham-Mishra04
Copy link
Collaborator

Summary

Added a configurable code mode binding level for MCP tools, allowing tools to be exposed in the virtual file system (VFS) at either server-level or tool-level granularity.

Changes

  • Added a new CodeModeBindingLevel configuration option with two possible values:
    • server: All tools for a server are exposed in a single file (e.g., servers/calculator.d.ts)
    • tool: Each tool is exposed in its own file (e.g., servers/calculator/add.d.ts)
  • Enhanced the listToolFiles and readToolFile tools to support both binding levels
  • Implemented a tree-based VFS structure for better organization of tool files
  • Added UI configuration in the MCP Gateway settings page with visual examples
  • Updated database schema and migrations to store the new configuration

Type of change

  • Feature
  • UI (Next.js)

Affected areas

  • Core (Go)
  • Transports (HTTP)
  • UI (Next.js)

How to test

  1. Configure the code mode binding level in the UI:

    • Navigate to Workspace → Config → MCP Gateway
    • Select either "Server-Level" or "Tool-Level" binding
    • Save changes
  2. Test with code mode in a chat:

    // First list available tools
    await listToolFiles()
    
    // Read tool definitions based on binding level
    // For server-level:
    await readToolFile({ fileName: "servers/calculator.d.ts" })
    
    // For tool-level:
    await readToolFile({ fileName: "servers/calculator/add.d.ts" })
    
    // Execute tool code as usual
    await executeToolCode(`
      const result = await calculator.add({ a: 5, b: 3 });
      return result;
    `)

Screenshots/Recordings

N/A

Breaking changes

  • No

Related issues

N/A

Security considerations

No additional security implications. This change only affects how tools are organized and presented in the virtual file system.

Checklist

  • I added/updated tests where appropriate
  • I updated documentation where needed
  • I verified builds succeed (Go and UI)

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 23, 2025

📝 Walkthrough

Summary by CodeRabbit

Release Notes

  • New Features

    • Added Code Mode Binding Level configuration for MCP tools with "server" and "tool" options to control how tools are organized in the virtual file system
    • Added new MCP Gateway configuration page accessible from the sidebar with visual examples showing VFS structure variations
  • UI/UX

    • Added Code Mode Binding Level selector control with live demonstration of server-level vs tool-level organization

✏️ Tip: You can customize this high-level summary in your review settings.

Walkthrough

This PR introduces Code Mode Binding Level to control how MCP tools are exposed in virtual file systems. The feature propagates through schemas, configuration storage, the tool manager, VFS file handling logic, HTTP API endpoints, and UI components, allowing tools to be organized at either server-level or tool-level granularity.

Changes

Cohort / File(s) Summary
Schema Definitions
core/schemas/mcp.go, ui/lib/types/config.ts, ui/lib/types/schemas.ts
Added CodeModeBindingLevel type with constants "server" and "tool", new field in MCPToolManagerConfig, and Zod enum schema for validation.
Configuration Storage Layer
framework/configstore/clientconfig.go, framework/configstore/tables/clientconfig.go, framework/configstore/migrations.go, framework/configstore/rdb.go
Added MCPCodeModeBindingLevel field to ClientConfig table with default "server", new migration to create column, and propagation to MCPToolManagerConfig in retrieval.
Tool Manager
core/mcp/toolmanager.go
Added atomic field to store binding level, getter, initialization, and update handling with logging.
VFS List Tool
core/mcp/codemode_listfiles.go
Implemented dynamic descriptions based on binding level, VFS tree building logic with buildVFSTree and renderTreeNode helpers, and server/tool-level file list generation.
VFS Read Tool
core/mcp/codemode_readfile.go
Added parseVFSFilePath to extract server/tool names, binding-level-aware file handling with ambiguity resolution, conditional type definition generation via updated generateTypeDefinitions, and detailed error messages.
Bifrost Core
core/bifrost.go
Added codeModeBindingLevel parameter to UpdateToolManagerConfig method and propagation to MCP manager config.
HTTP API Layer
transports/bifrost-http/handlers/config.go, transports/bifrost-http/server/server.go, transports/bifrost-http/lib/config.go
Updated method signatures for UpdateMCPToolManagerConfig, added validation for binding level values ("server" or "tool"), config propagation, and reload triggering.
UI Configuration Views
ui/app/workspace/config/views/{clientSettingsView, governanceView, loggingView, observabilityView, performanceTuningView, securityView}.tsx
Added mcp_code_mode_binding_level: "server" default to CoreConfig in each view's defaultConfig.
MCP Gateway UI
ui/app/workspace/config/views/mcpView.tsx
Added UI controls (Select widget) for Code Mode Binding Level with "server"/"tool" options, state tracking in localValues, change detection, and live visual example demonstrating VFS structure differences.
UI Routing & Navigation
ui/app/workspace/config/mcp-gateway/page.tsx, ui/components/sidebar.tsx
New MCP Gateway page component and sidebar menu item with MCPIcon and access control.
Changelog Updates
core/changelog.md, framework/changelog.md, transports/changelog.md
Updated entries to reflect new code mode and health monitoring features for MCP.

Sequence Diagram

sequenceDiagram
    actor User
    participant UI as MCP Gateway UI
    participant HTTP as HTTP Handler
    participant Bifrost as Bifrost Core
    participant ToolMgr as Tool Manager
    participant VFS as VFS Tools

    User->>UI: Select binding level (server/tool)
    UI->>HTTP: POST /config with mcp_code_mode_binding_level
    HTTP->>HTTP: Validate binding level ∈ {server, tool}
    HTTP->>Bifrost: UpdateToolManagerConfig(..., codeModeBindingLevel)
    Bifrost->>ToolMgr: UpdateConfig with CodeModeBindingLevel
    ToolMgr->>ToolMgr: Store atomically, log update
    ToolMgr->>VFS: GetCodeModeBindingLevel() on next tool invocation
    Note over VFS: VFS tools now organize files<br/>based on binding level:<br/>- server: /servers/X.d.ts<br/>- tool: /servers/X/tools/Y.d.ts
    UI->>User: Config updated, VFS layout changed
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A warren of tools, now neatly arranged,
Server-by-server or tool-by-tool changed,
VFS trees bloom where once flat lists lay,
Binding levels dance in our protocol's way,
The burrow grows organized, bright and profound!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 42.11% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The pull request title 'feat: add tool-level binding option for MCP code mode' clearly summarizes the main feature addition and aligns with the primary changes throughout the changeset.
Description check ✅ Passed The pull request description covers all required template sections including Summary, Changes, Type of change, Affected areas, How to test, Breaking changes, and Checklist; all critical sections are complete and well-documented.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 12-23-feat_added_binding_level_toggle_in_mcp_codemode

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

Copy link
Collaborator Author

Pratham-Mishra04 commented Dec 23, 2025

This stack of pull requests is managed by Graphite. Learn more about stacking.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (9)
ui/lib/types/config.ts (1)

328-328: Tighten CoreConfig type to a literal union instead of plain string

Backend and UI both treat this as "server" or "tool" only; using string misses easy type safety and autocomplete.

Consider introducing a dedicated union type and using it here:

Proposed type-level refinement
+export type MCPCodeModeBindingLevel = "server" | "tool";
+
 // Core Bifrost configuration types
 export interface CoreConfig {
@@
-	mcp_tool_execution_timeout: number;
-	mcp_code_mode_binding_level?: string;
+	mcp_tool_execution_timeout: number;
+	mcp_code_mode_binding_level?: MCPCodeModeBindingLevel;
 }
transports/bifrost-http/lib/config.go (1)

217-232: Consider normalizing empty MCPCodeModeBindingLevel to the “server” default

The default client config sets MCPCodeModeBindingLevel to "server", and the merge-from-file path copies a non-empty value from the file when the DB field is empty. There’s still a narrow case where both DB and file have this field empty, leaving the in-memory value as "" instead of the intended default.

For extra robustness (and to decouple behavior from migration guarantees), you could normalize after merging:

Suggested normalization after merge
 func loadClientConfigFromFile(ctx context.Context, config *Config, configData *ConfigData) {
@@
 			if config.ClientConfig.MCPToolExecutionTimeout == 0 && configData.Client.MCPToolExecutionTimeout != 0 {
 				config.ClientConfig.MCPToolExecutionTimeout = configData.Client.MCPToolExecutionTimeout
 			}
-			if config.ClientConfig.MCPCodeModeBindingLevel == "" && configData.Client.MCPCodeModeBindingLevel != "" {
-				config.ClientConfig.MCPCodeModeBindingLevel = configData.Client.MCPCodeModeBindingLevel
-			}
+			if config.ClientConfig.MCPCodeModeBindingLevel == "" && configData.Client.MCPCodeModeBindingLevel != "" {
+				config.ClientConfig.MCPCodeModeBindingLevel = configData.Client.MCPCodeModeBindingLevel
+			}
+			// Ensure a sane default if still empty after merging
+			if config.ClientConfig.MCPCodeModeBindingLevel == "" {
+				config.ClientConfig.MCPCodeModeBindingLevel = string(schemas.CodeModeBindingLevelServer)
+			}

(You could also centralize this invariant anywhere you finalize ClientConfig.)

Also applies to: 508-510

ui/components/sidebar.tsx (1)

372-377: Clarify UX for the two “MCP Gateway” entries and consider de‑duplicating the icon

You now have:

  • A top-level item: title: "MCP Gateway", url: "/workspace/mcp-gateway".
  • A Config sub-item: title: "MCP Gateway", url: "/workspace/config/mcp-gateway".

Both use hasMCPGatewayAccess and similar descriptions (“MCP configuration/gateway configuration”). If these represent different surfaces (e.g., runtime status vs. config), consider differentiating titles/descriptions, or dropping one if they’re effectively the same destination; otherwise it may be confusing in the sidebar.

Separately, this file defines a local MCPIcon SVG while ui/components/ui/icons.tsx also exports MCPIcon with the same path data. Importing and reusing the shared icon instead of duplicating it here would reduce maintenance overhead.

Also applies to: 489-495

framework/configstore/rdb.go (1)

30-55: MCPCodeModeBindingLevel wiring looks correct; optional explicit default in fallback branch

Persisting MCPCodeModeBindingLevel through UpdateClientConfig, GetClientConfig, and into MCPToolManagerConfig.CodeModeBindingLevel in GetMCPConfig is consistent and keeps the new knob fully round-tripped.

In the rare ErrRecordNotFound branch in GetMCPConfig, you currently omit CodeModeBindingLevel from the default MCPToolManagerConfig. This is functionally fine because NewToolsManager already normalizes an empty value to CodeModeBindingLevelServer, but if you want the config object itself to be self-describing, you could also set the field there for clarity.

Also applies to: 180-205, 706-773

core/bifrost.go (1)

1887-1900: Good propagation of binding level; consider typing parameter as schemas.CodeModeBindingLevel

The new codeModeBindingLevel parameter is correctly threaded into MCPToolManagerConfig and will be applied atomically via the MCP manager.

Since this is a public method that may be called by Go consumers directly (bypassing HTTP validation), consider changing the third argument’s type to schemas.CodeModeBindingLevel to enforce the "server" / "tool" enum at compile time and avoid accidental invalid strings.

core/mcp/codemode_listfiles.go (2)

13-39: Dynamic description is correct but heavily duplicated across branches

Conditioning the tool description on CodeModeBindingLevel is nice and keeps the behavior self‑documenting. The two branches share a lot of identical copy, though, which will be tedious to keep in sync.

Consider factoring the shared paragraphs into a common base string and only varying the sentences that differ between server‑ and tool‑level modes.


77-118: File listing and VFS tree construction look correct; minor UX and style tweaks possible

The binding‑level split in handleListToolFiles and the buildVFSTree / renderTreeNode helpers produce the expected hierarchies for both:

  • servers/<server>.d.ts (server level),
  • servers/<server>/<tool>.d.ts (tool level),

with stable lexicographic ordering and sensible indentation.

Two small improvements you might consider:

  1. Empty files edge case
    If codeModeServerCount > 0 but, for whatever reason, no tool files are derived (e.g., a misconfigured client exposing zero tools), buildVFSTree returns "", and the user gets an empty response body. Checking len(files) == 0 in handleListToolFiles and returning a short explanatory message would make this failure mode clearer.

  2. Use sort.Strings instead of manual bubble sort
    In renderTreeNode, replacing the custom nested loops with sort.Strings(keys) (and importing sort) would be more idiomatic and simpler to read.

Also applies to: 144-229

core/mcp/toolmanager.go (1)

467-484: Config updates and accessor for CodeModeBindingLevel behave correctly; logging is slightly optimistic

UpdateConfig correctly treats non‑zero timeout/depth and non‑empty CodeModeBindingLevel as updates, and GetCodeModeBindingLevel safely falls back to CodeModeBindingLevelServer when the atomic value hasn’t been initialized.

One minor nuance: the log line in UpdateConfig prints the fields from the passed config struct, which may deliberately omit some values (e.g., 0 timeout used to mean “no change”), so the message can under‑report the actual effective configuration. If you care about absolute accuracy here, consider logging the values read back from the atomics instead.

Functionally, though, the update and read paths are correct.

Also applies to: 486-494

transports/bifrost-http/server/server.go (1)

735-740: Consider adding validation for the codeModeBindingLevel parameter.

The codeModeBindingLevel parameter is accepted as a plain string without validation. According to the PR description, valid values are "server" and "tool". Consider adding validation to reject invalid values early, or use a typed constant from core/schemas to ensure type safety.

🔎 Suggested validation approach
 func (s *BifrostHTTPServer) UpdateMCPToolManagerConfig(ctx context.Context, maxAgentDepth int, toolExecutionTimeoutInSeconds int, codeModeBindingLevel string) error {
 	if s.Config == nil {
 		return fmt.Errorf("config not found")
 	}
+	// Validate binding level
+	if codeModeBindingLevel != string(schemas.CodeModeBindingLevelServer) && codeModeBindingLevel != string(schemas.CodeModeBindingLevelTool) {
+		return fmt.Errorf("invalid codeModeBindingLevel: %s (must be 'server' or 'tool')", codeModeBindingLevel)
+	}
 	return s.Client.UpdateToolManagerConfig(maxAgentDepth, toolExecutionTimeoutInSeconds, codeModeBindingLevel)
 }
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bd2355b and 8a83112.

📒 Files selected for processing (27)
  • core/bifrost.go
  • core/mcp.go
  • core/mcp/codemode_listfiles.go
  • core/mcp/codemode_readfile.go
  • core/mcp/toolmanager.go
  • core/schemas/mcp.go
  • framework/configstore/clientconfig.go
  • framework/configstore/migrations.go
  • framework/configstore/rdb.go
  • framework/configstore/tables/clientconfig.go
  • framework/configstore/tables/mcp.go
  • transports/bifrost-http/handlers/config.go
  • transports/bifrost-http/lib/config.go
  • transports/bifrost-http/server/server.go
  • transports/go.mod
  • ui/app/workspace/config/logging/page.tsx
  • ui/app/workspace/config/mcp-gateway/page.tsx
  • ui/app/workspace/config/views/clientSettingsView.tsx
  • ui/app/workspace/config/views/governanceView.tsx
  • ui/app/workspace/config/views/loggingView.tsx
  • ui/app/workspace/config/views/mcpView.tsx
  • ui/app/workspace/config/views/observabilityView.tsx
  • ui/app/workspace/config/views/performanceTuningView.tsx
  • ui/app/workspace/config/views/securityView.tsx
  • ui/components/sidebar.tsx
  • ui/lib/types/config.ts
  • ui/lib/types/schemas.ts
💤 Files with no reviewable changes (1)
  • framework/configstore/tables/mcp.go
🧰 Additional context used
📓 Path-based instructions (1)
**

⚙️ CodeRabbit configuration file

always check the stack if there is one for the current PR. do not give localized reviews for the PR, always see all changes in the light of the whole stack of PRs (if there is a stack, if there is no stack you can continue to make localized suggestions/reviews)

Files:

  • ui/lib/types/config.ts
  • ui/app/workspace/config/views/loggingView.tsx
  • ui/lib/types/schemas.ts
  • framework/configstore/clientconfig.go
  • core/bifrost.go
  • ui/app/workspace/config/views/securityView.tsx
  • core/schemas/mcp.go
  • core/mcp/codemode_listfiles.go
  • ui/app/workspace/config/views/observabilityView.tsx
  • core/mcp.go
  • framework/configstore/tables/clientconfig.go
  • transports/bifrost-http/server/server.go
  • core/mcp/codemode_readfile.go
  • framework/configstore/migrations.go
  • ui/app/workspace/config/mcp-gateway/page.tsx
  • transports/bifrost-http/handlers/config.go
  • ui/app/workspace/config/views/performanceTuningView.tsx
  • ui/app/workspace/config/views/mcpView.tsx
  • ui/components/sidebar.tsx
  • ui/app/workspace/config/logging/page.tsx
  • transports/bifrost-http/lib/config.go
  • transports/go.mod
  • ui/app/workspace/config/views/governanceView.tsx
  • framework/configstore/rdb.go
  • ui/app/workspace/config/views/clientSettingsView.tsx
  • core/mcp/toolmanager.go
🧠 Learnings (2)
📚 Learning: 2025-12-09T17:07:42.007Z
Learnt from: qwerty-dvorak
Repo: maximhq/bifrost PR: 1006
File: core/schemas/account.go:9-18
Timestamp: 2025-12-09T17:07:42.007Z
Learning: In core/schemas/account.go, the HuggingFaceKeyConfig field within the Key struct is currently unused and reserved for future Hugging Face inference endpoint deployments. Do not flag this field as missing from OpenAPI documentation or require its presence in the API spec until the feature is actively implemented and used. When the feature is added, update the OpenAPI docs accordingly; otherwise, treat this field as non-breaking and not part of the current API surface.

Applied to files:

  • framework/configstore/clientconfig.go
  • core/bifrost.go
  • core/schemas/mcp.go
  • core/mcp/codemode_listfiles.go
  • core/mcp.go
  • framework/configstore/tables/clientconfig.go
  • transports/bifrost-http/server/server.go
  • core/mcp/codemode_readfile.go
  • framework/configstore/migrations.go
  • transports/bifrost-http/handlers/config.go
  • transports/bifrost-http/lib/config.go
  • framework/configstore/rdb.go
  • core/mcp/toolmanager.go
📚 Learning: 2025-12-12T08:25:02.629Z
Learnt from: Pratham-Mishra04
Repo: maximhq/bifrost PR: 1000
File: transports/bifrost-http/integrations/router.go:709-712
Timestamp: 2025-12-12T08:25:02.629Z
Learning: In transports/bifrost-http/**/*.go, update streaming response handling to align with OpenAI Responses API: use typed SSE events such as response.created, response.output_text.delta, response.done, etc., and do not rely on the legacy data: [DONE] termination marker. Note that data: [DONE] is only used by the older Chat Completions and Text Completions streaming APIs. Ensure parsers, writers, and tests distinguish SSE events from the [DONE] sentinel and handle each event type accordingly for correct stream termination and progress updates.

Applied to files:

  • transports/bifrost-http/server/server.go
  • transports/bifrost-http/handlers/config.go
  • transports/bifrost-http/lib/config.go
🧬 Code graph analysis (11)
core/bifrost.go (1)
core/schemas/mcp.go (2)
  • MCPToolManagerConfig (25-29)
  • CodeModeBindingLevel (37-37)
core/mcp/codemode_listfiles.go (4)
core/mcp/toolmanager.go (2)
  • ToolsManager (22-34)
  • ToolTypeListToolFiles (37-37)
core/schemas/chatcompletions.go (2)
  • ChatTool (252-257)
  • ChatToolFunction (260-265)
core/schemas/mcp.go (1)
  • CodeModeBindingLevelServer (40-40)
core/schemas/utils.go (1)
  • Ptr (16-18)
core/mcp/codemode_readfile.go (5)
core/mcp/toolmanager.go (1)
  • ToolsManager (22-34)
core/schemas/chatcompletions.go (2)
  • ChatTool (252-257)
  • OrderedMap (277-277)
core/schemas/mcp.go (1)
  • CodeModeBindingLevelServer (40-40)
core/schemas/utils.go (1)
  • Ptr (16-18)
ui/lib/types/logs.ts (1)
  • Function (152-157)
framework/configstore/migrations.go (2)
framework/migrator/migrator.go (3)
  • New (131-149)
  • DefaultOptions (100-106)
  • Migration (62-69)
framework/configstore/tables/clientconfig.go (2)
  • TableClientConfig (11-41)
  • TableClientConfig (44-44)
transports/bifrost-http/handlers/config.go (2)
framework/configstore/clientconfig.go (1)
  • ClientConfig (37-54)
transports/bifrost-http/handlers/utils.go (1)
  • SendError (35-44)
ui/app/workspace/config/views/mcpView.tsx (2)
ui/postcss.config.mjs (1)
  • config (1-3)
ui/components/ui/select.tsx (5)
  • Select (151-151)
  • SelectTrigger (159-159)
  • SelectValue (160-160)
  • SelectContent (152-152)
  • SelectItem (154-154)
ui/components/sidebar.tsx (1)
ui/components/ui/icons.tsx (1)
  • MCPIcon (1758-1773)
ui/app/workspace/config/logging/page.tsx (1)
ui/app/workspace/config/views/loggingView.tsx (1)
  • LoggingView (31-174)
transports/bifrost-http/lib/config.go (2)
core/schemas/mcp.go (1)
  • CodeModeBindingLevelServer (40-40)
framework/configstore/clientconfig.go (1)
  • ClientConfig (37-54)
framework/configstore/rdb.go (1)
core/schemas/mcp.go (1)
  • CodeModeBindingLevel (37-37)
core/mcp/toolmanager.go (2)
core/schemas/mcp.go (2)
  • CodeModeBindingLevel (37-37)
  • CodeModeBindingLevelServer (40-40)
core/mcp.go (1)
  • MCPLogPrefix (31-31)
🔇 Additional comments (26)
transports/go.mod (1)

11-11: Ensure dependency aligns with MCP ecosystem direction.

The dependency github.com/mark3labs/mcp-go v0.41.1 is a valid, released version and appears stable. However, note that both local and remote GitHub MCP Server have been fully migrated from mark3labs/mcp-go to the official Go SDK for the Model Context Protocol. The official SDK has reached v1.0 with a formalized compatibility guarantee, while mark3labs/mcp-go remains under active development with some advanced capabilities still in progress.

Consider evaluating whether the official github.com/modelcontextprotocol/go-sdk would be more appropriate for long-term maintainability and alignment with the broader MCP ecosystem.

core/mcp.go (1)

1140-1140: Code is type-safe as written—no type assertion removal occurred.

config.InProcessServer is already statically typed as *server.MCPServer in the schema definition, not as interface{}. The client.NewInProcessClient function signature requires func NewInProcessClient(server *server.MCPServer) (*Client, error), and the code at line 1140 passes the properly typed value directly. The nil check at lines 1135–1137 provides appropriate validation. No type assertion was removed because none existed in this code path.

Likely an incorrect or invalid review comment.

core/schemas/mcp.go (1)

26-28: CodeModeBindingLevel wiring into MCPToolManagerConfig looks consistent

The enum-style type plus the new field on MCPToolManagerConfig are well-scoped and match the intended "server"/"tool" JSON surface; no issues from this file’s side.

Also applies to: 36-42

ui/app/workspace/config/views/loggingView.tsx (1)

28-28: Default MCP code-mode binding level aligns with backend defaults

Setting mcp_code_mode_binding_level to "server" in defaultConfig is consistent with the Go DefaultClientConfig and avoids undefined in local state.

ui/app/workspace/config/views/observabilityView.tsx (1)

29-29: Observability default now correctly carries MCP binding level

Including mcp_code_mode_binding_level: "server" in defaultConfig keeps this view’s local CoreConfig shape aligned with the backend and other config views.

ui/app/workspace/config/logging/page.tsx (1)

1-10: LoggingPage formatting changes are no-op functionally

The added semicolons and JSX reformatting don’t alter behavior; LoggingPage still just renders LoggingView inside the same container.

ui/app/workspace/config/views/securityView.tsx (1)

36-36: Security view CoreConfig default now includes MCP binding level

Adding mcp_code_mode_binding_level: "server" keeps this view’s default CoreConfig consistent with other config views and the Go defaults.

ui/app/workspace/config/views/clientSettingsView.tsx (1)

26-26: LGTM! Default value is consistent.

The new mcp_code_mode_binding_level field with default "server" aligns with the backend defaults and Zod schema validation.

ui/lib/types/schemas.ts (1)

465-465: LGTM! Schema validation is appropriate.

The z.enum(["server", "tool"]) validation properly constrains the binding level values, and the default of "server" is consistent with the backend implementation.

framework/configstore/clientconfig.go (2)

52-52: LGTM! Field definition is correct.

The MCPCodeModeBindingLevel field is properly defined with an appropriate JSON tag and clear documentation of allowed values.


116-120: LGTM! Hash generation is consistent.

The hash logic properly includes MCPCodeModeBindingLevel with a sensible default of "server" when empty, following the same pattern as other fields.

framework/configstore/migrations.go (2)

101-103: LGTM! Migration is properly sequenced.

The migration call is correctly placed in the sequence with appropriate error handling.


1320-1349: LGTM! Migration implementation is correct.

The migration follows the established pattern with proper:

  • Column existence check before adding
  • Rollback support
  • Error handling and formatting

The column will inherit the default value "server" from the gorm struct tags defined in TableClientConfig.

ui/app/workspace/config/mcp-gateway/page.tsx (1)

1-11: LGTM! Clean page component.

This is a straightforward Next.js app router page component that properly wraps the MCPGatewayView with appropriate layout classes.

framework/configstore/tables/clientconfig.go (1)

26-26: LGTM! Database field is properly defined.

The MCPCodeModeBindingLevel field has:

  • Correct gorm default value ("server")
  • Consistent JSON tag naming (mcp_code_mode_binding_level)
  • Clear documentation explaining its purpose
ui/app/workspace/config/views/governanceView.tsx (1)

26-26: LGTM! Default value is consistent.

The mcp_code_mode_binding_level field is correctly added to the default config with the standard "server" value. This view doesn't provide UI controls for this field, which is appropriate since it's managed in the MCP Gateway settings.

ui/app/workspace/config/views/performanceTuningView.tsx (1)

28-28: LGTM! Default value is consistent.

The mcp_code_mode_binding_level field is appropriately added with the default "server" value. This performance-focused view doesn't manage this setting, which is correct—it's handled in the MCP Gateway configuration.

framework/configstore/rdb.go (1)

650-676: Bedrock key env processing remains safe

The Bedrock env-variable processing block still defensively copies BedrockKeyConfig, conditionally rewrites fields, and then assigns the copy back through bedrockConfig. No correctness issues here; this is a clean, side‑effect‑free pattern.

core/mcp/toolmanager.go (1)

22-35: Thread-safe storage and defaulting for CodeModeBindingLevel look solid

Adding codeModeBindingLevel atomic.Value alongside the existing atomic config fields and initializing it in NewToolsManager (with a default to CodeModeBindingLevelServer when unset) gives you a safe, race‑free way to read this setting from code‑mode helpers.

The constructor’s normalization of MaxAgentDepth, ToolExecutionTimeout, and CodeModeBindingLevel is consistent and avoids surprise zero values.

Also applies to: 53-82

core/mcp/codemode_readfile.go (4)

19-74: LGTM! Well-structured dynamic description generation.

The dynamic description generation based on CodeModeBindingLevel is well-implemented. The descriptions clearly communicate the differences between server-level and tool-level binding, including proper file path formats and usage instructions.


100-170: Excellent handling of ambiguity and tool-level filtering.

The implementation properly handles:

  • Case-insensitive matching with ambiguity detection (matchCount > 1)
  • Tool-level filtering with appropriate error messages when tools are not found
  • Clear error messages listing available options

The logic correctly differentiates between server-level and tool-level reads based on the parsed file path.


266-281: Clean and focused helper function.

The parseVFSFilePath function is well-designed:

  • Clear separation of concerns
  • Proper handling of both server-level and tool-level paths
  • Good documentation with examples

218-248: Robust line range validation with clear error messages.

The line range slicing implementation correctly:

  • Validates 1-based line numbers (not 0-based)
  • Checks bounds against totalLines
  • Ensures startLine <= endLine
  • Provides detailed error messages with context
ui/app/workspace/config/views/mcpView.tsx (3)

27-27: LGTM! Consistent default values and proper state initialization.

The mcp_code_mode_binding_level field is properly initialized to "server" across:

  • defaultConfig
  • localValues initial state
  • Synchronization from config with appropriate fallback

Also applies to: 40-44, 53-53


83-88: Good defensive validation in the handler.

The handleCodeModeBindingLevelChange handler includes validation to ensure only "server" or "tool" values are accepted, even though the Select component already constrains the options. This defensive approach is appropriate for robustness.


164-215: Excellent UX with visual examples!

The Code Mode Binding Level UI section provides:

  • Clear labeling and description
  • A Select component with intuitive option names
  • Dynamic visual examples showing the VFS structure for each binding level
  • Realistic file/folder names in the examples

This significantly improves user understanding of the feature's impact.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (5)
core/bifrost.go (1)

1887-1899: Prefer a typed CodeModeBindingLevel over a raw string parameter here.

You already have schemas.CodeModeBindingLevel, but UpdateToolManagerConfig accepts a plain string and then casts it, which makes it easy to pass invalid values through this boundary. Consider changing the signature to take schemas.CodeModeBindingLevel (and converting/validating earlier), so only well-typed values reach the tool manager.

Possible signature tweak
-func (bifrost *Bifrost) UpdateToolManagerConfig(maxAgentDepth int, toolExecutionTimeoutInSeconds int, codeModeBindingLevel string) error {
+func (bifrost *Bifrost) UpdateToolManagerConfig(
+    maxAgentDepth int,
+    toolExecutionTimeoutInSeconds int,
+    codeModeBindingLevel schemas.CodeModeBindingLevel,
+) error {
@@
-        CodeModeBindingLevel: schemas.CodeModeBindingLevel(codeModeBindingLevel),
+        CodeModeBindingLevel: codeModeBindingLevel,
ui/app/workspace/config/mcp-gateway/page.tsx (1)

1-11: MCP gateway page wrapper looks good; consider limiting the client boundary.

The page correctly wraps MCPGatewayView and wires the route. If ../views/mcpView already declares "use client", you could drop "use client" from this page and let it stay a server component to reduce the client-side surface; otherwise the current setup is fine and safe.

core/mcp/codemode_listfiles.go (1)

144-176: Consider using slices.Sort instead of bubble sort for consistency.

While bubble sort is acceptable for small lists, Go 1.21+ provides slices.Sort which is more idiomatic and efficient. This would also align with the slices package already used elsewhere in the codebase (e.g., transports/bifrost-http/handlers/config.go uses slices.Equal).

🔎 Proposed refactor using slices.Sort
 import (
 	"context"
 	"fmt"
+	"slices"
 	"strings"

 	"github.com/maximhq/bifrost/core/schemas"
 )

Then in renderTreeNode:

-	// Simple bubble sort for small lists (good enough for this use case)
-	for i := 0; i < len(keys); i++ {
-		for j := i + 1; j < len(keys); j++ {
-			if keys[j] < keys[i] {
-				keys[i], keys[j] = keys[j], keys[i]
-			}
-		}
-	}
+	slices.Sort(keys)
core/mcp/codemode_readfile.go (1)

266-281: Consider handling paths with more than two segments.

The current implementation assumes paths have at most two segments after removing the prefix. If a malformed path like servers/foo/bar/baz.d.ts is provided, it will only capture foo and bar, silently ignoring baz. Consider adding validation or handling this case explicitly.

🔎 Proposed enhancement for edge case handling
 func parseVFSFilePath(fileName string) (serverName, toolName string, isToolLevel bool) {
 	// Remove .d.ts extension
 	basePath := strings.TrimSuffix(fileName, ".d.ts")
 
 	// Remove "servers/" prefix if present
 	basePath = strings.TrimPrefix(basePath, "servers/")
 
 	// Check for path separator
 	parts := strings.Split(basePath, "/")
+	if len(parts) > 2 {
+		// Handle nested paths by joining extra segments into toolName
+		// e.g., "server/tool/subtool" -> serverName="server", toolName="tool/subtool"
+		return parts[0], strings.Join(parts[1:], "/"), true
+	}
 	if len(parts) == 2 {
 		// Tool-level: "serverName/toolName"
 		return parts[0], parts[1], true
 	}
 	// Server-level: "serverName"
 	return basePath, "", false
 }
ui/app/workspace/config/views/mcpView.tsx (1)

174-182: Consider adding aria-label for improved accessibility.

The Select component could benefit from an explicit aria-label to improve screen reader support.

🔎 Proposed accessibility enhancement
-				<Select value={localValues.mcp_code_mode_binding_level} onValueChange={handleCodeModeBindingLevelChange}>
+				<Select value={localValues.mcp_code_mode_binding_level} onValueChange={handleCodeModeBindingLevelChange} aria-label="Code Mode Binding Level">
 					<SelectTrigger id="mcp-binding-level" className="w-56">
 						<SelectValue placeholder="Select binding level" />
 					</SelectTrigger>
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8a83112 and 412e427.

📒 Files selected for processing (27)
  • core/bifrost.go
  • core/mcp.go
  • core/mcp/codemode_listfiles.go
  • core/mcp/codemode_readfile.go
  • core/mcp/toolmanager.go
  • core/schemas/mcp.go
  • framework/configstore/clientconfig.go
  • framework/configstore/migrations.go
  • framework/configstore/rdb.go
  • framework/configstore/tables/clientconfig.go
  • framework/configstore/tables/mcp.go
  • transports/bifrost-http/handlers/config.go
  • transports/bifrost-http/lib/config.go
  • transports/bifrost-http/server/server.go
  • transports/go.mod
  • ui/app/workspace/config/logging/page.tsx
  • ui/app/workspace/config/mcp-gateway/page.tsx
  • ui/app/workspace/config/views/clientSettingsView.tsx
  • ui/app/workspace/config/views/governanceView.tsx
  • ui/app/workspace/config/views/loggingView.tsx
  • ui/app/workspace/config/views/mcpView.tsx
  • ui/app/workspace/config/views/observabilityView.tsx
  • ui/app/workspace/config/views/performanceTuningView.tsx
  • ui/app/workspace/config/views/securityView.tsx
  • ui/components/sidebar.tsx
  • ui/lib/types/config.ts
  • ui/lib/types/schemas.ts
💤 Files with no reviewable changes (1)
  • framework/configstore/tables/mcp.go
🚧 Files skipped from review as they are similar to previous changes (13)
  • ui/lib/types/config.ts
  • transports/bifrost-http/lib/config.go
  • ui/app/workspace/config/views/performanceTuningView.tsx
  • core/schemas/mcp.go
  • ui/lib/types/schemas.ts
  • ui/app/workspace/config/logging/page.tsx
  • core/mcp/toolmanager.go
  • ui/components/sidebar.tsx
  • transports/bifrost-http/server/server.go
  • transports/go.mod
  • framework/configstore/rdb.go
  • ui/app/workspace/config/views/loggingView.tsx
  • ui/app/workspace/config/views/governanceView.tsx
🧰 Additional context used
📓 Path-based instructions (1)
**

⚙️ CodeRabbit configuration file

always check the stack if there is one for the current PR. do not give localized reviews for the PR, always see all changes in the light of the whole stack of PRs (if there is a stack, if there is no stack you can continue to make localized suggestions/reviews)

Files:

  • core/mcp/codemode_listfiles.go
  • ui/app/workspace/config/views/securityView.tsx
  • ui/app/workspace/config/views/observabilityView.tsx
  • core/bifrost.go
  • ui/app/workspace/config/views/clientSettingsView.tsx
  • ui/app/workspace/config/views/mcpView.tsx
  • framework/configstore/migrations.go
  • framework/configstore/clientconfig.go
  • transports/bifrost-http/handlers/config.go
  • core/mcp.go
  • core/mcp/codemode_readfile.go
  • framework/configstore/tables/clientconfig.go
  • ui/app/workspace/config/mcp-gateway/page.tsx
🧠 Learnings (2)
📚 Learning: 2025-12-09T17:07:42.007Z
Learnt from: qwerty-dvorak
Repo: maximhq/bifrost PR: 1006
File: core/schemas/account.go:9-18
Timestamp: 2025-12-09T17:07:42.007Z
Learning: In core/schemas/account.go, the HuggingFaceKeyConfig field within the Key struct is currently unused and reserved for future Hugging Face inference endpoint deployments. Do not flag this field as missing from OpenAPI documentation or require its presence in the API spec until the feature is actively implemented and used. When the feature is added, update the OpenAPI docs accordingly; otherwise, treat this field as non-breaking and not part of the current API surface.

Applied to files:

  • core/mcp/codemode_listfiles.go
  • core/bifrost.go
  • framework/configstore/migrations.go
  • framework/configstore/clientconfig.go
  • transports/bifrost-http/handlers/config.go
  • core/mcp.go
  • core/mcp/codemode_readfile.go
  • framework/configstore/tables/clientconfig.go
📚 Learning: 2025-12-12T08:25:02.629Z
Learnt from: Pratham-Mishra04
Repo: maximhq/bifrost PR: 1000
File: transports/bifrost-http/integrations/router.go:709-712
Timestamp: 2025-12-12T08:25:02.629Z
Learning: In transports/bifrost-http/**/*.go, update streaming response handling to align with OpenAI Responses API: use typed SSE events such as response.created, response.output_text.delta, response.done, etc., and do not rely on the legacy data: [DONE] termination marker. Note that data: [DONE] is only used by the older Chat Completions and Text Completions streaming APIs. Ensure parsers, writers, and tests distinguish SSE events from the [DONE] sentinel and handle each event type accordingly for correct stream termination and progress updates.

Applied to files:

  • transports/bifrost-http/handlers/config.go
🧬 Code graph analysis (5)
core/mcp/codemode_listfiles.go (4)
core/mcp/toolmanager.go (1)
  • ToolsManager (22-34)
core/schemas/chatcompletions.go (2)
  • ChatTool (252-257)
  • ChatToolFunction (260-265)
core/schemas/mcp.go (1)
  • CodeModeBindingLevelServer (40-40)
core/schemas/utils.go (1)
  • Ptr (16-18)
core/bifrost.go (1)
core/schemas/mcp.go (2)
  • MCPToolManagerConfig (25-29)
  • CodeModeBindingLevel (37-37)
ui/app/workspace/config/views/mcpView.tsx (1)
ui/components/ui/select.tsx (5)
  • Select (151-151)
  • SelectTrigger (159-159)
  • SelectValue (160-160)
  • SelectContent (152-152)
  • SelectItem (154-154)
framework/configstore/migrations.go (2)
framework/migrator/migrator.go (3)
  • New (131-149)
  • DefaultOptions (100-106)
  • Migration (62-69)
framework/configstore/tables/clientconfig.go (2)
  • TableClientConfig (11-41)
  • TableClientConfig (44-44)
transports/bifrost-http/handlers/config.go (3)
framework/configstore/clientconfig.go (1)
  • ClientConfig (37-54)
core/schemas/mcp.go (2)
  • CodeModeBindingLevelServer (40-40)
  • CodeModeBindingLevelTool (41-41)
transports/bifrost-http/handlers/utils.go (1)
  • SendError (35-44)
🔇 Additional comments (18)
framework/configstore/clientconfig.go (1)

52-54: MCP code mode binding level field and hashing look consistent.

Adding MCPCodeModeBindingLevel to ClientConfig and treating the empty value as "server" in the hash keeps DB and config.json in sync with the same effective default while still tracking non-default values. This is a clean extension of the existing hashing scheme.

Also applies to: 116-120

ui/app/workspace/config/views/observabilityView.tsx (1)

29-30: Default config correctly initializes mcp_code_mode_binding_level.

Including mcp_code_mode_binding_level: "server" in defaultConfig keeps this view’s CoreConfig shape consistent with the shared type and other config screens; no additional changes are needed here.

framework/configstore/migrations.go (1)

101-103: New MCP code mode binding level migration is consistent and safe.

Wiring migrationAddMCPCodeModeBindingLevelColumn into triggerMigrations and implementing it with a HasColumn guard plus symmetric rollback matches the existing migration style and should be safe for both fresh and upgraded installs.

Also applies to: 1320-1349

framework/configstore/tables/clientconfig.go (1)

25-27: ClientConfig DB schema aligns with the new MCP code mode binding level.

Adding MCPCodeModeBindingLevel with gorm:"default:server" and the matching JSON tag keeps the persisted schema in sync with the in-memory ClientConfig and the intended default behavior.

ui/app/workspace/config/views/securityView.tsx (1)

36-37: Security view defaultConfig updated correctly for mcp_code_mode_binding_level.

Including mcp_code_mode_binding_level: "server" in this view’s defaultConfig keeps it consistent with the CoreConfig type and other config views, without affecting the existing hasChanges/save logic.

ui/app/workspace/config/views/clientSettingsView.tsx (1)

26-27: Client settings defaults and layout remain consistent after extension.

Adding mcp_code_mode_binding_level: "server" to defaultConfig keeps this view in step with the extended CoreConfig, and the wrapper’s class reordering is a no-op stylistically; no further changes are required here.

Also applies to: 76-77

core/mcp/codemode_listfiles.go (2)

17-53: LGTM! Dynamic description generation is well-implemented.

The description correctly differentiates between server-level and tool-level binding modes, providing clear guidance to LLMs on how to navigate the VFS structure.


68-117: LGTM! File list generation correctly handles both binding levels.

The logic properly iterates through code mode clients and builds the appropriate file paths based on the configured binding level.

transports/bifrost-http/handlers/config.go (3)

32-32: LGTM! Interface updated to accept the new binding level parameter.

The UpdateMCPToolManagerConfig signature correctly includes the new codeModeBindingLevel string parameter.


233-239: LGTM! Validation correctly uses schema constants.

The validation properly checks against schemas.CodeModeBindingLevelServer and schemas.CodeModeBindingLevelTool constants, avoiding magic strings as suggested in the past review.


253-264: LGTM! Change detection and update logic handles empty string correctly.

The logic at lines 253-256 only triggers updates when the payload is non-empty and differs from the current value, and lines 285-288 prevent clearing the stored value when an empty string is sent. This addresses the drift concern from the previous review.

core/mcp/codemode_readfile.go (3)

19-74: LGTM! Tool definition correctly adapts descriptions based on binding level.

The dynamic descriptions clearly explain the file format and usage for both server-level (servers/<serverName>.d.ts) and tool-level (servers/<serverName>/<toolName>.d.ts) paths.


140-169: LGTM! Tool-level filtering with helpful error messages.

When a tool is not found, the error message enumerates all available tools in the server, guiding users to the correct file path.


294-312: LGTM! Type definition headers correctly reflect the scope.

The generated TypeScript definitions clearly indicate whether they cover a single tool or all tools in a server, helping LLMs understand the scope of the definitions.

ui/app/workspace/config/views/mcpView.tsx (3)

27-28: LGTM! Default configuration correctly includes the new binding level.

The default value of "server" aligns with the backend defaults and provides a sensible out-of-the-box experience.


83-88: LGTM! Handler validates binding level values.

The handler correctly validates that only "server" or "tool" values are propagated to localConfig, preventing invalid values from being saved.


164-215: LGTM! Excellent UX with the visual VFS structure example.

The live visual example effectively demonstrates the difference between server-level and tool-level binding modes, making it easy for users to understand the impact of their selection.

core/mcp.go (1)

1134-1151: No changes needed—code is type-safe by design.

The field config.InProcessServer is defined in core/schemas/mcp.go as *server.MCPServer, which matches exactly what client.NewInProcessClient expects (per mcp-go v0.41.1 signature). Go's static type system enforces this at compile time; no explicit type assertion was ever present or needed. The nil check at lines 1135–1137 provides appropriate validation for runtime behavior.

Likely an incorrect or invalid review comment.

@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 12-23-feat_added_binding_level_toggle_in_mcp_codemode branch from 412e427 to f26d081 Compare December 24, 2025 12:19
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (4)
ui/components/sidebar.tsx (1)

69-86: Import MCPIcon instead of redefining it.

The MCPIcon component is already exported from ui/components/ui/icons.tsx (as shown in the relevant code snippets). Redefining it here creates code duplication and violates the DRY principle.

🔎 Proposed fix to import MCPIcon

Remove the inline definition and import it instead:

+import { MCPIcon } from "@/components/ui/icons";
 import {
 	ArrowUpRight,
 	BookUser,
@@ -66,22 +67,6 @@
 import { ThemeToggle } from "./themeToggle";
 import { Badge } from "./ui/badge";
 import { PromoCardStack } from "./ui/promoCardStack";
-
-// Custom MCP Icon Component
-const MCPIcon = ({ className }: { className?: string }) => (
-	<svg
-		className={className}
-		fill="currentColor"
-		fillRule="evenodd"
-		height="1em"
-		style={{ flex: "none", lineHeight: 1 }}
-		viewBox="0 0 24 24"
-		width="1em"
-		xmlns="http://www.w3.org/2000/svg"
-		aria-label="MCP clients icon"
-	>
-		<title>MCP clients icon</title>
-		<path d="M15.688 2.343a2.588 2.588 0 00-3.61 0l-9.626 9.44a.863.863 0 01-1.203 0 .823.823 0 010-1.18l9.626-9.44a4.313 4.313 0 016.016 0 4.116 4.116 0 011.204 3.54 4.3 4.3 0 013.609 1.18l.05.05a4.115 4.115 0 010 5.9l-8.706 8.537a.274.274 0 000 .393l1.788 1.754a.823.823 0 010 1.18.863.863 0 01-1.203 0l-1.788-1.753a1.92 1.92 0 010-2.754l8.706-8.538a2.47 2.47 0 000-3.54l-.05-.049a2.588 2.588 0 00-3.607-.003l-7.172 7.034-.002.002-.098.097a.863.863 0 01-1.204 0 .823.823 0 010-1.18l7.273-7.133a2.47 2.47 0 00-.003-3.537z" />
-		<path d="M14.485 4.703a.823.823 0 000-1.18.863.863 0 00-1.204 0l-7.119 6.982a4.115 4.115 0 000 5.9 4.314 4.314 0 006.016 0l7.12-6.982a.823.823 0 000-1.18.863.863 0 00-1.204 0l-7.119 6.982a2.588 2.588 0 01-3.61 0 2.47 2.47 0 010-3.54l7.12-6.982z" />
-	</svg>
-);
core/mcp/codemode_listfiles.go (1)

186-193: Consider using sort.Strings for better performance.

The bubble sort implementation works for small lists but could be replaced with Go's standard sort.Strings(keys) for better performance and readability, especially as the number of servers/tools grows.

🔎 Proposed refactor
+import (
+	"sort"
+)

 func renderTreeNode(node *treeNode, indent string, lines *[]string, isRoot bool) {
 	// Get sorted keys for consistent output
 	var keys []string
 	for key := range node.children {
 		keys = append(keys, key)
 	}
 
-	// Simple bubble sort for small lists (good enough for this use case)
-	for i := 0; i < len(keys); i++ {
-		for j := i + 1; j < len(keys); j++ {
-			if keys[j] < keys[i] {
-				keys[i], keys[j] = keys[j], keys[i]
-			}
-		}
-	}
+	// Sort keys for consistent output
+	sort.Strings(keys)
ui/app/workspace/config/views/mcpView.tsx (1)

90-114: Consider adding binding level validation in save handler.

While handleCodeModeBindingLevelChange already validates the value, adding explicit validation in handleSave would provide an extra safety layer against edge cases where localConfig.mcp_code_mode_binding_level might contain an invalid value.

🔎 Optional validation enhancement
 	const handleSave = useCallback(async () => {
 		try {
 			const agentDepth = Number.parseInt(localValues.mcp_agent_depth);
 			const toolTimeout = Number.parseInt(localValues.mcp_tool_execution_timeout);
 
 			if (isNaN(agentDepth) || agentDepth <= 0) {
 				toast.error("Max agent depth must be a positive number.");
 				return;
 			}
 
 			if (isNaN(toolTimeout) || toolTimeout <= 0) {
 				toast.error("Tool execution timeout must be a positive number.");
 				return;
 			}
+
+			const bindingLevel = localConfig.mcp_code_mode_binding_level;
+			if (bindingLevel !== "server" && bindingLevel !== "tool") {
+				toast.error("Invalid binding level. Please select either Server-Level or Tool-Level.");
+				return;
+			}
 
 			if (!bifrostConfig) {
 				toast.error("Configuration not loaded. Please refresh and try again.");
 				return;
 			}
 			await updateCoreConfig({ ...bifrostConfig, client_config: localConfig }).unwrap();
 			toast.success("MCP settings updated successfully.");
 		} catch (error) {
 			toast.error(getErrorMessage(error));
 		}
 	}, [bifrostConfig, localConfig, localValues, updateCoreConfig]);
core/mcp/codemode_readfile.go (1)

266-281: Consider handling edge cases in path parsing.

The parseVFSFilePath function handles the common cases well, but a few edge cases could cause unexpected behavior:

  1. Paths with more than one / after removing prefix (e.g., "servers/calc/tool/extra.d.ts") would silently ignore parts beyond the second.
  2. Empty parts from double slashes (e.g., "servers//tool.d.ts") would produce empty serverName.

Since these are malformed inputs that shouldn't occur with proper listToolFiles output, this is a minor concern. Consider adding a comment noting the expected input format assumption.

🔎 Optional: Add input validation or comment
 func parseVFSFilePath(fileName string) (serverName, toolName string, isToolLevel bool) {
+	// Expects fileName from listToolFiles in format:
+	// - Server-level: "servers/<serverName>.d.ts" or "<serverName>.d.ts"
+	// - Tool-level: "servers/<serverName>/<toolName>.d.ts" or "<serverName>/<toolName>.d.ts"
 	// Remove .d.ts extension
 	basePath := strings.TrimSuffix(fileName, ".d.ts")
 
 	// Remove "servers/" prefix if present
 	basePath = strings.TrimPrefix(basePath, "servers/")
 
 	// Check for path separator
 	parts := strings.Split(basePath, "/")
-	if len(parts) == 2 {
+	if len(parts) >= 2 && parts[0] != "" && parts[1] != "" {
 		// Tool-level: "serverName/toolName"
 		return parts[0], parts[1], true
 	}
 	// Server-level: "serverName"
 	return basePath, "", false
 }
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 412e427 and f26d081.

📒 Files selected for processing (28)
  • core/bifrost.go
  • core/changelog.md
  • core/mcp/codemode_listfiles.go
  • core/mcp/codemode_readfile.go
  • core/mcp/toolmanager.go
  • core/schemas/mcp.go
  • framework/changelog.md
  • framework/configstore/clientconfig.go
  • framework/configstore/migrations.go
  • framework/configstore/rdb.go
  • framework/configstore/tables/clientconfig.go
  • framework/configstore/tables/mcp.go
  • transports/bifrost-http/handlers/config.go
  • transports/bifrost-http/lib/config.go
  • transports/bifrost-http/server/server.go
  • transports/changelog.md
  • ui/app/workspace/config/logging/page.tsx
  • ui/app/workspace/config/mcp-gateway/page.tsx
  • ui/app/workspace/config/views/clientSettingsView.tsx
  • ui/app/workspace/config/views/governanceView.tsx
  • ui/app/workspace/config/views/loggingView.tsx
  • ui/app/workspace/config/views/mcpView.tsx
  • ui/app/workspace/config/views/observabilityView.tsx
  • ui/app/workspace/config/views/performanceTuningView.tsx
  • ui/app/workspace/config/views/securityView.tsx
  • ui/components/sidebar.tsx
  • ui/lib/types/config.ts
  • ui/lib/types/schemas.ts
💤 Files with no reviewable changes (1)
  • framework/changelog.md
🚧 Files skipped from review as they are similar to previous changes (14)
  • framework/configstore/clientconfig.go
  • transports/bifrost-http/lib/config.go
  • core/schemas/mcp.go
  • ui/lib/types/config.ts
  • ui/app/workspace/config/views/performanceTuningView.tsx
  • core/mcp/toolmanager.go
  • ui/app/workspace/config/logging/page.tsx
  • framework/configstore/migrations.go
  • ui/app/workspace/config/views/clientSettingsView.tsx
  • ui/app/workspace/config/views/observabilityView.tsx
  • core/bifrost.go
  • ui/app/workspace/config/mcp-gateway/page.tsx
  • ui/lib/types/schemas.ts
  • ui/app/workspace/config/views/securityView.tsx
🧰 Additional context used
📓 Path-based instructions (1)
**

⚙️ CodeRabbit configuration file

always check the stack if there is one for the current PR. do not give localized reviews for the PR, always see all changes in the light of the whole stack of PRs (if there is a stack, if there is no stack you can continue to make localized suggestions/reviews)

Files:

  • core/changelog.md
  • framework/configstore/tables/clientconfig.go
  • transports/bifrost-http/handlers/config.go
  • transports/changelog.md
  • framework/configstore/rdb.go
  • framework/configstore/tables/mcp.go
  • core/mcp/codemode_listfiles.go
  • ui/components/sidebar.tsx
  • core/mcp/codemode_readfile.go
  • transports/bifrost-http/server/server.go
  • ui/app/workspace/config/views/mcpView.tsx
  • ui/app/workspace/config/views/governanceView.tsx
  • ui/app/workspace/config/views/loggingView.tsx
🧠 Learnings (2)
📚 Learning: 2025-12-09T17:07:42.007Z
Learnt from: qwerty-dvorak
Repo: maximhq/bifrost PR: 1006
File: core/schemas/account.go:9-18
Timestamp: 2025-12-09T17:07:42.007Z
Learning: In core/schemas/account.go, the HuggingFaceKeyConfig field within the Key struct is currently unused and reserved for future Hugging Face inference endpoint deployments. Do not flag this field as missing from OpenAPI documentation or require its presence in the API spec until the feature is actively implemented and used. When the feature is added, update the OpenAPI docs accordingly; otherwise, treat this field as non-breaking and not part of the current API surface.

Applied to files:

  • framework/configstore/tables/clientconfig.go
  • transports/bifrost-http/handlers/config.go
  • framework/configstore/rdb.go
  • framework/configstore/tables/mcp.go
  • core/mcp/codemode_listfiles.go
  • core/mcp/codemode_readfile.go
  • transports/bifrost-http/server/server.go
📚 Learning: 2025-12-12T08:25:02.629Z
Learnt from: Pratham-Mishra04
Repo: maximhq/bifrost PR: 1000
File: transports/bifrost-http/integrations/router.go:709-712
Timestamp: 2025-12-12T08:25:02.629Z
Learning: In transports/bifrost-http/**/*.go, update streaming response handling to align with OpenAI Responses API: use typed SSE events such as response.created, response.output_text.delta, response.done, etc., and do not rely on the legacy data: [DONE] termination marker. Note that data: [DONE] is only used by the older Chat Completions and Text Completions streaming APIs. Ensure parsers, writers, and tests distinguish SSE events from the [DONE] sentinel and handle each event type accordingly for correct stream termination and progress updates.

Applied to files:

  • transports/bifrost-http/handlers/config.go
  • transports/bifrost-http/server/server.go
🧬 Code graph analysis (5)
transports/bifrost-http/handlers/config.go (3)
framework/configstore/clientconfig.go (1)
  • ClientConfig (37-54)
core/schemas/mcp.go (2)
  • CodeModeBindingLevelServer (40-40)
  • CodeModeBindingLevelTool (41-41)
transports/bifrost-http/handlers/utils.go (1)
  • SendError (35-44)
framework/configstore/rdb.go (1)
core/schemas/mcp.go (1)
  • CodeModeBindingLevel (37-37)
core/mcp/codemode_listfiles.go (3)
core/mcp/toolmanager.go (1)
  • ToolsManager (22-34)
core/schemas/chatcompletions.go (2)
  • ChatTool (252-257)
  • ChatToolFunction (260-265)
core/schemas/mcp.go (1)
  • CodeModeBindingLevelServer (40-40)
ui/components/sidebar.tsx (1)
ui/components/ui/icons.tsx (1)
  • MCPIcon (1758-1773)
core/mcp/codemode_readfile.go (4)
core/schemas/chatcompletions.go (1)
  • ChatTool (252-257)
core/schemas/mcp.go (1)
  • CodeModeBindingLevelServer (40-40)
core/schemas/utils.go (1)
  • Ptr (16-18)
ui/lib/types/logs.ts (1)
  • Function (152-157)
🔇 Additional comments (24)
core/changelog.md (1)

1-3: Changelog entries accurately reflect the PR stack scope.

The three new entries align with the coordinated MCP enhancements across the PR stack (code mode, health monitoring, and responses format support). Entries follow the project's changelog format and are appropriately scoped.

ui/components/sidebar.tsx (2)

489-495: Verify navigation structure for two "MCP Gateway" entries.

The sidebar now contains two separate "MCP Gateway" navigation items:

  1. Top-level item at Line 372: /workspace/mcp-gateway - "MCP configuration"
  2. New Config submenu item (this change): /workspace/config/mcp-gateway - "MCP gateway configuration"

While the PR objectives indicate these serve different purposes (main management vs. binding level configuration), the similar naming may cause user confusion.

Consider one of the following:

  • Differentiate the labels (e.g., "MCP Gateway" vs. "MCP Gateway Settings" or "MCP Binding Config")
  • Add clarifying descriptions
  • Confirm this navigation structure has been validated with the team

Based on PR objectives indicating separate pages for management and configuration.


725-725: LGTM: Good formatting cleanup.

Removing the extra whitespace around the router prop improves consistency with standard JSX formatting conventions.

framework/configstore/tables/mcp.go (1)

82-82: LGTM: Formatting improvement.

The added blank line before the return statement improves readability and aligns with common Go style conventions.

transports/changelog.md (1)

1-4: LGTM: Changelog appropriately documents new MCP features.

The changelog entries accurately reflect the code mode binding level feature and related MCP enhancements introduced in this PR and related stack changes.

core/mcp/codemode_listfiles.go (2)

17-53: LGTM: Dynamic description based on binding level.

The tool description correctly adapts to the configured binding level, providing clear guidance to users about the available file structure and how to access tools.


68-118: LGTM: Binding level logic correctly implements file listing.

The implementation correctly handles both server-level and tool-level binding modes, building appropriate file paths and checking for valid tool functions before adding them to the list.

ui/app/workspace/config/views/loggingView.tsx (1)

13-29: LGTM: Default config extended with new MCP field.

The addition of mcp_code_mode_binding_level: "server" maintains consistency across config views and ensures the field is preserved during updates.

ui/app/workspace/config/views/governanceView.tsx (2)

11-27: LGTM: Default config extended with new MCP field.

Consistent addition of mcp_code_mode_binding_level to maintain config completeness across views.


67-67: LGTM: Styling consistency improvement.

The className reordering maintains the same visual output while aligning with layout patterns used in other views.

framework/configstore/rdb.go (2)

30-56: LGTM: Client config update correctly persists new field.

The MCPCodeModeBindingLevel field is properly mapped during client configuration updates.


179-205: LGTM: Client config retrieval correctly reads new field.

The MCPCodeModeBindingLevel field is properly retrieved and returned in the client configuration.

ui/app/workspace/config/views/mcpView.tsx (5)

12-28: LGTM: Default configuration includes new binding level field.

The default value of "server" is consistent with backend defaults and provides a sensible starting point.


37-56: LGTM: State management properly handles binding level.

The local state initialization and synchronization correctly handle the new field with appropriate fallback to "server" when undefined.


58-65: LGTM: Change detection includes binding level.

The comparison properly detects changes in the binding level with a safe fallback for backward compatibility.


83-88: LGTM: Handler validates binding level values.

The change handler correctly validates that only "server" or "tool" values are accepted before updating the configuration.


164-215: Excellent UX: Visual examples clearly demonstrate binding levels.

The UI section effectively communicates the difference between server-level and tool-level bindings through interactive visual examples. The dynamic display helps users understand the impact of their choice.

transports/bifrost-http/handlers/config.go (2)

233-239: Validation logic uses schema constants correctly.

The validation correctly uses schemas.CodeModeBindingLevelServer and schemas.CodeModeBindingLevelTool constants instead of string literals, avoiding typos if constants change. The empty string guard ensures validation only runs when a value is provided.


253-256: Empty string handling now consistent.

The fix addresses the previous review concern: binding level is only updated when the payload is non-empty (lines 253-256 for reload trigger, lines 285-288 for persistence). This prevents clearing stored values when clients omit the field.

Also applies to: 285-288

transports/bifrost-http/server/server.go (2)

69-69: Interface signature updated to include binding level parameter.

The ServerCallbacks interface correctly adds the codeModeBindingLevel string parameter, maintaining consistency with the config handler's call site.


711-716: Method forwards binding level to client correctly.

The implementation passes codeModeBindingLevel through to s.Client.UpdateToolManagerConfig, completing the propagation chain from the HTTP handler to the Bifrost core.

core/mcp/codemode_readfile.go (3)

19-46: Dynamic tool descriptions based on binding level are well-structured.

The descriptions clearly differentiate server-level (servers/<serverName>.d.ts) and tool-level (servers/<serverName>/<toolName>.d.ts) workflows, providing helpful usage guidance for LLMs.


140-169: Tool-level filtering logic is correct with helpful error messaging.

The code properly filters to the specific tool when isToolLevel is true, and provides a detailed error message listing available tools when the requested tool isn't found. The case-insensitive matching is consistent with server-level matching.


294-312: Header generation correctly adapts to binding level.

The conditional logic produces appropriate headers:

  • Tool-level (single tool): Shows <server>.<tool> in the header
  • Server-level (all tools): Shows <server> MCP server in the header

The instructions also adapt appropriately ("a specific tool" vs "all tools").

Copy link
Contributor

akshaydeo commented Dec 24, 2025

Merge activity

  • Dec 24, 12:44 PM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Dec 24, 12:44 PM UTC: @akshaydeo merged this pull request with Graphite.

@akshaydeo akshaydeo merged commit 4f82c3b into v1.4.0 Dec 24, 2025
3 checks passed
@akshaydeo akshaydeo deleted the 12-23-feat_added_binding_level_toggle_in_mcp_codemode branch December 24, 2025 12:44
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.

3 participants