import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Switch } from "@/components/ui/switch"; import { getErrorMessage, useGetCoreConfigQuery, useUpdateCoreConfigMutation, } from "@/lib/store"; import { CoreConfig, DefaultCoreConfig } from "@/lib/types/config"; import { RbacOperation, RbacResource, useRbac } from "@enterprise/lib"; import { useCallback, useEffect, useMemo, useState } from "react"; import { toast } from "sonner"; export default function MCPView() { const hasSettingsUpdateAccess = useRbac( RbacResource.Settings, RbacOperation.Update, ); const { data: bifrostConfig } = useGetCoreConfigQuery({ fromDB: true }); const config = bifrostConfig?.client_config; const [updateCoreConfig, { isLoading }] = useUpdateCoreConfigMutation(); const [localConfig, setLocalConfig] = useState(DefaultCoreConfig); const [localValues, setLocalValues] = useState<{ mcp_agent_depth: string; mcp_tool_execution_timeout: string; mcp_code_mode_binding_level: string; mcp_tool_sync_interval: string; }>({ mcp_agent_depth: "10", mcp_tool_execution_timeout: "30", mcp_code_mode_binding_level: "server", mcp_tool_sync_interval: "10", }); useEffect(() => { if (bifrostConfig && config) { setLocalConfig(config); setLocalValues({ mcp_agent_depth: config?.mcp_agent_depth?.toString() || "10", mcp_tool_execution_timeout: config?.mcp_tool_execution_timeout?.toString() || "30", mcp_code_mode_binding_level: config?.mcp_code_mode_binding_level || "server", mcp_tool_sync_interval: config?.mcp_tool_sync_interval?.toString() || "10", }); } }, [config, bifrostConfig]); const hasChanges = useMemo(() => { if (!config) return false; return ( localConfig.mcp_agent_depth !== config.mcp_agent_depth || localConfig.mcp_tool_execution_timeout !== config.mcp_tool_execution_timeout || localConfig.mcp_code_mode_binding_level !== (config.mcp_code_mode_binding_level || "server") || localConfig.mcp_tool_sync_interval !== (config.mcp_tool_sync_interval ?? 10) || localConfig.mcp_disable_auto_tool_inject !== (config.mcp_disable_auto_tool_inject ?? false) ); }, [config, localConfig]); const handleAgentDepthChange = useCallback((value: string) => { setLocalValues((prev) => ({ ...prev, mcp_agent_depth: value })); const numValue = Number.parseInt(value); if (!isNaN(numValue) && numValue > 0) { setLocalConfig((prev) => ({ ...prev, mcp_agent_depth: numValue })); } }, []); const handleToolExecutionTimeoutChange = useCallback((value: string) => { setLocalValues((prev) => ({ ...prev, mcp_tool_execution_timeout: value })); const numValue = Number.parseInt(value); if (!isNaN(numValue) && numValue > 0) { setLocalConfig((prev) => ({ ...prev, mcp_tool_execution_timeout: numValue, })); } }, []); const handleCodeModeBindingLevelChange = useCallback((value: string) => { setLocalValues((prev) => ({ ...prev, mcp_code_mode_binding_level: value })); if (value === "server" || value === "tool") { setLocalConfig((prev) => ({ ...prev, mcp_code_mode_binding_level: value, })); } }, []); const handleToolSyncIntervalChange = useCallback((value: string) => { setLocalValues((prev) => ({ ...prev, mcp_tool_sync_interval: value })); const numValue = Number.parseInt(value); if (!isNaN(numValue) && numValue >= 0) { setLocalConfig((prev) => ({ ...prev, mcp_tool_sync_interval: numValue })); } }, []); const handleDisableAutoToolInjectChange = useCallback((checked: boolean) => { setLocalConfig((prev) => ({ ...prev, mcp_disable_auto_tool_inject: checked, })); }, []); 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; } 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]); return (

MCP Settings

Configure MCP (Model Context Protocol) agent and tool settings.

{/* Max Agent Depth */}

Maximum depth for MCP agent execution.

handleAgentDepthChange(e.target.value)} min="1" />
{/* Tool Execution Timeout */}

Maximum time in seconds for tool execution.

handleToolExecutionTimeoutChange(e.target.value)} min="1" />
{/* Tool Sync Interval */}

How often to refresh tool lists from MCP servers. Set to 0 to disable.

handleToolSyncIntervalChange(e.target.value)} min="0" />
{/* Disable Auto Tool Injection */}

When enabled, MCP tools are not automatically included in every request. Tools are only injected when explicitly specified via request headers ( x-bf-mcp-include-tools) and still must be allowed by the virtual key MCP configuration.

{/* Code Mode Binding Level */}

How tools are exposed in the VFS: server-level (all tools per server) or tool-level (individual tools).

{/* Visual Example */}

VFS Structure:

{localValues.mcp_code_mode_binding_level === "server" ? (
servers/
├─ calculator.py
├─ youtube.py
└─ weather.py

All tools per server in a single .py file

) : (
servers/
├─ calculator/
├─ add.py
└─ subtract.py
├─ youtube/
├─ GET_CHANNELS.py
└─ SEARCH_VIDEOS.py
└─ weather/
└─ get_forecast.py

Individual .py file for each tool

)}
); }