Home Assistant MCP server: full REST and WebSocket control surface (states, services, history, templates, area awareness) for Claude and Codex.
ha-mcp defines 9 tools with consistent naming (verb_noun pattern: ha_get_*, ha_call_*, ha_list_*) and reasonable descriptions (avg ~120 chars). All tools have input schemas with Zod validation. However, parameter descriptions are minimal (often single phrases like 'Entity identifier'), output schemas are undocumented (responses wrapped in generic text content), and error handling lacks recovery guidance. No tool annotations (readOnlyHint/destructiveHint). Schemas are present but sparse, most parameters lack format/range constraints. This is solid for a domain-specific tool but falls short of production-grade patterns.
Call any Home Assistant service. Examples: light.turn_on, climate.set_temperature, automation.trigger, scene.turn_on, media_player.play_media. Pass extra params (brightness, temperature, etc.) in `data`.
Get Home Assistant configuration: version, location, unit system, time zone, loaded components.
List the entity_ids in a given area/room (by name or area_id), resolving device→area inheritance.
Get the full state and attributes of one entity by entity_id (e.g. 'light.kitchen_lights').
Get the Home Assistant error log (plain text) for troubleshooting.
Get state-change history for an entity over the last N hours (default 24).
Output schemas undocumented. All tools return generic text content wrapper; LLMs cannot infer response structure (fields, types, pagination). Breaks downstream tool chaining and forces parsing unstructured JSON.
Parameter descriptions are minimal (single phrases). 'Optional domain filter (e.g. 'light', 'sensor')' lacks format/constraint details. LLMs cannot validate inputs or self-correct invalid values.
No tool annotations. ha_call_service is destructive (WRITE risk) but lacks destructiveHint. ha_get_* tools are read-only but lack readOnlyHint. Agents cannot distinguish safe from risky operations.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | D | 55 | 2026-07-28+ | v2 |
List Home Assistant entity states. Optionally filter by domain (e.g. 'light', 'sensor') and/or area (room name or area_id).
List all areas/rooms defined in Home Assistant.
Render a Home Assistant Jinja2 template and return the result. Example: "{{ states('sensor.outside_temperature') }}".
Error handling lacks recovery guidance. REST errors (e.g. 404, 401) are thrown as generic Error objects with minimal context. No actionable messages to guide LLM retry or fallback strategies.
No input validation or constraint enforcement. domain/area/entity_id parameters accept any string; invalid values fail silently at HA API. Should validate early and return 'Invalid domain: must be one of: light, sensor, ...' to enable LLM self-correction.