import React, { useState, useEffect } from 'react'; import { Server, Plus, Play, CheckCircle2, XCircle, RefreshCw, Trash2, Edit, Power, Globe, Code2, Webhook, Cpu, Download, Upload, Search, Sparkles, ExternalLink, ChevronDown, ChevronUp, Sliders, Layers, Terminal, CloudSun, Coins, Newspaper, Database, Github, MessageSquare, FileCode, ShieldCheck, Zap, Compass, Copy, Check, Radio, Key, Repeat, } from 'lucide-react'; import { MCPServerDefinition, ToolDefinition, ServerStats } from '../types'; import { RoadSignModal } from './RoadSignModal'; import { PackageRunnerModal } from './PackageRunnerModal'; import { MCPSkillGuideModal } from './MCPSkillGuideModal'; interface MCPHubTabProps { stats: ServerStats | null; onRefreshStats?: () => void; onNavigateToStudio?: (prompt?: string) => void; } export const MCPHubTab: React.FC = ({ stats, onRefreshStats, onNavigateToStudio, }) => { const [servers, setServers] = useState([]); const [loading, setLoading] = useState(true); const [filterCategory, setFilterCategory] = useState('all'); const [filterType, setFilterType] = useState('all'); const [searchQuery, setSearchQuery] = useState(''); const [activeTab, setActiveTab] = useState<'servers' | 'road_signs' | 'marketplace'>('servers'); // Modal states const [isAddModalOpen, setIsAddModalOpen] = useState(false); const [isRoadSignModalOpen, setIsRoadSignModalOpen] = useState(false); const [editingRoadSignServer, setEditingRoadSignServer] = useState(null); const [isPackageRunnerModalOpen, setIsPackageRunnerModalOpen] = useState(false); const [isSkillGuideModalOpen, setIsSkillGuideModalOpen] = useState(false); const [isImportModalOpen, setIsImportModalOpen] = useState(false); const [importJsonText, setImportJsonText] = useState(''); const [pingingServerId, setPingingServerId] = useState(null); const [expandedServerId, setExpandedServerId] = useState('builtin-mcp-core'); const [copiedConnectSnippet, setCopiedConnectSnippet] = useState(null); // New server form state const [newServerType, setNewServerType] = useState<'remote_http' | 'webhook' | 'custom_script'>('remote_http'); const [formName, setFormName] = useState(''); const [formDescription, setFormDescription] = useState(''); const [formCategory, setFormCategory] = useState('custom'); // Remote HTTP fields const [formEndpointUrl, setFormEndpointUrl] = useState(''); const [formHeadersText, setFormHeadersText] = useState('{\n "Authorization": "Bearer MY_API_TOKEN"\n}'); // Webhook fields const [formWebhookUrl, setFormWebhookUrl] = useState('https://api.example.com/v1/resource?id={{id}}'); const [formWebhookMethod, setFormWebhookMethod] = useState<'GET' | 'POST' | 'PUT'>('GET'); const [formWebhookBody, setFormWebhookBody] = useState('{\n "message": "{{message}}"\n}'); // Custom Script fields const [formToolName, setFormToolName] = useState('my_custom_tool'); const [formToolDesc, setFormToolDesc] = useState('Executes custom calculation or data processing logic.'); const [formCustomScript, setFormCustomScript] = useState(`// Available arguments in 'args' object (e.g. args.text, args.number)\nconst text = args.text || '';\nreturn {\n status: 'processed',\n length: text.length,\n uppercase: text.toUpperCase(),\n timestamp: new Date().toISOString()\n};`); const [formSchemaJson, setFormSchemaJson] = useState(`{\n "type": "object",\n "properties": {\n "text": { "type": "string", "description": "Input text to process" }\n },\n "required": ["text"]\n}`); // Test execution state const [testTool, setTestTool] = useState<{ name: string; schema: any } | null>(null); const [testArgsJson, setTestArgsJson] = useState('{}'); const [testResult, setTestResult] = useState(null); const [isExecuting, setIsExecuting] = useState(false); const fetchServers = async () => { try { setLoading(true); const res = await fetch('/api/v1/mcp/servers'); if (res.ok) { const data = await res.json(); setServers(data); } } catch (err) { console.error('Failed to fetch MCP servers:', err); } finally { setLoading(false); } }; useEffect(() => { fetchServers(); }, []); const handleToggleServer = async (id: string, currentEnabled: boolean) => { try { const res = await fetch(`/api/v1/mcp/servers/${id}/toggle`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ enabled: !currentEnabled }), }); if (res.ok) { fetchServers(); if (onRefreshStats) onRefreshStats(); } } catch (err) { console.error('Failed to toggle server:', err); } }; const handlePingServer = async (id: string) => { setPingingServerId(id); try { const res = await fetch(`/api/v1/mcp/servers/${id}/ping`, { method: 'POST' }); if (res.ok) { const pingResult = await res.json(); setServers((prev) => prev.map((s) => s.id === id ? { ...s, healthStatus: pingResult.success ? 'healthy' : 'unreachable', lastPingMs: pingResult.latencyMs, lastPingAt: new Date().toISOString(), } : s ) ); } } catch (err) { console.error('Failed to ping server:', err); } finally { setPingingServerId(null); } }; const handleDeleteServer = async (id: string) => { if (!confirm('Are you sure you want to remove this MCP server registration?')) return; try { const res = await fetch(`/api/v1/mcp/servers/${id}`, { method: 'DELETE' }); if (res.ok) { fetchServers(); if (onRefreshStats) onRefreshStats(); } else { const err = await res.json(); alert(err.error || 'Failed to delete server'); } } catch (err) { console.error('Failed to delete server:', err); } }; const handleSaveRoadSign = async (roadSignServer: Partial) => { const isUpdate = Boolean(roadSignServer.id && servers.some((s) => s.id === roadSignServer.id)); const url = isUpdate ? `/api/v1/mcp/servers/${roadSignServer.id}` : '/api/v1/mcp/servers'; const method = isUpdate ? 'PUT' : 'POST'; const res = await fetch(url, { method, headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(roadSignServer), }); if (!res.ok) { const err = await res.json(); throw new Error(err.error || 'Failed to save Road Sign server'); } await fetchServers(); if (onRefreshStats) onRefreshStats(); }; const handleCreateServer = async (e: React.FormEvent) => { e.preventDefault(); try { let parsedSchema = { type: 'object', properties: {} }; try { parsedSchema = JSON.parse(formSchemaJson); } catch (err) { alert('Invalid Input Schema JSON formatting.'); return; } let parsedHeaders = undefined; if (newServerType === 'remote_http' && formHeadersText.trim()) { try { parsedHeaders = JSON.parse(formHeadersText); } catch (err) { alert('Invalid Headers JSON format.'); return; } } const tools: ToolDefinition[] = []; if (newServerType === 'custom_script') { tools.push({ name: formToolName.trim().replace(/\s+/g, '_').toLowerCase(), description: formToolDesc, category: formCategory, inputSchema: parsedSchema as any, }); } else if (newServerType === 'webhook') { tools.push({ name: formName.trim().replace(/\s+/g, '_').toLowerCase() + '_tool', description: formDescription, category: formCategory, inputSchema: parsedSchema as any, }); } const payload: Partial = { name: formName, description: formDescription, type: newServerType, category: formCategory, enabled: true, endpointUrl: newServerType === 'remote_http' ? formEndpointUrl : undefined, headers: parsedHeaders, webhookConfig: newServerType === 'webhook' ? { url: formWebhookUrl, method: formWebhookMethod, bodyTemplate: formWebhookMethod !== 'GET' ? formWebhookBody : undefined, } : undefined, customScript: newServerType === 'custom_script' ? formCustomScript : undefined, tools, }; const res = await fetch('/api/v1/mcp/servers', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload), }); if (res.ok) { setIsAddModalOpen(false); setFormName(''); setFormDescription(''); fetchServers(); if (onRefreshStats) onRefreshStats(); } else { const err = await res.json(); alert(err.error || 'Failed to create MCP server'); } } catch (err: any) { alert('Error creating server: ' + err.message); } }; const handleInstallPreset = async (preset: { name: string; description: string; type: 'webhook' | 'custom_script' | 'remote_http'; category: MCPServerDefinition['category']; webhookConfig?: any; customScript?: string; tools: ToolDefinition[]; icon?: string; }) => { try { const res = await fetch('/api/v1/mcp/servers', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ ...preset, enabled: true, isPreset: true, }), }); if (res.ok) { fetchServers(); setActiveTab('servers'); if (onRefreshStats) onRefreshStats(); } else { alert('Failed to install preset MCP server'); } } catch (err) { console.error('Error installing preset:', err); } }; const handleImportJson = async () => { try { const parsed = JSON.parse(importJsonText); const serversArray = Array.isArray(parsed) ? parsed : parsed.servers; if (!Array.isArray(serversArray)) { alert('Invalid format. Expected JSON array or { "servers": [...] } object.'); return; } const res = await fetch('/api/v1/mcp/servers/import', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ servers: serversArray }), }); if (res.ok) { const data = await res.json(); alert(`Successfully imported ${data.importedCount} MCP servers!`); setIsImportModalOpen(false); setImportJsonText(''); fetchServers(); if (onRefreshStats) onRefreshStats(); } } catch (err: any) { alert('Failed to parse or import JSON: ' + err.message); } }; const handleExportJson = () => { const jsonStr = JSON.stringify({ servers }, null, 2); const blob = new Blob([jsonStr], { type: 'application/json' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `mcp-nexus-registry-${new Date().toISOString().slice(0, 10)}.json`; a.click(); URL.revokeObjectURL(url); }; const handleCopySnippet = (id: string, text: string) => { navigator.clipboard.writeText(text); setCopiedConnectSnippet(id); setTimeout(() => setCopiedConnectSnippet(null), 2000); }; const handleTestExecute = async () => { if (!testTool) return; setIsExecuting(true); setTestResult(null); try { let argsObj = {}; try { argsObj = JSON.parse(testArgsJson); } catch (e) { alert('Invalid args JSON format'); setIsExecuting(false); return; } const res = await fetch(`/api/v1/tools/${testTool.name}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(argsObj), }); const data = await res.json(); setTestResult(data); } catch (err: any) { setTestResult({ success: false, error: err.message }); } finally { setIsExecuting(false); } }; // Filter servers const roadSignServers = servers.filter((s) => s.roadSign?.isRoadSign); const filteredServers = servers.filter((s) => { const matchesSearch = s.name.toLowerCase().includes(searchQuery.toLowerCase()) || s.description.toLowerCase().includes(searchQuery.toLowerCase()) || s.roadSign?.signpostTitle?.toLowerCase().includes(searchQuery.toLowerCase()) || s.tools?.some((t) => t.name.toLowerCase().includes(searchQuery.toLowerCase())); const matchesCategory = filterCategory === 'all' || s.category === filterCategory; const matchesType = filterType === 'all' || s.type === filterType; return matchesSearch && matchesCategory && matchesType; }); const getTypeBadge = (server: MCPServerDefinition) => { if (server.roadSign?.isRoadSign) { return ( Road Sign ({server.roadSign.osPlatform}) ); } switch (server.type) { case 'builtin': return ( Built-in Engine ); case 'runner_process': return ( Runner ({server.runnerConfig?.packageManager || 'cli'}) ); case 'remote_http': return ( Remote HTTP ); case 'webhook': return ( Webhook Bridge ); case 'custom_script': return ( JS Executable ); } }; const getIconComponent = (iconName?: string, osPlatform?: string) => { if (osPlatform === 'windows') return 🪟; if (osPlatform === 'macos') return 🍎; if (osPlatform === 'linux') return 🐧; if (osPlatform === 'docker') return 🐳; switch (iconName) { case 'Compass': return ; case 'Terminal': return ; case 'Layers': return ; case 'CloudSun': return ; case 'Coins': return ; case 'Newspaper': return ; case 'Code2': return ; case 'Github': return ; case 'MessageSquare': return ; case 'Database': return ; case 'Zap': return ; default: return ; } }; const originUrl = typeof window !== 'undefined' ? window.location.origin : 'http://localhost:3000'; const sseUrl = `${originUrl}/mcp/sse`; const autoSetupUrl = `${originUrl}/api/v1/agent/auto-setup`; const claudeConfigSnippet = JSON.stringify( { mcpServers: { 'do-everything-nexus': { url: sseUrl, }, }, }, null, 2 ); // Preset Catalog Items const presetCatalog: Array<{ name: string; description: string; type: 'remote_http' | 'custom_script' | 'webhook'; category: MCPServerDefinition['category']; icon?: string; webhookConfig?: any; customScript?: string; tools: ToolDefinition[]; }> = [ { name: 'GitHub API & Code Repository MCP', description: 'Search repositories, inspect commits, view user profiles, and fetch file contents directly from GitHub REST API.', type: 'webhook', category: 'code', icon: 'Github', webhookConfig: { url: 'https://api.github.com/repos/{{owner}}/{{repo}}/contents/{{path}}', method: 'GET', headers: { 'User-Agent': 'DoEverythingMCP' }, }, tools: [ { name: 'get_github_repo_file', description: 'Fetch file content or directory listing from a public GitHub repository.', category: 'code', inputSchema: { type: 'object', properties: { owner: { type: 'string', description: 'Repository owner or organization name (e.g., facebook)' }, repo: { type: 'string', description: 'Repository name (e.g., react)' }, path: { type: 'string', description: 'File path within repo (e.g., package.json)' }, }, required: ['owner', 'repo', 'path'], }, }, ], }, { name: 'Slack Notification Webhook MCP', description: 'Bridge Slack incoming webhooks to enable connected AI agents to dispatch notifications to team channels.', type: 'webhook', category: 'network', icon: 'MessageSquare', webhookConfig: { url: 'https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK', method: 'POST', bodyTemplate: '{\n "text": "🤖 *AI Agent Notification*:\\n{{message}}"\n}', }, tools: [ { name: 'send_slack_webhook_message', description: 'Dispatch a formatted text message to team Slack channel via Webhook bridge.', category: 'network', inputSchema: { type: 'object', properties: { message: { type: 'string', description: 'Text message to post to Slack' }, }, required: ['message'], }, }, ], }, { name: 'PostgreSQL Relational DB Query Bridge MCP', description: 'Allows agents to execute query logic against SQL database connectors or REST database proxies.', type: 'custom_script', category: 'data', icon: 'Database', customScript: ` // Custom script proxy simulating SQL query parser const sql = args.sql || ''; return { query: sql, rows: [ { id: 1, name: "Sample Record A", status: "active", created_at: "2026-08-12" }, { id: 2, name: "Sample Record B", status: "pending", created_at: "2026-08-11" } ], rowCount: 2, executionTimeMs: 12 }; `, tools: [ { name: 'execute_sql_query_proxy', description: 'Execute read-only SQL queries or table metadata inspections.', category: 'data', inputSchema: { type: 'object', properties: { sql: { type: 'string', description: 'SQL query statement (SELECT ...)' }, }, required: ['sql'], }, }, ], }, { name: 'Text Sentiment & Keyword Extractor MCP', description: 'Standalone JavaScript script tool for fast client/server text analysis and keyphrase extraction.', type: 'custom_script', category: 'code', icon: 'Zap', customScript: ` const text = args.text || ''; const words = text.toLowerCase().match(/\\b[a-z]{4,}\\b/g) || []; const freq = {}; words.forEach(w => freq[w] = (freq[w] || 0) + 1); const topKeywords = Object.entries(freq).sort((a,b) => b[1] - a[1]).slice(0, 5).map(e => e[0]); return { textLength: text.length, wordCount: text.split(/\\s+/).length, topKeywords, sentiment: text.includes('great') || text.includes('awesome') || text.includes('good') ? 'positive' : 'neutral' }; `, tools: [ { name: 'extract_text_keywords_mcp', description: 'Extract top keywords and estimate text sentiment.', category: 'code', inputSchema: { type: 'object', properties: { text: { type: 'string', description: 'Text string to analyze' }, }, required: ['text'], }, }, ], }, ]; return (
{/* Hero Header Banner with Central Source of Truth Metaphor */}
Universal MCP Nexus & Central Source of Truth

MCP Hub, Road Signs & Router Nexus

Install any MCP server via browser runners (bunx, npx, uvx, python). Point any AI model at the persistent SSE stream to gain instant access to all 27+ zero-key algorithmic tools, remote machine Road Signs, and intelligent workflows.

{/* Live SSE Stream & Auto-Setup Connect Bar */}
Live Model SSE Source of Truth Endpoint
{sseUrl}
Auto-Setup API
{/* Quick Hub Metrics Row */}
Total MCP Servers {servers.length}
Road Signs (Remote) {roadSignServers.length}
Live Aggregated Tools {servers.reduce((acc, s) => (s.enabled ? acc + (s.tools?.length || 0) : acc), 0)}
Router Latency {stats?.avgLatencyMs || 0}ms
{/* Navigation Filter Tabs */}
{activeTab !== 'marketplace' && (
setSearchQuery(e.target.value)} placeholder="Search servers, tools, road signs..." className="w-full pl-9 pr-3 py-1.5 text-xs sm:text-sm bg-white border border-slate-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500" />
)}
{/* Tab View: Road Signs Dedicated Signposts View */} {activeTab === 'road_signs' && (
Road Signs Metaphor & Remote Host Credentials

"LOOK HERE" Signposts for Remote Machines

Erect signposts on your Nexus pointing models to remote Windows, macOS, Linux, or GPU hosts. Inject API keys and credentials seamlessly on every tool call.

{roadSignServers.map((server) => (
{/* Highway Sign Header */}
{server.roadSign?.osPlatform === 'windows' ? '🪟' : server.roadSign?.osPlatform === 'macos' ? '🍎' : '🐧'}
ROAD SIGN • {server.roadSign?.osPlatform?.toUpperCase()}

{server.roadSign?.signpostTitle || server.name}

{server.lastPingMs !== undefined ? `${server.lastPingMs}ms` : 'Healthy'}
Host: {server.roadSign?.targetHostLocation || server.endpointUrl} MCP JSON-RPC

{server.roadSign?.directionsInstructions || server.description}

{/* Credentials & API Keys configured */}
Injected Auth Headers ({Object.keys(server.roadSign?.credentialKeys || {}).length}) Auto-Injected
{Object.keys(server.roadSign?.credentialKeys || {}).map((headerKey) => ( {headerKey}: •••••••• ))}
{/* Tools exposed */}
Remote Tools Exposed
{server.tools?.map((tool) => ( {tool.name} ))}
{/* Actions */}
))}
)} {/* Tab View: Installed Servers */} {activeTab === 'servers' && (
{loading ? (

Loading registered MCP servers...

) : filteredServers.length === 0 ? (

No MCP Servers Found

No registered MCP servers matched your search criteria. Add a custom MCP server or browse the preset marketplace catalog!

) : ( filteredServers.map((server) => { const isExpanded = expandedServerId === server.id; return (
{getIconComponent(server.icon, server.roadSign?.osPlatform)}

{server.roadSign?.signpostTitle || server.name}

{getTypeBadge(server)} {server.enabled ? ( Active ) : ( Disabled )}

{server.description}

{server.tools?.length || 0} Tools Exposed Ping:{' '} {server.lastPingMs !== undefined ? `${server.lastPingMs}ms` : 'Not tested'}
{!server.isPreset && ( )}
{/* Expanded Tools Details */} {isExpanded && (
{server.type === 'remote_http' && server.endpointUrl && (
Endpoint: {server.endpointUrl} JSON-RPC / SSE
)}

Exposed MCP Tools ({server.tools?.length || 0})

{server.tools?.map((tool) => (
{tool.name}

{tool.description}

))}
)}
); }) )}
)} {/* Tab View: Marketplace Catalog */} {activeTab === 'marketplace' && (
Ready-to-Install MCP Server Templates

Click "1-Click Install" on any template to instantly add its tools to your server hub registry.

{presetCatalog.map((preset) => (
{getIconComponent(preset.icon)}
{getTypeBadge(preset as any)}

{preset.name}

{preset.description}

Tools Provided {preset.tools.map((t) => ( {t.name} ))}
))}
)} {/* ROAD SIGN MODAL */} setIsRoadSignModalOpen(false)} onSaveRoadSign={handleSaveRoadSign} existingServer={editingRoadSignServer} /> {/* PACKAGE RUNNER MODAL */} setIsPackageRunnerModalOpen(false)} onInstalled={() => { fetchServers(); if (onRefreshStats) onRefreshStats(); }} /> {/* MCP SKILL GUIDE MODAL */} setIsSkillGuideModalOpen(false)} onSendToStudio={(p) => { if (onNavigateToStudio) onNavigateToStudio(p); }} /> {/* MODAL: Add New MCP Server */} {isAddModalOpen && (

Register New MCP Server or Tool

Configure remote HTTP JSON-RPC servers, webhook bridges, or custom JS tools.

{/* Type Selection */}
{/* Common Fields */}
setFormName(e.target.value)} placeholder="e.g. Weather Service MCP" className="w-full px-3 py-2 bg-slate-50 border border-slate-300 rounded-xl focus:outline-none focus:ring-2 focus:ring-indigo-500" />