UNPKG

domotz-mcp

Version:

MCP server for Domotz API and BMS (Building Management System) integration with IoT device monitoring

100 lines (99 loc) 4.03 kB
import axios from "axios"; import { z } from "zod"; import { MCPTool } from "mcp-framework"; export default class HomeAssistantDiscoveryTool extends MCPTool { name = "ha_discover"; description = "Discover entities and devices in Home Assistant"; schema = { ha_url: { type: z.string(), description: "Home Assistant URL (e.g., http://homeassistant.local:8123)" }, access_token: { type: z.string(), description: "Long-lived access token from Home Assistant" }, entity_type: { type: z.string().optional(), description: "Filter by entity type (e.g., light, switch, sensor, climate)" } }; async execute(params) { try { const { ha_url, access_token, entity_type } = params; // Remove trailing slash from URL const baseUrl = ha_url.replace(/\/$/, ""); // Get all states (entities) const statesResponse = await axios.get(`${baseUrl}/api/states`, { headers: { "Authorization": `Bearer ${access_token}`, "Content-Type": "application/json" } }); let entities = statesResponse.data; // Filter by entity type if specified if (entity_type) { entities = entities.filter((entity) => entity.entity_id.startsWith(`${entity_type}.`)); } // Get devices const devicesResponse = await axios.get(`${baseUrl}/api/config/device_registry/list`, { headers: { "Authorization": `Bearer ${access_token}`, "Content-Type": "application/json" } }); // Get areas const areasResponse = await axios.get(`${baseUrl}/api/config/area_registry/list`, { headers: { "Authorization": `Bearer ${access_token}`, "Content-Type": "application/json" } }); // Process entities to extract useful information const processedEntities = entities.map((entity) => ({ entity_id: entity.entity_id, name: entity.attributes.friendly_name || entity.entity_id, state: entity.state, type: entity.entity_id.split('.')[0], attributes: entity.attributes, last_changed: entity.last_changed, last_updated: entity.last_updated })); // Group entities by type const entitiesByType = {}; processedEntities.forEach((entity) => { if (!entitiesByType[entity.type]) { entitiesByType[entity.type] = []; } entitiesByType[entity.type].push(entity); }); return { success: true, summary: { total_entities: processedEntities.length, total_devices: devicesResponse.data.length, total_areas: areasResponse.data.length, entity_types: Object.keys(entitiesByType).map(type => ({ type, count: entitiesByType[type].length })) }, entities: processedEntities, devices: devicesResponse.data.slice(0, 10), // Limit to first 10 devices areas: areasResponse.data }; } catch (error) { if (error.response?.status === 401) { return { success: false, error: "Invalid access token. Please check your Home Assistant long-lived access token." }; } return { success: false, error: error.message || "Failed to discover Home Assistant entities" }; } } }