"use client"; import { useState, useEffect } from "react"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog"; import { Button } from "@/components/ui/button"; import { ScrollArea } from "@/components/ui/scroll-area"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { Switch } from "@/components/ui/switch"; import { Save, Settings, Search, Database, GitBranch, MessageSquare, AlertTriangle } from "lucide-react"; import { CredentialProfileSelector } from "./CredentialProfileSelector"; import { type CredentialProfile } from "@/hooks/react-query/mcp/use-credential-profiles"; interface MCPServer { id: string; name: string; description: string; icon: any; qualifiedName: string; configSchema: { properties: Record; required: string[]; }; tools: Array<{ name: string; description: string; }>; } interface MCPConfiguration { id: string; name: string; qualifiedName: string; profileId?: string; // NEW: Reference to credential profile config: Record; enabledTools: string[]; isConfigured: boolean; } interface MCPConfigurationDialogProps { open: boolean; onOpenChange: (open: boolean) => void; onSave: (configurations: MCPConfiguration[], profileMappings: Record) => void; existingConfigurations?: MCPConfiguration[]; existingProfileMappings?: Record; } // Updated mock MCP servers with qualified names const mockMCPServers: MCPServer[] = [ { id: "exa", name: "Exa Search", description: "Advanced web search with AI-powered results", icon: Search, qualifiedName: "exa", configSchema: { properties: { exaApiKey: { type: "string", title: "Exa API Key", description: "Your Exa API key for search functionality", format: "password" } }, required: ["exaApiKey"] }, tools: [ { name: "web_search_exa", description: "Search the web with Exa" }, { name: "find_similar", description: "Find similar content" } ] }, { id: "github", name: "GitHub", description: "Access GitHub repositories, issues, and pull requests", icon: GitBranch, qualifiedName: "github", configSchema: { properties: { githubToken: { type: "string", title: "GitHub Token", description: "Personal access token for GitHub API", format: "password" }, defaultOwner: { type: "string", title: "Default Owner", description: "Default repository owner/organization" } }, required: ["githubToken"] }, tools: [ { name: "list_repositories", description: "List repositories" }, { name: "get_repository", description: "Get repository details" }, { name: "create_issue", description: "Create a new issue" }, { name: "list_issues", description: "List repository issues" } ] }, { id: "slack", name: "Slack", description: "Send messages and interact with Slack workspaces", icon: MessageSquare, qualifiedName: "@smithery-ai/slack", configSchema: { properties: { slackBotToken: { type: "string", title: "Slack Bot Token", description: "Bot token for Slack API (starts with xoxb-)", format: "password" }, defaultChannel: { type: "string", title: "Default Channel", description: "Default channel for messages (e.g., #general)" } }, required: ["slackBotToken"] }, tools: [ { name: "slack_post_message", description: "Send a message to a channel" }, { name: "slack_list_channels", description: "List available channels" }, { name: "slack_get_channel_history", description: "Get channel message history" } ] }, { id: "postgres", name: "PostgreSQL", description: "Execute SQL queries and manage PostgreSQL databases", icon: Database, qualifiedName: "postgres", configSchema: { properties: { host: { type: "string", title: "Host", description: "PostgreSQL server host" }, port: { type: "string", title: "Port", description: "PostgreSQL server port (default: 5432)" }, database: { type: "string", title: "Database", description: "Database name" }, username: { type: "string", title: "Username", description: "Database username" }, password: { type: "string", title: "Password", description: "Database password", format: "password" } }, required: ["host", "database", "username", "password"] }, tools: [ { name: "execute_query", description: "Execute SQL query" }, { name: "list_tables", description: "List database tables" }, { name: "describe_table", description: "Get table schema" } ] } ]; export default function MCPConfigurationDialog({ open, onOpenChange, onSave, existingConfigurations = [], existingProfileMappings = {} }: MCPConfigurationDialogProps) { const [configurations, setConfigurations] = useState(existingConfigurations); const [profileMappings, setProfileMappings] = useState>(existingProfileMappings); const [selectedServer, setSelectedServer] = useState(null); const [selectedProfile, setSelectedProfile] = useState(null); const [enabledTools, setEnabledTools] = useState>(new Set()); const [activeTab, setActiveTab] = useState("browse"); useEffect(() => { setConfigurations(existingConfigurations); setProfileMappings(existingProfileMappings); }, [existingConfigurations, existingProfileMappings]); const handleServerSelect = (server: MCPServer) => { setSelectedServer(server); // Load existing configuration if available const existingConfig = configurations.find(c => c.id === server.id); if (existingConfig) { setEnabledTools(new Set(existingConfig.enabledTools)); // selectedProfile will be set by CredentialProfileSelector } else { setEnabledTools(new Set(server.tools.map(t => t.name))); // Enable all tools by default setSelectedProfile(null); } setActiveTab("configure"); }; const handleProfileSelect = (profileId: string | null, profile: CredentialProfile | null) => { setSelectedProfile(profile); if (selectedServer && profileId) { // Update profile mapping setProfileMappings(prev => ({ ...prev, [selectedServer.qualifiedName]: profileId })); } }; const handleConfigSave = () => { if (!selectedServer || !selectedProfile) return; const newConfig: MCPConfiguration = { id: selectedServer.id, name: selectedServer.name, qualifiedName: selectedServer.qualifiedName, profileId: selectedProfile.profile_id, config: {}, // Config is now managed by credential profiles enabledTools: Array.from(enabledTools), isConfigured: true }; const updatedConfigurations = configurations.filter(c => c.id !== selectedServer.id); updatedConfigurations.push(newConfig); setConfigurations(updatedConfigurations); setSelectedServer(null); setSelectedProfile(null); setActiveTab("browse"); }; const handleRemoveConfiguration = (id: string) => { const config = configurations.find(c => c.id === id); if (config) { // Remove from profile mappings const { [config.qualifiedName]: removed, ...remainingMappings } = profileMappings; setProfileMappings(remainingMappings); } setConfigurations(configurations.filter(c => c.id !== id)); }; const handleSaveAll = () => { onSave(configurations, profileMappings); onOpenChange(false); }; const isConfigValid = () => { return selectedServer && selectedProfile && enabledTools.size > 0; }; return ( Configure MCP Servers Set up Model Context Protocol servers for your workflow using credential profiles Browse Servers Configure Configured ({configurations.length})
{mockMCPServers.map((server) => { const isConfigured = configurations.some(c => c.id === server.id); return ( handleServerSelect(server)} >
{server.name} {server.description}
{isConfigured && ( Configured )}
{server.tools.length} tools available
); })}
{selectedServer && (

{selectedServer.name}

{selectedServer.description}

Credential Profile Select or create a credential profile for this MCP server
Available Tools Select which tools to enable for this server
{selectedServer.tools.map((tool) => (
{ const newTools = new Set(enabledTools); if (checked) { newTools.add(tool.name); } else { newTools.delete(tool.name); } setEnabledTools(newTools); }} />
{tool.name}
{tool.description}
))}
)}
{configurations.length === 0 ? (

No MCP Servers Configured

Configure MCP servers to use them in your workflows

) : (
{configurations.map((config) => { const server = mockMCPServers.find(s => s.id === config.id); if (!server) return null; const profileId = profileMappings[config.qualifiedName]; const hasValidProfile = !!profileId; return (
{config.name} {!hasValidProfile && ( )} {config.enabledTools.length} tools enabled {profileId && ( • Profile: {profileId.slice(0, 8)}... )}
{config.enabledTools.map((tool) => ( {tool} ))}
{!hasValidProfile && (
No credential profile selected. Please configure credentials.
)}
); })}
)}
); }