Skip to main content
Glama
system.ts11.2 kB
import { z } from "zod"; import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { getAllStates, callHomeAssistantService, restartHomeAssistant, stopHomeAssistant, renderTemplate, makeGetRequest, formatErrorResponse, formatSuccessResponse } from "../../utils/api.js"; /** * Register system administration and management tools */ export function registerSystemTools(server: McpServer) { // System information tool server.tool( "homeassistant_system_info", "Get Home Assistant system information and health status", {}, async () => { try { // Get multiple system endpoints const [statesResult, configResult] = await Promise.all([ getAllStates(), makeGetRequest('/api/config') ]); const output = ["Home Assistant System Information:", ""]; if (configResult.success && configResult.data) { const config = configResult.data; output.push(`Version: ${config.version || 'Unknown'}`); output.push(`Installation Type: ${config.installation_type || 'Unknown'}`); output.push(`Location: ${config.location_name || 'Unknown'}`); output.push(`Time Zone: ${config.time_zone || 'Unknown'}`); output.push(`Unit System: ${config.unit_system?.temperature || 'Unknown'} / ${config.unit_system?.length || 'Unknown'}`); output.push(`Components: ${config.components ? config.components.length : 0}`); output.push(""); } if (statesResult.success && statesResult.data) { const entities = statesResult.data; const entityStats: { [key: string]: number } = {}; entities.forEach((entity: any) => { const domain = entity.entity_id.split('.')[0]; entityStats[domain] = (entityStats[domain] || 0) + 1; }); output.push(`Total Entities: ${entities.length}`); output.push("Entities by Domain:"); Object.entries(entityStats) .sort(([,a], [,b]) => b - a) .forEach(([domain, count]) => { output.push(` ${domain}: ${count}`); }); } return formatSuccessResponse(output.join('\n')); } catch (error) { return formatErrorResponse(`Failed to get system info: ${error}`); } } ); // Template rendering tool server.tool( "homeassistant_render_template", "Render a Home Assistant Jinja2 template", { template: z.string().describe("The Jinja2 template to render (e.g., '{{ states.sensor.temperature.state }}')"), }, async ({ template }) => { const result = await renderTemplate(template); if (!result.success) { return formatErrorResponse(`Failed to render template: ${result.message}`); } return formatSuccessResponse(`Template result: ${result.data}`); } ); // Get all areas server.tool( "homeassistant_list_areas", "Get all areas defined in Home Assistant", {}, async () => { const result = await makeGetRequest('/api/config/area_registry'); if (!result.success) { return formatErrorResponse(`Failed to get areas: ${result.message}`); } const areas = result.data; if (!areas || areas.length === 0) { return formatSuccessResponse("No areas configured"); } const output = [`Found ${areas.length} areas:`, ""]; areas.forEach((area: any) => { output.push(`🏠 ${area.name} (${area.area_id})`); if (area.aliases && area.aliases.length > 0) { output.push(` Aliases: ${area.aliases.join(', ')}`); } output.push(""); }); return formatSuccessResponse(output.join('\n')); } ); // Get all devices server.tool( "homeassistant_list_devices", "Get all devices registered in Home Assistant", {}, async () => { const result = await makeGetRequest('/api/config/device_registry'); if (!result.success) { return formatErrorResponse(`Failed to get devices: ${result.message}`); } const devices = result.data; if (!devices || devices.length === 0) { return formatSuccessResponse("No devices found"); } const output = [`Found ${devices.length} devices:`, ""]; devices.slice(0, 50).forEach((device: any) => { output.push(`📱 ${device.name || device.name_by_user || 'Unknown Device'}`); output.push(` ID: ${device.id}`); if (device.manufacturer) output.push(` Manufacturer: ${device.manufacturer}`); if (device.model) output.push(` Model: ${device.model}`); if (device.area_id) output.push(` Area: ${device.area_id}`); output.push(""); }); if (devices.length > 50) { output.push(`... and ${devices.length - 50} more devices`); } return formatSuccessResponse(output.join('\n')); } ); // Get integrations server.tool( "homeassistant_list_integrations", "Get all installed integrations/components", {}, async () => { const result = await makeGetRequest('/api/config'); if (!result.success) { return formatErrorResponse(`Failed to get integrations: ${result.message}`); } const config = result.data; if (!config.components || config.components.length === 0) { return formatSuccessResponse("No components found"); } const components = config.components.sort(); const output = [ `Found ${components.length} components/integrations:`, "", components.join(', ') ]; return formatSuccessResponse(output.join('\n')); } ); // Restart Home Assistant (dangerous - requires confirmation) server.tool( "homeassistant_restart_service", "Restart Home Assistant (WARNING: This will restart the entire system)", { confirm: z.boolean().describe("Set to true to confirm you want to restart Home Assistant") }, async ({ confirm }) => { if (!confirm) { return formatErrorResponse("Restart cancelled. Set confirm=true to proceed with restart."); } const result = await restartHomeAssistant(); if (!result.success) { return formatErrorResponse(`Failed to restart Home Assistant: ${result.message}`); } return formatSuccessResponse("⚠️ Home Assistant restart initiated. The system will be unavailable for a few minutes."); } ); // Get supervisor info (if running Home Assistant OS/Supervised) server.tool( "homeassistant_supervisor_info", "Get Home Assistant Supervisor information (if available)", {}, async () => { const result = await makeGetRequest('/api/hassio/supervisor/info'); if (!result.success) { if (result.statusCode === 404) { return formatSuccessResponse("Home Assistant Supervisor not available (running in Core mode)"); } return formatErrorResponse(`Failed to get supervisor info: ${result.message}`); } const info = result.data; const output = [ "Home Assistant Supervisor Information:", "", `Version: ${info.version || 'Unknown'}`, `Channel: ${info.channel || 'Unknown'}`, `Arch: ${info.arch || 'Unknown'}`, `Hostname: ${info.hostname || 'Unknown'}`, `Timezone: ${info.timezone || 'Unknown'}`, `Healthy: ${info.healthy ? '✅' : '❌'}`, `Supported: ${info.supported ? '✅' : '❌'}` ]; if (info.addons && info.addons.length > 0) { output.push("", `Add-ons: ${info.addons.length}`); } return formatSuccessResponse(output.join('\n')); } ); // Get add-ons list server.tool( "homeassistant_list_addons", "Get list of Home Assistant add-ons (if Supervisor is available)", {}, async () => { const result = await makeGetRequest('/api/hassio/addons'); if (!result.success) { if (result.statusCode === 404) { return formatSuccessResponse("Add-ons not available (not running Home Assistant OS/Supervised)"); } return formatErrorResponse(`Failed to get add-ons: ${result.message}`); } const addons = result.data; if (!addons.addons || addons.addons.length === 0) { return formatSuccessResponse("No add-ons installed"); } const output = [`Found ${addons.addons.length} add-ons:`, ""]; addons.addons.forEach((addon: any) => { const status = addon.installed ? (addon.state === 'started' ? '🟢 Running' : '🟡 Stopped') : '⚪ Not Installed'; output.push(`${status} ${addon.name}`); output.push(` Slug: ${addon.slug}`); if (addon.version) output.push(` Version: ${addon.version}`); if (addon.description) output.push(` Description: ${addon.description}`); output.push(""); }); return formatSuccessResponse(output.join('\n')); } ); // Get entity registry server.tool( "homeassistant_search_entities", "Search for entities by name or ID pattern", { search: z.string().describe("Search term to find in entity IDs or friendly names"), domain: z.string().optional().describe("Limit search to specific domain") }, async ({ search, domain }) => { const result = await getAllStates(); if (!result.success) { return formatErrorResponse(`Failed to search entities: ${result.message}`); } let entities = result.data; // Filter by domain if specified if (domain) { entities = entities.filter((entity: any) => entity.entity_id.startsWith(`${domain}.`)); } // Search in entity ID and friendly name const searchLower = search.toLowerCase(); const matchingEntities = entities.filter((entity: any) => { const entityIdMatch = entity.entity_id.toLowerCase().includes(searchLower); const nameMatch = entity.attributes?.friendly_name?.toLowerCase().includes(searchLower); return entityIdMatch || nameMatch; }); if (matchingEntities.length === 0) { return formatSuccessResponse(`No entities found matching "${search}"`); } const output = [`Found ${matchingEntities.length} entities matching "${search}":`, ""]; matchingEntities.slice(0, 20).forEach((entity: any) => { output.push(`📍 ${entity.entity_id}`); if (entity.attributes?.friendly_name) { output.push(` Name: ${entity.attributes.friendly_name}`); } output.push(` State: ${entity.state}`); output.push(""); }); if (matchingEntities.length > 20) { output.push(`... and ${matchingEntities.length - 20} more matches`); } return formatSuccessResponse(output.join('\n')); } ); }

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/gilberth/enhanced-homeassistant-mcp'

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