| import React from 'react'; |
| import { KeyRound, PlugZap, AlertTriangle } from 'lucide-react'; |
| import { |
| Spinner, |
| OGDialog, |
| OGDialogTitle, |
| OGDialogHeader, |
| OGDialogContent, |
| } from '@librechat/client'; |
| import type { MCPServerStatus } from 'librechat-data-provider'; |
| import type { ConfigFieldDetail } from '~/common'; |
| import ServerInitializationSection from './ServerInitializationSection'; |
| import CustomUserVarsSection from './CustomUserVarsSection'; |
| import { useLocalize } from '~/hooks'; |
|
|
| interface MCPConfigDialogProps { |
| isOpen: boolean; |
| onOpenChange: (isOpen: boolean) => void; |
| fieldsSchema: Record<string, ConfigFieldDetail>; |
| initialValues: Record<string, string>; |
| onSave: (updatedValues: Record<string, string>) => void; |
| isSubmitting?: boolean; |
| onRevoke?: () => void; |
| serverName: string; |
| serverStatus?: MCPServerStatus; |
| conversationId?: string | null; |
| } |
|
|
| export default function MCPConfigDialog({ |
| isOpen, |
| onOpenChange, |
| fieldsSchema, |
| onSave, |
| isSubmitting = false, |
| onRevoke, |
| serverName, |
| serverStatus, |
| conversationId, |
| }: MCPConfigDialogProps) { |
| const localize = useLocalize(); |
|
|
| const hasFields = Object.keys(fieldsSchema).length > 0; |
| const dialogTitle = hasFields |
| ? localize('com_ui_configure_mcp_variables_for', { 0: serverName }) |
| : `${serverName} MCP Server`; |
|
|
| |
| const renderStatusBadge = () => { |
| if (!serverStatus) { |
| return null; |
| } |
|
|
| const { connectionState, requiresOAuth } = serverStatus; |
|
|
| if (connectionState === 'connecting') { |
| return ( |
| <div className="flex items-center gap-2 rounded-full bg-blue-50 px-2 py-0.5 text-xs font-medium text-blue-600 dark:bg-blue-950 dark:text-blue-400"> |
| <Spinner className="h-3 w-3" /> |
| <span>{localize('com_ui_connecting')}</span> |
| </div> |
| ); |
| } |
|
|
| if (connectionState === 'disconnected') { |
| if (requiresOAuth) { |
| return ( |
| <div className="flex items-center gap-2 rounded-full bg-amber-50 px-2 py-0.5 text-xs font-medium text-amber-600 dark:bg-amber-950 dark:text-amber-400"> |
| <KeyRound className="h-3 w-3" /> |
| <span>{localize('com_ui_oauth')}</span> |
| </div> |
| ); |
| } else { |
| return ( |
| <div className="flex items-center gap-2 rounded-full bg-orange-50 px-2 py-0.5 text-xs font-medium text-orange-600 dark:bg-orange-950 dark:text-orange-400"> |
| <PlugZap className="h-3 w-3" /> |
| <span>{localize('com_ui_offline')}</span> |
| </div> |
| ); |
| } |
| } |
|
|
| if (connectionState === 'error') { |
| return ( |
| <div className="flex items-center gap-2 rounded-full bg-red-50 px-2 py-0.5 text-xs font-medium text-red-600 dark:bg-red-950 dark:text-red-400"> |
| <AlertTriangle className="h-3 w-3" /> |
| <span>{localize('com_ui_error')}</span> |
| </div> |
| ); |
| } |
|
|
| if (connectionState === 'connected') { |
| return ( |
| <div className="flex items-center gap-2 rounded-full bg-green-100 px-2 py-0.5 text-xs font-medium text-green-700 dark:bg-green-900 dark:text-green-300"> |
| <div className="h-1.5 w-1.5 rounded-full bg-green-500" /> |
| <span>{localize('com_ui_active')}</span> |
| </div> |
| ); |
| } |
|
|
| return null; |
| }; |
|
|
| return ( |
| <OGDialog open={isOpen} onOpenChange={onOpenChange}> |
| <OGDialogContent className="flex max-h-screen w-11/12 max-w-lg flex-col space-y-2"> |
| <OGDialogHeader> |
| <div className="flex items-center gap-3"> |
| <OGDialogTitle className="text-xl"> |
| {dialogTitle.charAt(0).toUpperCase() + dialogTitle.slice(1)} |
| </OGDialogTitle> |
| {renderStatusBadge()} |
| </div> |
| </OGDialogHeader> |
| |
| {/* Custom User Variables Section */} |
| <CustomUserVarsSection |
| serverName={serverName} |
| fields={fieldsSchema} |
| onSave={onSave} |
| onRevoke={onRevoke || (() => {})} |
| isSubmitting={isSubmitting} |
| /> |
| |
| {/* Server Initialization Section */} |
| <ServerInitializationSection |
| serverName={serverName} |
| conversationId={conversationId} |
| requiresOAuth={serverStatus?.requiresOAuth || false} |
| hasCustomUserVars={fieldsSchema && Object.keys(fieldsSchema).length > 0} |
| /> |
| </OGDialogContent> |
| </OGDialog> |
| ); |
| } |
|
|