Skip to main content
Glama
system.ts3.44 kB
import { SystemInfo } from '../types.js'; import { promises as fs } from 'fs'; import os from 'os'; export async function getSystemInfo(): Promise<SystemInfo> { const hostname = os.hostname(); const uptimeHours = parseFloat((os.uptime() / 3600).toFixed(2)); // CPU usage - average over 1 second const cpuPercent = await getCPUUsage(); // Memory const totalMemory = os.totalmem(); const freeMemory = os.freemem(); const usedMemory = totalMemory - freeMemory; const memoryUsedGB = parseFloat((usedMemory / (1024 ** 3)).toFixed(2)); const memoryTotalGB = parseFloat((totalMemory / (1024 ** 3)).toFixed(2)); const memoryPercent = parseFloat(((usedMemory / totalMemory) * 100).toFixed(2)); // Disk usage for root filesystem const diskStats = await getDiskUsage('/'); return { hostname, uptime_hours: uptimeHours, cpu_percent: cpuPercent, memory_used_gb: memoryUsedGB, memory_total_gb: memoryTotalGB, memory_percent: memoryPercent, disk_used_gb: diskStats.usedGB, disk_total_gb: diskStats.totalGB, disk_percent: diskStats.percent, }; } async function getCPUUsage(): Promise<number> { const startUsage = getCPUInfo(); await new Promise(resolve => setTimeout(resolve, 1000)); const endUsage = getCPUInfo(); const idleDiff = endUsage.idle - startUsage.idle; const totalDiff = endUsage.total - startUsage.total; const cpuPercent = 100 - (100 * idleDiff / totalDiff); return parseFloat(cpuPercent.toFixed(2)); } function getCPUInfo() { const cpus = os.cpus(); let idle = 0; let total = 0; cpus.forEach(cpu => { for (const type in cpu.times) { total += cpu.times[type as keyof typeof cpu.times]; } idle += cpu.times.idle; }); return { idle, total }; } async function getDiskUsage(path: string): Promise<{ usedGB: number; totalGB: number; percent: number }> { try { // Read /proc/mounts to find the device for the path const mounts = await fs.readFile('/proc/mounts', 'utf-8'); const lines = mounts.split('\n'); // Find the mount point for the path let device = ''; let mountPoint = ''; let longestMatch = 0; for (const line of lines) { const parts = line.split(' '); if (parts.length < 2) continue; const mount = parts[1]; if (path.startsWith(mount) && mount.length > longestMatch) { device = parts[0]; mountPoint = mount; longestMatch = mount.length; } } if (!device) { throw new Error('Could not find device for path'); } // Use statvfs-like approach via /proc/self/mountinfo const { execSync } = await import('child_process'); const dfOutput = execSync(`df -B1 ${mountPoint}`).toString(); const dfLines = dfOutput.split('\n'); if (dfLines.length < 2) { throw new Error('Unexpected df output'); } const stats = dfLines[1].split(/\s+/); const totalBytes = parseInt(stats[1], 10); const usedBytes = parseInt(stats[2], 10); const totalGB = parseFloat((totalBytes / (1024 ** 3)).toFixed(2)); const usedGB = parseFloat((usedBytes / (1024 ** 3)).toFixed(2)); const percent = parseFloat(((usedBytes / totalBytes) * 100).toFixed(2)); return { usedGB, totalGB, percent }; } catch (error) { // Fallback: return dummy data console.warn('[System] Could not get disk usage:', (error as Error).message); return { usedGB: 0, totalGB: 0, percent: 0 }; } }

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/bshandley/homelab-mcp'

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