Skip to main content
Glama

ACE MCP Server

app.jsโ€ข9.81 kB
// ACE MCP Server Dashboard JavaScript class Dashboard { constructor() { this.startTime = Date.now(); this.init(); } init() { this.bindEvents(); this.updateStatus(); this.startPeriodicUpdates(); this.loadConfig(); this.addInitialLog('Dashboard initialized successfully', 'info'); } bindEvents() { const refreshBtn = document.getElementById('refresh-btn'); const testLLMBtn = document.getElementById('test-llm-btn'); if (refreshBtn) { refreshBtn.addEventListener('click', () => this.refresh()); } if (testLLMBtn) { testLLMBtn.addEventListener('click', () => this.testLLM()); } } async updateStatus() { try { // Simulate server status check const serverStatus = document.getElementById('server-status'); const dot = serverStatus.querySelector('.dot'); const text = serverStatus.querySelector('.text'); // Mock server check - in real implementation, this would be an API call const isOnline = await this.checkServerHealth(); if (isOnline) { dot.className = 'dot'; text.textContent = 'Online'; } else { dot.className = 'dot error'; text.textContent = 'Offline'; } this.addLog(`Server status: ${isOnline ? 'Online' : 'Offline'}`, isOnline ? 'info' : 'error'); } catch (error) { console.error('Failed to update status:', error); this.addLog('Failed to check server status', 'error'); } } async checkServerHealth() { try { const response = await fetch('/health'); if (response.ok) { const data = await response.json(); return data.status === 'healthy'; } return false; } catch (error) { console.error('Health check failed:', error); return false; } } async loadConfig() { try { const response = await fetch('/health'); if (response.ok) { const data = await response.json(); const config = { llmProvider: data.environment?.llmProvider || 'Unknown', logLevel: 'info', contextDir: data.environment?.contextDir || './contexts', contextCount: data.environment?.maxPlaybookSize || 'N/A', uptime: data.uptime || 0 }; this.updateConfigDisplay(config); } else { // Fallback to mock data if API fails this.loadMockConfig(); } } catch (error) { console.error('Failed to load config:', error); this.loadMockConfig(); } } loadMockConfig() { // Fallback mock configuration const config = { llmProvider: 'DeepSeek (Fallback)', logLevel: 'info', contextDir: './contexts', contextCount: 'Unknown' }; this.updateConfigDisplay(config); } detectLLMProvider() { // This will be set by loadConfig() from real API return 'Loading...'; } updateConfigDisplay(config) { const elements = { 'llm-provider': config.llmProvider, 'log-level': config.logLevel, 'context-dir': config.contextDir, 'context-count': config.contextCount.toString(), 'uptime': this.formatUptime() }; Object.entries(elements).forEach(([id, value]) => { const element = document.getElementById(id); if (element) { if (id === 'llm-provider') { element.querySelector('.provider-name').textContent = value; } else { element.textContent = value; } } }); } formatUptime() { const uptime = Date.now() - this.startTime; const seconds = Math.floor(uptime / 1000); const minutes = Math.floor(seconds / 60); const hours = Math.floor(minutes / 60); if (hours > 0) { return `${hours}h ${minutes % 60}m`; } else if (minutes > 0) { return `${minutes}m ${seconds % 60}s`; } else { return `${seconds}s`; } } async refresh() { this.addLog('Refreshing dashboard...', 'info'); const refreshBtn = document.getElementById('refresh-btn'); const originalText = refreshBtn.innerHTML; refreshBtn.innerHTML = '<span class="loading"></span> Refreshing...'; refreshBtn.disabled = true; try { await this.updateStatus(); this.loadConfig(); this.addLog('Dashboard refreshed successfully', 'info'); } catch (error) { this.addLog('Failed to refresh dashboard', 'error'); } finally { setTimeout(() => { refreshBtn.innerHTML = originalText; refreshBtn.disabled = false; }, 1000); } } async testLLM() { this.addLog('Testing LLM connection...', 'info'); const testBtn = document.getElementById('test-llm-btn'); const originalText = testBtn.innerHTML; testBtn.innerHTML = '<span class="loading"></span> Testing...'; testBtn.disabled = true; try { // Mock LLM test const success = await this.performLLMTest(); if (success) { this.addLog('LLM test successful - Connection OK', 'info'); } else { this.addLog('LLM test failed - Check configuration', 'error'); } } catch (error) { this.addLog('LLM test error: ' + error.message, 'error'); } finally { setTimeout(() => { testBtn.innerHTML = originalText; testBtn.disabled = false; }, 2000); } } async performLLMTest() { try { // Test with a simple API call to check if server responds const response = await fetch('/health'); if (response.ok) { const data = await response.json(); // If health check passes and we have LLM provider info, consider it successful return data.status === 'healthy' && data.environment?.llmProvider; } return false; } catch (error) { console.error('LLM test failed:', error); return false; } } addLog(message, level = 'info') { const logsContainer = document.getElementById('logs'); if (!logsContainer) return; const logEntry = document.createElement('div'); logEntry.className = 'log-entry'; const timestamp = new Date().toLocaleString(); logEntry.innerHTML = ` <span class="timestamp">${timestamp}</span> <span class="level ${level}">${level.toUpperCase()}</span> <span class="message">${message}</span> `; // Add to top of logs const firstChild = logsContainer.firstChild; if (firstChild) { logsContainer.insertBefore(logEntry, firstChild); } else { logsContainer.appendChild(logEntry); } // Keep only last 50 log entries const logEntries = logsContainer.querySelectorAll('.log-entry'); if (logEntries.length > 50) { logEntries[logEntries.length - 1].remove(); } // Auto-scroll to top for new entries logsContainer.scrollTop = 0; } addInitialLog(message, level) { // Clear the placeholder log and add the real one const logsContainer = document.getElementById('logs'); if (logsContainer) { logsContainer.innerHTML = ''; this.addLog(message, level); } } startPeriodicUpdates() { // Update uptime every 10 seconds setInterval(() => { const uptimeElement = document.getElementById('uptime'); if (uptimeElement) { uptimeElement.textContent = this.formatUptime(); } }, 10000); // Check server status every 30 seconds setInterval(() => { this.updateStatus(); }, 30000); } } // Initialize dashboard when DOM is loaded document.addEventListener('DOMContentLoaded', () => { window.dashboard = new Dashboard(); }); // Add some utility functions for future use window.ACEDashboard = { showNotification: (message, type = 'info') => { console.log(`[${type.toUpperCase()}] ${message}`); if (window.dashboard) { window.dashboard.addLog(message, type); } }, formatBytes: (bytes) => { if (bytes === 0) return '0 Bytes'; const k = 1024; const sizes = ['Bytes', 'KB', 'MB', 'GB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; }, formatDuration: (ms) => { const seconds = Math.floor(ms / 1000); const minutes = Math.floor(seconds / 60); const hours = Math.floor(minutes / 60); const days = Math.floor(hours / 24); if (days > 0) return `${days}d ${hours % 24}h`; if (hours > 0) return `${hours}h ${minutes % 60}m`; if (minutes > 0) return `${minutes}m ${seconds % 60}s`; return `${seconds}s`; } };

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Angry-Robot-Deals/ace-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server