Skip to main content
Glama

FGD Fusion Stack Pro

index.html6.81 kB
<!DOCTYPE html> <html data-theme="dark"> <head> <meta charset="UTF-8" /> <title>FGD Stack</title> <style> :root { --bg: #0d1117; --card: #161b22; --text: #f0f6fc; --accent: #58a6ff; --border: #30363d; --log-bg: #010409; } [data-theme="light"] { --bg: #f7f9fc; --card: #ffffff; --text: #24292f; --accent: #0969da; --border: #d0d7de; --log-bg: #f6f8fa; } * { box-sizing: border-box; margin: 0; padding: 0; } body { background: var(--bg); color: var(--text); font-family: -apple-system, sans-serif; padding: 2rem; } .container { max-width: 800px; margin: 0 auto; } .card { background: var(--card); border: 1px solid var(--border); border-radius: 12px; padding: 1.5rem; margin-bottom: 1.5rem; } button, input, select { padding: 0.65rem; margin: 0.4rem 0; border-radius: 8px; width: 100%; font-size: 1rem; } button { background: var(--accent); color: white; border: none; cursor: pointer; } .suggestion { background: rgba(88,166,255,0.1); padding: 0.6rem; border-radius: 6px; margin: 0.3rem 0; cursor: pointer; } #logViewer { background: var(--log-bg); height: 300px; overflow-y: auto; padding: 0.75rem; font-family: monospace; font-size: 0.85rem; white-space: pre-wrap; } .theme-toggle { position: fixed; top: 1rem; right: 1rem; width: 40px; height: 40px; background: var(--card); border: 1px solid var(--border); border-radius: 50%; display: flex; align-items: center; justify-content: center; cursor: pointer; } </style> </head> <body> <div class="theme-toggle" id="themeToggle">Dark Mode</div> <div class="container"> <h1>FGD Stack</h1> <div class="card"> <h3>1. Select Directory</h3> <input type="file" id="dirPicker" webkitdirectory directory style="display:none"> <button onclick="document.getElementById('dirPicker').click()">Browse...</button> <div id="selectedPath"></div> </div> <div class="card"> <h3>2. Git Repos</h3> <div id="suggestions"></div> </div> <div class="card"> <h3>3. LLM</h3> <select id="provider"><option value="grok">Grok</option><option value="openai">ChatGPT</option></select> </div> <button onclick="startServer()" id="startBtn">Launch Server</button> <div id="status"></div> <div class="card" id="logCard" style="display:none;"> <h3>Live Logs <span style="float:right;font-size:0.8rem;"> <select id="levelFilter" style="padding:0.3rem;"><option value="">All</option><option>INFO</option><option>ERROR</option></select> <input id="searchFilter" placeholder="Search..." style="width:120px;padding:0.3rem;margin-left:0.5rem;"> <button onclick="clearFilters()" style="padding:0.3rem 0.5rem;margin-left:0.3rem;">Clear</button> </span> </h3> <div id="logViewer"></div> </div> </div> <script> let allLogLines = [], logInterval; const themeToggle = document.getElementById('themeToggle'); themeToggle.onclick = () => { const isDark = document.documentElement.getAttribute('data-theme') === 'dark'; document.documentElement.setAttribute('data-theme', isDark ? 'light' : 'dark'); themeToggle.textContent = isDark ? 'Light Mode' : 'Dark Mode'; }; document.getElementById('dirPicker').onchange = () => { const entry = document.getElementById('dirPicker').webkitEntries?.[0]; if (entry) window.selectedDir = entry.fullPath || entry.name; document.getElementById('selectedPath').innerHTML = `<strong>Selected:</strong> ${window.selectedDir || 'None'}`; }; async function loadSuggestions() { const res = await fetch('/api/suggest'); const paths = await res.json(); document.getElementById('suggestions').innerHTML = paths.map(p => `<div class="suggestion" onclick="window.selectedDir='${p}'; document.getElementById('selectedPath').innerHTML='<strong>Selected:</strong> ${p}'">${p}</div>` ).join(''); } async function startServer() { const dir = window.selectedDir || document.getElementById('selectedPath').innerText.replace(/.*:\s*/, ''); const provider = document.getElementById('provider').value; if (!dir || dir === 'None') return alert("Select a directory"); const res = await fetch('/api/start', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({watch_dir: dir, default_provider: provider}) }); const result = await res.json(); document.getElementById('status').innerHTML = result.success ? `<div style="background:#e8f5e9;color:#2e7d32;padding:1rem;border-radius:8px;"> Server running!<br>Memory: ${result.memory_file}<br> <a href="#" onclick="showLogs('${result.log_file}'); return false;">View Live Logs</a> </div>` : `<div style="background:#ffebee;color:#c62828;padding:1rem;border-radius:8px;">Error: ${result.error}</div>`; } function showLogs(file) { const card = document.getElementById('logCard'); const viewer = document.getElementById('logViewer'); card.style.display = 'block'; viewer.innerHTML = 'Loading...\n'; allLogLines = []; if (logInterval) clearInterval(logInterval); logInterval = setInterval(async () => { const res = await fetch(`/api/logs?file=${encodeURIComponent(file)}&t=${Date.now()}`); const text = await res.text(); const lines = text.trim().split('\n'); const newLines = lines.slice(allLogLines.length); allLogLines.push(...newLines); applyFilters(); }, 1500); } function applyFilters() { const level = document.getElementById('levelFilter').value; const search = document.getElementById('searchFilter').value.toLowerCase(); const viewer = document.getElementById('logViewer'); const filtered = allLogLines.filter(l => { if (level && !l.includes(level)) return false; if (search && !l.toLowerCase().includes(search)) return false; return true; }); viewer.innerHTML = filtered.map(l => search && l.toLowerCase().includes(search) ? `<span style="background:#fffbe6;padding:0 2px;">${l.replace(/</g, '&lt;')}</span>` : l.replace(/</g, '&lt;')).join('\n'); viewer.scrollTop = viewer.scrollHeight; } function clearFilters() { document.getElementById('levelFilter').value = ''; document.getElementById('searchFilter').value = ''; applyFilters(); } document.getElementById('levelFilter').onchange = applyFilters; document.getElementById('searchFilter').oninput = () => setTimeout(applyFilters, 300); loadSuggestions(); </script> </body> </html>

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/mikeychann-hash/MCPM'

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