import React, { useState, useEffect } from 'react'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog'; import { Card } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; import { ScrollArea } from '@/components/ui/scroll-area'; import { Loader2, Search, Plus, Settings, ExternalLink, Shield, X, Sparkles, ChevronRight, ChevronLeft } from 'lucide-react'; import { usePopularMCPServers, usePopularMCPServersV2, useMCPServers, useMCPServerDetails } from '@/hooks/react-query/mcp/use-mcp-servers'; import { cn } from '@/lib/utils'; interface MCPConfiguration { name: string; qualifiedName: string; config: Record; enabledTools?: string[]; } interface MCPConfigurationProps { configuredMCPs: MCPConfiguration[]; onConfigurationChange: (mcps: MCPConfiguration[]) => void; } interface ConfigDialogProps { server: any; existingConfig?: MCPConfiguration; onSave: (config: MCPConfiguration) => void; onCancel: () => void; } const categoryIcons = { "AI & Search": "🤖", "Development & Version Control": "🔧", "Automation & Productivity": "⚡", "Communication & Collaboration": "💬", "Project Management": "📅", "Data & Analytics": "📊", "Cloud & Infrastructure": "☁️", "File Storage": "📁", "Marketing & Sales": "🛒", "Customer Support": "🎧", "Finance": "💰", "Utilities": "🔨", "Other": "🧩", // Legacy fallbacks "development": "🔧", "ai": "🤖", "automation": "⚡", "search": "🔍", "Database": "📊", "Web": "🌐", "File": "📄", "Development": "💻", "AI": "🤖", "Cloud": "☁️", "Utility": "⚡", "Integration": "🧩", }; const ConfigDialog: React.FC = ({ server, existingConfig, onSave, onCancel }) => { const [config, setConfig] = useState>(existingConfig?.config || {}); const [selectedTools, setSelectedTools] = useState>( new Set(existingConfig?.enabledTools || []) ); const { data: serverDetails, isLoading } = useMCPServerDetails(server.qualifiedName); const handleSave = () => { onSave({ name: server.displayName || server.name || server.qualifiedName, qualifiedName: server.qualifiedName, config, enabledTools: Array.from(selectedTools), }); }; const handleToolToggle = (toolName: string) => { const newTools = new Set(selectedTools); if (newTools.has(toolName)) { newTools.delete(toolName); } else { newTools.add(toolName); } setSelectedTools(newTools); }; return ( Configure {server.displayName || server.name} Set up the connection and select which tools to enable for this MCP server. {isLoading ? (
) : (
{serverDetails?.connections?.[0]?.configSchema?.properties && (

Connection Settings

{Object.entries(serverDetails.connections[0].configSchema.properties).map(([key, schema]: [string, any]) => (
setConfig({ ...config, [key]: e.target.value })} /> {schema.description && (

{schema.description}

)}
))}
)} {serverDetails?.tools && serverDetails.tools.length > 0 && (

Available Tools

{selectedTools.size} of {serverDetails.tools.length} selected
{serverDetails.tools.map((tool: any) => (
handleToolToggle(tool.name)} > {}} className="mt-1" />
{tool.name}
{tool.description && (
{tool.description}
)}
))}
)}
)}
); }; export const MCPConfiguration: React.FC = ({ configuredMCPs, onConfigurationChange, }) => { const [searchQuery, setSearchQuery] = useState(''); const [showBrowseDialog, setShowBrowseDialog] = useState(false); const [configuringServer, setConfiguringServer] = useState(null); const [editingIndex, setEditingIndex] = useState(null); const [selectedCategory, setSelectedCategory] = useState(null); const [currentPage, setCurrentPage] = useState(1); const [pageSize] = useState(200); const { data: popularServers } = usePopularMCPServers(); const { data: popularServersV2, isLoading: isLoadingV2 } = usePopularMCPServersV2(currentPage, pageSize); const { data: searchResults, isLoading: isSearching } = useMCPServers( searchQuery.length > 2 ? searchQuery : undefined ); const handleAddMCP = (server: any) => { setConfiguringServer(server); setEditingIndex(null); }; React.useEffect(() => { setCurrentPage(1); }, [searchQuery]); React.useEffect(() => { if (showBrowseDialog) { setCurrentPage(1); setSelectedCategory(null); } }, [showBrowseDialog]); const handleEditMCP = (index: number) => { const mcp = configuredMCPs[index]; setConfiguringServer({ qualifiedName: mcp.qualifiedName, displayName: mcp.name, name: mcp.name, }); setEditingIndex(index); }; const handleRemoveMCP = (index: number) => { const newMCPs = [...configuredMCPs]; newMCPs.splice(index, 1); onConfigurationChange(newMCPs); }; const handleSaveConfiguration = (config: MCPConfiguration) => { if (editingIndex !== null) { const newMCPs = [...configuredMCPs]; newMCPs[editingIndex] = config; onConfigurationChange(newMCPs); } else { onConfigurationChange([...configuredMCPs, config]); } setConfiguringServer(null); setEditingIndex(null); }; const getFilteredServers = () => { if (!popularServersV2?.success || !popularServersV2.categorized) return []; if (selectedCategory) { return popularServersV2.categorized[selectedCategory] || []; } // Return all servers from all categories return Object.values(popularServersV2.categorized).flat(); }; const categories = popularServersV2?.success ? Object.keys(popularServersV2.categorized) : []; return (

MCP Servers

Connect Model Context Protocol servers to extend agent capabilities

{/* Configured MCPs */} {configuredMCPs.length > 0 && (
{configuredMCPs.map((mcp, index) => (
{mcp.name}
{mcp.enabledTools?.length || 0} tools enabled
))}
)} {/* Browse MCP Servers Dialog */} Browse MCP Servers Discover and add Model Context Protocol servers from Smithery {/* Search */}
setSearchQuery(e.target.value)} className="pl-10" />
{!searchQuery && categories.length > 0 && (

Categories

{categories.map((category) => { const count = popularServersV2?.categorized[category]?.length || 0; return ( ); })}
)} {/* Main Content Area */}
{/* Search Results */} {searchQuery && (
{isSearching ? (
) : searchResults?.servers && searchResults.servers.length > 0 ? ( <>

Search Results ({searchResults.pagination.totalCount})

{searchResults.servers.map((server) => ( handleAddMCP(server)} >
{server.iconUrl ? ( {server.displayName} ) : (
)}

{server.displayName}

{server.security?.scanPassed && ( )} {server.isDeployed && ( Deployed )}

{server.description}

Used {server.useCount} times {server.homepage && ( )}
))}
) : (

No servers found

)}
)} {/* Categorized Servers */} {!searchQuery && ( <> {isLoadingV2 ? (
) : popularServersV2?.success ? (
{selectedCategory ? ( // Show single category
{categoryIcons[selectedCategory] || "🧩"}

{selectedCategory}

{popularServersV2.categorized[selectedCategory]?.length || 0} servers
{(popularServersV2.categorized[selectedCategory] || []).map((server) => ( handleAddMCP(server)} >
{server.iconUrl ? ( {server.name} ) : (
)}

{server.name}

{server.isDeployed && ( Deployed )}

{server.description}

Used {server.useCount} times {server.homepage && ( )}
))}
) : ( // Show all categories (overview) Object.entries(popularServersV2.categorized).map(([category, servers]) => (
{categoryIcons[category] || "🧩"}

{category}

{servers.length} servers
{servers.slice(0, 6).map((server) => ( handleAddMCP(server)} >
{server.iconUrl ? ( {server.name} ) : (
)}

{server.name}

{server.isDeployed && ( Deployed )}

{server.description}

Used {server.useCount} times
))}
)) )}
) : popularServers ? ( // Fallback to V1 simple list

Popular Servers

{popularServers.servers.map((server) => ( handleAddMCP(server)} >
{server.icon}

{server.displayName}

{server.description}

{server.category}
))}
) : null} )}
{!searchQuery && popularServersV2?.success && popularServersV2.pagination && (
Showing {((currentPage - 1) * pageSize) + 1} to {Math.min(currentPage * pageSize, popularServersV2.pagination.totalCount)} of {popularServersV2.pagination.totalCount} servers
Page {currentPage} of {popularServersV2.pagination.totalPages}
)}
{/* Configuration Dialog */} {configuringServer && ( setConfiguringServer(null)}> setConfiguringServer(null)} /> )}
); };