"use client"; import React, { useState } from 'react'; import { Button } from '@/components/ui/button'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { Badge } from '@/components/ui/badge'; import { Card, CardContent } from '@/components/ui/card'; import { Label } from '@/components/ui/label'; import { Input } from '@/components/ui/input'; import { Alert, AlertDescription } from '@/components/ui/alert'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog'; import { Plus, Settings, Star, AlertCircle, Key, Shield, Loader2 } from 'lucide-react'; import { useCredentialProfilesForMcp, useSetDefaultProfile, useCreateCredentialProfile, type CredentialProfile, type CreateCredentialProfileRequest } from '@/hooks/react-query/mcp/use-credential-profiles'; import { useMCPServerDetails } from '@/hooks/react-query/mcp/use-mcp-servers'; import { toast } from 'sonner'; interface CredentialProfileSelectorProps { mcpQualifiedName: string; mcpDisplayName: string; selectedProfileId?: string; onProfileSelect: (profileId: string | null, profile: CredentialProfile | null) => void; disabled?: boolean; } interface InlineCreateProfileDialogProps { open: boolean; onOpenChange: (open: boolean) => void; mcpQualifiedName: string; mcpDisplayName: string; onSuccess: (profile: CredentialProfile) => void; } const InlineCreateProfileDialog: React.FC = ({ open, onOpenChange, mcpQualifiedName, mcpDisplayName, onSuccess }) => { const [formData, setFormData] = useState<{ profile_name: string; display_name: string; config: Record; is_default: boolean; }>({ profile_name: `${mcpDisplayName} Profile`, display_name: mcpDisplayName, config: {}, is_default: false }); const { data: serverDetails, isLoading: isLoadingDetails } = useMCPServerDetails(mcpQualifiedName); const createProfileMutation = useCreateCredentialProfile(); const getConfigProperties = () => { const schema = serverDetails?.connections?.[0]?.configSchema; return schema?.properties || {}; }; const getRequiredFields = () => { const schema = serverDetails?.connections?.[0]?.configSchema; return schema?.required || []; }; const isFieldRequired = (fieldName: string) => { return getRequiredFields().includes(fieldName); }; const handleConfigChange = (key: string, value: string) => { setFormData(prev => ({ ...prev, config: { ...prev.config, [key]: value } })); }; const handleSubmit = async () => { try { const request: CreateCredentialProfileRequest = { mcp_qualified_name: mcpQualifiedName, profile_name: formData.profile_name, display_name: formData.display_name, config: formData.config, is_default: formData.is_default }; const response = await createProfileMutation.mutateAsync(request); toast.success('Credential profile created successfully!'); // Create a profile object to return const newProfile: CredentialProfile = { profile_id: response.profile_id || 'new-profile', mcp_qualified_name: mcpQualifiedName, profile_name: formData.profile_name, display_name: formData.display_name, config_keys: Object.keys(formData.config), is_active: true, is_default: formData.is_default, last_used_at: null, created_at: new Date().toISOString(), updated_at: new Date().toISOString() }; onSuccess(newProfile); onOpenChange(false); // Reset form setFormData({ profile_name: `${mcpDisplayName} Profile`, display_name: mcpDisplayName, config: {}, is_default: false }); } catch (error: any) { toast.error(error.message || 'Failed to create credential profile'); } }; const configProperties = getConfigProperties(); const hasConfigFields = Object.keys(configProperties).length > 0; return ( Create Credential Profile Create a new credential profile for {mcpDisplayName} {isLoadingDetails ? (
Loading server configuration...
) : (
setFormData(prev => ({ ...prev, profile_name: e.target.value }))} placeholder="Enter a name for this profile" />

This helps you identify different configurations for the same MCP server

{hasConfigFields ? (

Connection Settings

{Object.entries(configProperties).map(([key, schema]: [string, any]) => (
handleConfigChange(key, e.target.value)} /> {schema.description && (

{schema.description}

)}
))}
) : ( This MCP server doesn't require any API credentials to use. )} Your credentials will be encrypted and stored securely. You can create multiple profiles for the same MCP server to handle different use cases.
)}
); }; export function CredentialProfileSelector({ mcpQualifiedName, mcpDisplayName, selectedProfileId, onProfileSelect, disabled = false }: CredentialProfileSelectorProps) { const [showCreateDialog, setShowCreateDialog] = useState(false); const { data: profiles = [], isLoading, error, refetch } = useCredentialProfilesForMcp(mcpQualifiedName); const setDefaultMutation = useSetDefaultProfile(); const selectedProfile = profiles.find(p => p.profile_id === selectedProfileId); const handleSetDefault = async (profileId: string) => { try { await setDefaultMutation.mutateAsync(profileId); } catch (error) { console.error('Failed to set default profile:', error); } }; const handleCreateNewProfile = () => { setShowCreateDialog(true); }; const handleCreateSuccess = (newProfile: CredentialProfile) => { // Refetch profiles to get the updated list refetch(); // Auto-select the newly created profile onProfileSelect(newProfile.profile_id, newProfile); toast.success(`Profile "${newProfile.profile_name}" created and selected!`); }; if (isLoading) { return (
); } if (error) { return (
Failed to load credential profiles
); } return ( <>
{/* */}
{profiles.length === 0 ? (

No credential profiles found for {mcpDisplayName}

) : (
{selectedProfile && (

{selectedProfile.profile_name}

{selectedProfile.is_default && ( Default )}

{selectedProfile.display_name}

{!selectedProfile.is_default && ( )}
)}
)}
); }