import React from 'react'; import * as Ariakit from '@ariakit/react'; import { ChevronRight } from 'lucide-react'; import { PinIcon, MCPIcon } from '@librechat/client'; import MCPServerStatusIcon from '~/components/MCP/MCPServerStatusIcon'; import MCPConfigDialog from '~/components/MCP/MCPConfigDialog'; import { useBadgeRowContext } from '~/Providers'; import { cn } from '~/utils'; interface MCPSubMenuProps { placeholder?: string; } const MCPSubMenu = React.forwardRef( ({ placeholder, ...props }, ref) => { const { mcpServerManager } = useBadgeRowContext(); const { isPinned, mcpValues, setIsPinned, isInitializing, placeholderText, availableMCPServers, getConfigDialogProps, toggleServerSelection, getServerStatusIconProps, } = mcpServerManager; const menuStore = Ariakit.useMenuStore({ focusLoop: true, showTimeout: 100, placement: 'right', }); // Don't render if no MCP servers are configured if (!availableMCPServers || availableMCPServers.length === 0) { return null; } const configDialogProps = getConfigDialogProps(); return (
) => { e.stopPropagation(); menuStore.toggle(); }} className="flex w-full cursor-pointer items-center justify-between rounded-lg p-2 hover:bg-surface-hover" /> } >
{placeholder || placeholderText}
{availableMCPServers.map((s) => { const statusIconProps = getServerStatusIconProps(s.serverName); const isSelected = mcpValues?.includes(s.serverName) ?? false; const isServerInitializing = isInitializing(s.serverName); const statusIcon = statusIconProps && ; return ( { event.preventDefault(); toggleServerSelection(s.serverName); }} disabled={isServerInitializing} className={cn( 'flex items-center gap-2 rounded-lg px-2 py-1.5 text-text-primary hover:cursor-pointer', 'scroll-m-1 outline-none transition-colors', 'hover:bg-black/[0.075] dark:hover:bg-white/10', 'data-[active-item]:bg-black/[0.075] dark:data-[active-item]:bg-white/10', 'w-full min-w-0 justify-between text-sm', isServerInitializing && 'opacity-50 hover:bg-transparent dark:hover:bg-transparent', )} >
{s.serverName}
{statusIcon &&
{statusIcon}
}
); })}
{configDialogProps && }
); }, ); MCPSubMenu.displayName = 'MCPSubMenu'; export default React.memo(MCPSubMenu);