import React, { useState } from 'react'; import { useFormContext } from 'react-hook-form'; import { Constants } from 'librechat-data-provider'; import { useUpdateUserPluginsMutation } from 'librechat-data-provider/react-query'; import { Label, OGDialog, TrashIcon, OGDialogTrigger, useToastContext, OGDialogTemplate, } from '@librechat/client'; import type { AgentForm, MCPServerInfo } from '~/common'; import MCPServerStatusIcon from '~/components/MCP/MCPServerStatusIcon'; import MCPConfigDialog from '~/components/MCP/MCPConfigDialog'; import { useLocalize, useMCPServerManager } from '~/hooks'; import { cn } from '~/utils'; export default function UninitializedMCPTool({ serverInfo }: { serverInfo?: MCPServerInfo }) { const [isFocused, setIsFocused] = useState(false); const [isHovering, setIsHovering] = useState(false); const localize = useLocalize(); const { showToast } = useToastContext(); const updateUserPlugins = useUpdateUserPluginsMutation(); const { getValues, setValue } = useFormContext(); const { initializeServer, isInitializing, getServerStatusIconProps, getConfigDialogProps } = useMCPServerManager(); if (!serverInfo) { return null; } const removeTool = (serverName: string) => { if (!serverName) { return; } updateUserPlugins.mutate( { pluginKey: `${Constants.mcp_prefix}${serverName}`, action: 'uninstall', auth: {}, isEntityTool: true, }, { onError: (error: unknown) => { showToast({ message: localize('com_ui_delete_tool_error', { error: String(error) }), status: 'error', }); }, onSuccess: () => { const currentTools = getValues('tools'); const remainingToolIds = currentTools?.filter( (currentToolId) => currentToolId !== serverName && !currentToolId.endsWith(`${Constants.mcp_delimiter}${serverName}`), ) || []; setValue('tools', remainingToolIds); showToast({ message: localize('com_ui_delete_tool_success'), status: 'success' }); }, }, ); }; const serverName = serverInfo.serverName; const isServerInitializing = isInitializing(serverName); const statusIconProps = getServerStatusIconProps(serverName); const configDialogProps = getConfigDialogProps(); const statusIcon = statusIconProps && (
{ e.stopPropagation(); }} className="cursor-pointer rounded p-0.5 hover:bg-surface-secondary" >
); return (
setIsHovering(true)} onMouseLeave={() => setIsHovering(false)} onFocus={() => setIsFocused(true)} onBlur={(e) => { if (!e.currentTarget.contains(e.relatedTarget)) { setIsFocused(false); } }} >
{ if ((e.target as HTMLElement).closest('[data-status-icon]')) { return; } if (!isServerInitializing) { initializeServer(serverName); } }} role="button" tabIndex={0} onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); if (!isServerInitializing) { initializeServer(serverName); } } }} aria-disabled={isServerInitializing} > {statusIcon && (
{statusIcon}
)} {serverInfo.metadata.icon && (
)}
{serverName} {isServerInitializing && ( {localize('com_ui_initializing')} )}
{localize('com_ui_delete_tool_confirm')} } selection={{ selectHandler: () => removeTool(serverName), selectClasses: 'bg-red-700 dark:bg-red-600 hover:bg-red-800 dark:hover:bg-red-800 transition-color duration-200 text-white', selectText: localize('com_ui_delete'), }} /> {configDialogProps && } ); }