From 78942c2778c0eeb00064894cb6e6695e2e5d6ff9 Mon Sep 17 00:00:00 2001 From: zgaetano Date: Tue, 31 Mar 2026 15:33:28 -0400 Subject: [PATCH] Add dashboard/Dashboard.jsx --- dashboard/Dashboard.jsx | 206 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 206 insertions(+) create mode 100644 dashboard/Dashboard.jsx diff --git a/dashboard/Dashboard.jsx b/dashboard/Dashboard.jsx new file mode 100644 index 0000000..41c660c --- /dev/null +++ b/dashboard/Dashboard.jsx @@ -0,0 +1,206 @@ +import React, { useState, useEffect } from 'react'; +import { RotateCcw, CheckCircle, AlertCircle, Clock, Zap } from 'lucide-react'; + +export default function Dashboard() { + const [services, setServices] = useState([]); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + const [lastUpdated, setLastUpdated] = useState(null); + + const fetchServiceStatus = async () => { + try { + setLoading(true); + setError(null); + const response = await fetch('/mcp/status'); + + if (!response.ok) { + throw new Error('Failed to fetch service status'); + } + + const data = await response.json(); + setServices(data.services || []); + setLastUpdated(new Date()); + } catch (err) { + console.error('Error fetching status:', err); + setError(err.message); + } finally { + setLoading(false); + } + }; + + useEffect(() => { + fetchServiceStatus(); + // Auto-refresh every 30 seconds + const interval = setInterval(fetchServiceStatus, 30000); + return () => clearInterval(interval); + }, []); + + const getStatusIcon = (status) => { + if (status === 'healthy') { + return ; + } else if (status === 'warning') { + return ; + } else { + return ; + } + }; + + const getStatusBgColor = (status) => { + if (status === 'healthy') return 'bg-green-50 border-green-200'; + if (status === 'warning') return 'bg-yellow-50 border-yellow-200'; + return 'bg-red-50 border-red-200'; + }; + + const getStatusTextColor = (status) => { + if (status === 'healthy') return 'text-green-700'; + if (status === 'warning') return 'text-yellow-700'; + return 'text-red-700'; + }; + + const totalTools = services.reduce((sum, service) => sum + (service.toolCount || 0), 0); + + return ( +
+
+ {/* Header */} +
+
+

MCP Gateway Dashboard

+

Real-time status and monitoring of all MCP services

+
+ +
+ + {/* Summary Stats */} +
+
+
+
+

Total Services

+

{services.length}

+
+ +
+
+ +
+
+
+

Total Tools

+

{totalTools}

+
+ +
+
+ +
+
+
+

Healthy Services

+

+ {services.filter(s => s.status === 'healthy').length} +

+
+ +
+
+
+ + {/* Last Updated */} + {lastUpdated && ( +
+ + Last updated: {lastUpdated.toLocaleTimeString()} +
+ )} + + {/* Error State */} + {error && ( +
+

Error loading service status

+

{error}

+
+ )} + + {/* Services Grid */} +
+ {services.map((service) => ( +
+ {/* Service Header */} +
+
+

+ {service.name} +

+

+ {service.status.charAt(0).toUpperCase() + service.status.slice(1)} +

+
+ {getStatusIcon(service.status)} +
+ + {/* Service Details */} +
+ {/* Tool Count */} +
+ Tools Available + {service.toolCount || 0} +
+ + {/* Response Time */} + {service.responseTime !== undefined && ( +
+ Response Time + + {service.responseTime}ms + +
+ )} + + {/* URL */} +
+

Service URL

+

{service.url}

+
+ + {/* Last Check */} + {service.lastCheck && ( +
+ Last health check: {new Date(service.lastCheck).toLocaleTimeString()} +
+ )} +
+
+ ))} +
+ + {/* Empty State */} + {!loading && services.length === 0 && !error && ( +
+

No services available yet. Check your configuration.

+
+ )} + + {/* Loading State */} + {loading && services.length === 0 && ( +
+
+
+
+

Loading service status...

+
+ )} +
+
+ ); +}