Skip to main content
Glama
nesirat

MCP Vulnerability Management System

by nesirat
dashboard.html19.2 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Dashboard - MCP Vulnerability Server</title> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet"> <style> body { background-color: #f8f9fa; } .dashboard-container { max-width: 1200px; margin: 20px auto; padding: 20px; } .nav-tabs { margin-bottom: 20px; } .card { margin-bottom: 20px; } .api-key-list { margin-top: 20px; } </style> </head> <body> <nav class="navbar navbar-expand-lg navbar-dark bg-primary"> <div class="container"> <a class="navbar-brand" href="#">MCP Vulnerability Server</a> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarNav"> <ul class="navbar-nav ms-auto"> <li class="nav-item"> <a class="nav-link" href="#" id="logoutBtn">Logout</a> </li> </ul> </div> </div> </nav> <div class="dashboard-container"> <ul class="nav nav-tabs" id="dashboardTabs" role="tablist"> <li class="nav-item" role="presentation"> <button class="nav-link active" id="vulnerabilities-tab" data-bs-toggle="tab" data-bs-target="#vulnerabilities" type="button" role="tab">Vulnerabilities</button> </li> <li class="nav-item" role="presentation"> <button class="nav-link" id="api-keys-tab" data-bs-toggle="tab" data-bs-target="#api-keys" type="button" role="tab">API Keys</button> </li> </ul> <div class="tab-content" id="dashboardTabContent"> <div class="tab-pane fade show active" id="vulnerabilities" role="tabpanel"> <div class="card"> <div class="card-header"> <h5 class="card-title mb-0">Vulnerability Collection</h5> </div> <div class="card-body"> <div class="row"> <div class="col-md-4"> <button class="btn btn-primary w-100" onclick="collectVulnerabilities('bsi')">Collect BSI Data</button> </div> <div class="col-md-4"> <button class="btn btn-primary w-100" onclick="collectVulnerabilities('nvd')">Collect NVD Data</button> </div> <div class="col-md-4"> <button class="btn btn-primary w-100" onclick="collectVulnerabilities('mitre')">Collect MITRE Data</button> </div> </div> </div> </div> <div class="card"> <div class="card-header"> <h5 class="card-title mb-0">Recent Vulnerabilities</h5> </div> <div class="card-body"> <div class="table-responsive"> <table class="table"> <thead> <tr> <th>CVE ID</th> <th>Title</th> <th>Severity</th> <th>Source</th> <th>Last Modified</th> </tr> </thead> <tbody id="vulnerabilitiesList"> <!-- Vulnerabilities will be listed here --> </tbody> </table> </div> </div> </div> </div> <div class="tab-pane fade" id="api-keys" role="tabpanel"> <div class="card"> <div class="card-header d-flex justify-content-between align-items-center"> <h5 class="card-title mb-0">API Keys</h5> <button class="btn btn-primary" onclick="showCreateKeyModal()">Create New Key</button> </div> <div class="card-body"> <div class="table-responsive"> <table class="table"> <thead> <tr> <th>Name</th> <th>Description</th> <th>Status</th> <th>Created</th> <th>Actions</th> </tr> </thead> <tbody id="apiKeysList"> <!-- API keys will be listed here --> </tbody> </table> </div> </div> </div> <div class="card"> <div class="card-header"> <h5 class="card-title mb-0">API Key Usage</h5> <div class="float-end"> <select id="keySelector" class="form-select d-inline-block w-auto" onchange="loadUsageGraph()"> <option value="">All Keys</option> </select> <input type="date" id="startDate" class="form-control d-inline-block w-auto ms-2" onchange="loadUsageGraph()"> <input type="date" id="endDate" class="form-control d-inline-block w-auto ms-2" onchange="loadUsageGraph()"> </div> </div> <div class="card-body"> <canvas id="usageGraph"></canvas> </div> </div> </div> </div> </div> <!-- Create API Key Modal --> <div class="modal fade" id="createKeyModal" tabindex="-1"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title">Create New API Key</h5> <button type="button" class="btn-close" data-bs-dismiss="modal"></button> </div> <div class="modal-body"> <form id="createKeyForm"> <div class="mb-3"> <label for="keyName" class="form-label">Name</label> <input type="text" class="form-control" id="keyName" required> </div> <div class="mb-3"> <label for="keyDescription" class="form-label">Description</label> <textarea class="form-control" id="keyDescription"></textarea> </div> </form> </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button> <button type="button" class="btn btn-primary" onclick="createApiKey()">Create</button> </div> </div> </div> </div> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> <script> // Check if user is logged in const token = localStorage.getItem('token'); if (!token) { window.location.href = '/'; } // Logout function document.getElementById('logoutBtn').addEventListener('click', (e) => { e.preventDefault(); localStorage.removeItem('token'); window.location.href = '/'; }); // Load vulnerabilities async function loadVulnerabilities() { try { const response = await fetch('/vulnerabilities/', { headers: { 'Authorization': `Bearer ${token}` } }); const data = await response.json(); const tbody = document.getElementById('vulnerabilitiesList'); tbody.innerHTML = data.map(vuln => ` <tr> <td>${vuln.cve_id}</td> <td>${vuln.title}</td> <td>${vuln.severity}</td> <td>${vuln.source}</td> <td>${new Date(vuln.last_modified_date).toLocaleString()}</td> </tr> `).join(''); } catch (error) { console.error('Error loading vulnerabilities:', error); } } let usageChart = null; // Load API keys async function loadApiKeys() { const token = localStorage.getItem('token'); if (!token) { console.error('No token found'); window.location.href = '/'; return; } try { const response = await fetch('/api-keys', { headers: { 'Authorization': `Bearer ${token}` } }); console.log('Load API keys response status:', response.status); const responseData = await response.json(); console.log('Load API keys response data:', responseData); if (!response.ok) { throw new Error(responseData.detail || 'Failed to load API keys'); } const tbody = document.getElementById('apiKeysList'); tbody.innerHTML = responseData.map(key => ` <tr> <td>${key.name}</td> <td>${key.description || 'No description'}</td> <td>${key.is_active ? '<span class="badge bg-success">Active</span>' : '<span class="badge bg-danger">Revoked</span>'}</td> <td>${new Date(key.created_at).toLocaleString()}</td> <td> <button class="btn btn-sm btn-danger" onclick="deleteApiKey(${key.id})">Delete</button> ${key.is_active ? `<button class="btn btn-sm btn-warning ms-1" onclick="revokeApiKey(${key.id})">Revoke</button>` : ''} </td> </tr> `).join(''); } catch (error) { console.error('Error loading API keys:', error); alert(error.message || 'Error loading API keys'); } } // Collect vulnerabilities async function collectVulnerabilities(source) { try { const response = await fetch(`/collect/${source}`, { method: 'POST', headers: { 'Authorization': `Bearer ${token}` } }); const data = await response.json(); alert(data.message); loadVulnerabilities(); } catch (error) { console.error('Error collecting vulnerabilities:', error); alert('Error collecting vulnerabilities'); } } // Show create key modal function showCreateKeyModal() { const modal = new bootstrap.Modal(document.getElementById('createKeyModal')); modal.show(); } // Create API key async function createApiKey() { const name = document.getElementById('keyName').value; const description = document.getElementById('keyDescription').value; if (!name) { alert('Please enter a name for the API key'); return; } const token = localStorage.getItem('token'); if (!token) { alert('You are not logged in. Please log in and try again.'); window.location.href = '/'; return; } const requestData = { name: name, description: description || null }; console.log('Creating API key with data:', requestData); console.log('Using token:', token); try { const response = await fetch('/api-keys', { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify(requestData) }); console.log('Response status:', response.status); const responseData = await response.json(); console.log('Response data:', responseData); if (!response.ok) { throw new Error(responseData.detail || 'Failed to create API key'); } alert(`API key created successfully!\nKey: ${responseData.key}\n\nPlease save this key as it won't be shown again.`); bootstrap.Modal.getInstance(document.getElementById('createKeyModal')).hide(); document.getElementById('keyName').value = ''; document.getElementById('keyDescription').value = ''; loadApiKeys(); } catch (error) { console.error('Error creating API key:', error); alert(error.message || 'Error creating API key'); } } // Revoke API key async function revokeApiKey(keyId) { if (!confirm('Are you sure you want to revoke this API key?')) return; try { const response = await fetch(`/api-keys/${keyId}/revoke`, { method: 'POST', headers: { 'Authorization': `Bearer ${token}` } }); const data = await response.json(); if (response.ok) { alert('API key revoked successfully'); loadApiKeys(); } else { alert(data.detail || 'Error revoking API key'); } } catch (error) { console.error('Error revoking API key:', error); alert('Error revoking API key'); } } // Delete API key async function deleteApiKey(keyId) { if (!confirm('Are you sure you want to delete this API key?')) return; try { const response = await fetch(`/api-keys/${keyId}`, { method: 'DELETE', headers: { 'Authorization': `Bearer ${token}` } }); const data = await response.json(); if (response.ok) { alert('API key deleted successfully'); loadApiKeys(); } else { alert(data.detail || 'Error deleting API key'); } } catch (error) { console.error('Error deleting API key:', error); alert('Error deleting API key'); } } // Load usage graph async function loadUsageGraph() { const keyId = document.getElementById('keySelector').value; const startDate = document.getElementById('startDate').value; const endDate = document.getElementById('endDate').value; try { let url = '/api-keys/usage?'; if (keyId) url += `key_id=${keyId}&`; if (startDate) url += `start_date=${startDate}&`; if (endDate) url += `end_date=${endDate}`; const response = await fetch(url, { headers: { 'Authorization': `Bearer ${token}` } }); const data = await response.json(); if (usageChart) { usageChart.destroy(); } const ctx = document.getElementById('usageGraph').getContext('2d'); usageChart = new Chart(ctx, { type: 'line', data: { labels: data.daily_usage.map(d => d.date), datasets: [ { label: 'Total Requests', data: data.daily_usage.map(d => d.requests), borderColor: 'rgb(75, 192, 192)', tension: 0.1 }, { label: 'Successful Requests', data: data.daily_usage.map(d => d.successful_requests), borderColor: 'rgb(54, 162, 235)', tension: 0.1 }, { label: 'Failed Requests', data: data.daily_usage.map(d => d.failed_requests), borderColor: 'rgb(255, 99, 132)', tension: 0.1 } ] }, options: { responsive: true, scales: { y: { beginAtZero: true } } } }); } catch (error) { console.error('Error loading usage graph:', error); } } // Set default date range const today = new Date(); const thirtyDaysAgo = new Date(today); thirtyDaysAgo.setDate(today.getDate() - 30); document.getElementById('startDate').value = thirtyDaysAgo.toISOString().split('T')[0]; document.getElementById('endDate').value = today.toISOString().split('T')[0]; // Load initial data loadVulnerabilities(); loadApiKeys(); loadUsageGraph(); </script> </body> </html>

Latest Blog Posts

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/nesirat/MCP'

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