Skip to main content
Glama
homeassistant-ai

Home Assistant MCP Server

Official

Breaking change (v7.3.0): ha_config_set_yaml has been moved to beta.

The Unofficial and Awesome Home Assistant MCP Server


Demo with Claude Desktop


๐Ÿš€ Get Started

The recommended way to run ha-mcp is the HA-MCP Custom Component. It installs into Home Assistant through HACS, runs the full server in-process, and works on every Home Assistant installation type โ€” Home Assistant OS, Supervised, Container, and Core โ€” with full feature parity. It is the easiest setup in every case, with no access token to manage.

Add it to Home Assistant via HACS (the preferred install):

Add HA-MCP to HACS

Quick start:

  1. Install the HA-MCP Custom Component from HACS โ€” click the badge above, or in HACS open Integrations โ†’ โ‹ฎ โ†’ Custom repositories, add https://github.com/homeassistant-ai/ha-mcp-integration (category: Integration), then Download.

  2. Restart Home Assistant.

  3. Go to Settings โ†’ Devices & Services โ†’ Add Integration, search for HA-MCP Custom Component, choose HA-MCP Server, and click Submit. Creating the entry starts the server.

  4. Copy the connect URL from the entry's Configure screen (Settings โ†’ Devices & Services โ†’ HA-MCP Custom Component โ†’ HA-MCP Server โ†’ Configure) โ€” it is also printed in the Home Assistant log. A notification confirms the server started and points you there.

  5. Paste that URL into your AI client โ€” done.

Connect URL. The Configure screen gives you a Home Assistant webhook URL for remote clients โ€” https://<your-ha-domain>/api/webhook/<webhook-id> through Nabu Casa or any reverse proxy already pointed at Home Assistant (locally, http://<ha-host>:8123/api/webhook/<webhook-id>). For clients on the same network, the server is also reachable directly at http://<ha-ip>:9584/private_<random>.

  • Replaces other install methods: the in-process server is a complete, standalone ha-mcp install โ€” it takes the place of the app (add-on), Docker, and uvx/PyPI (stdio) methods. Run only one; do not run the in-process server alongside another install.

  • Local only? Turn off Remote access via webhook in the entry options โ€” no webhook is registered at all, while the direct port and sidebar panel keep working.

  • Settings panel: while the server runs, an admin-only HA-MCP panel appears in the Home Assistant sidebar for managing tools, feature flags, backups, and themes.

  • Optional authentication: set Webhook authentication to ha_auth to require a Home Assistant account sign-in instead of using the secret URL as the credential.

  • Manual install (no HACS): copy custom_components/ha_mcp_tools/ from this repository into your Home Assistant config/custom_components/ directory, then restart and add the integration as above.

The component's second entry type, the File & YAML services entry (HA-MCP File & YAML Tools), is only needed if you enable ha-mcp's opt-in file and YAML editing tools (feature flags, off by default) โ€” skip it otherwise; you can add it later at any time. It works with any server type (in-process, app, Docker, or stdio).

Full in-process server documentation โ†’ ยท Setup Wizard for client-specific config โ†’

๐Ÿ  Home Assistant app (add-on)

Prefer to run ha-mcp as a Home Assistant app (add-on)? On Home Assistant OS and Supervised installs it is a close second โ€” no access token to manage, and it works with Claude Desktop, Claude.ai, ChatGPT, and any other MCP client on your local network or configured for remote access.

  1. Add the repository to your Home Assistant instance:

    Add Repository

    If that opens the App store without an add-repository dialog (a known Home Assistant issue), add it manually: Settings โ†’ Apps โ†’ Install app โ†’ โ‹ฎ โ†’ Repositories, then paste https://github.com/homeassistant-ai/ha-mcp.

  2. Install "Home Assistant MCP Server" from Settings โ†’ Apps โ†’ Install app and click Start. (Home Assistant 2026.2 renamed "Add-ons" to "Apps"; on older versions this is the Add-on store.)

  3. Open the Logs tab to find your unique MCP URL.

  4. Connect your AI client to that URL โ€” no token or credential setup needed.

Full app documentation โ†’

โš ๏ธ Configure exactly one install method per client. The custom component, the app, Docker/PyPI, and local stdio are independent ways to run the same server โ€” pick one and point your AI client at that single URL. Keeping two entries for the same server in one client (for example a local uvx ha-mcp@latest entry with HOMEASSISTANT_URL / HOMEASSISTANT_TOKEN alongside an app or component URL) is a known cause of connection hangs.

Other install methods

These run the server outside Home Assistant โ€” useful for Container / Core installs (which can't run apps) or a separate host. The Setup Wizard generates the exact client-specific config for each.

  • Docker (HTTP server): run ghcr.io/homeassistant-ai/ha-mcp in HTTP mode, pointed at your Home Assistant URL and a long-lived token, and connect your client to its secret URL. See the Setup Wizard for the full command and per-client config.

  • PyPI / uvx (HTTP server): run the published ha-mcp package with uvx ha-mcp@latest (or pip) as a streamable-HTTP server the same way. Details in the Setup Wizard.

  • Local stdio (not recommended): runs ha-mcp on your own machine over stdio. The one-command installers in the Demo server section below use this path; the Setup Wizard covers connecting it to your own Home Assistant.

  • OIDC authentication: gate remote access behind an external identity provider (Authentik, Keycloak, Auth0, etc.) instead of a secret URL โ€” all authenticated users share the server's Home Assistant credentials. See OIDC Mode.

    โš ๏ธ stdio has known transport issues. The stdio transport has connection problems that streamable HTTP does not (#1713). It is recommended only for demo/testing tinkering โ€” for a real setup, use the custom component or an HTTP method above.

Using the HA-MCP custom component? You do not need the Webhook Proxy โ€” the component has its own built-in webhook for remote access (see the Get Started quick start at the top). The proxy is for the app (it can also front another external server via its mcp_server_url option). The OpenAI Tunnel below is different: it applies to any install method when Home Assistant isn't publicly reachable at all (no Nabu Casa or reverse proxy).

Already have Nabu Casa or another reverse proxy pointing at your Home Assistant? The Webhook Proxy app routes MCP traffic through your existing setup โ€” no separate tunnel or port forwarding needed.

  1. Install the MCP Server app (see above) and the Webhook Proxy app from the same store

  2. Start the webhook proxy and restart Home Assistant when prompted

  3. Copy the webhook URL from the app logs:

    MCP Server URL (remote): https://xxxxx.ui.nabu.casa/api/webhook/mcp_xxxxxxxx
  4. Configure your AI client with that URL

For other remote access methods (Cloudflare Tunnel, custom reverse proxy), see the Setup Wizard.

ChatGPT / Codex behind a firewall (OpenAI Tunnel). ChatGPT connectors normally require a publicly reachable URL. If you can't (or don't want to) expose one, the community OpenAI Tunnel for HA-MCP integration by @norpol runs OpenAI's tunnel-client inside Home Assistant and connects your local MCP server URL to an OpenAI-hosted tunnel over an outbound-only connection โ€” no port forwarding, reverse proxy, or public URL. Point it at your ha-mcp URL, then attach the ChatGPT connector to the same tunnel ID. See the FAQ entry and #1811.

Webhook proxy documentation โ†’

๐Ÿงช Demo server (Windows / macOS / Linux)

Want to try ha-mcp before connecting your own Home Assistant? No paid subscription required. These one-command scripts set up a local stdio connection to a hosted demo environment so you can see it working in a few minutes. Each script's Connect your own Home Assistant link then shows how to point it at your instance.

  1. Go to claude.ai and sign in (or create a free account)

  2. Open Terminal and run:

    curl -LsSf https://raw.githubusercontent.com/homeassistant-ai/ha-mcp/master/scripts/install-macos.sh | sh
  3. Download Claude Desktop (or restart: Claude menu โ†’ Quit)

  4. Ask Claude: "Can you see my Home Assistant?"

You're now connected to the demo environment! Connect your own Home Assistant โ†’

Anthropic doesn't ship Claude Desktop for Linux, so pick one path:

Claude Desktop โ€” free, via the community build:

  1. Install the community Claude Desktop for Linux build and sign in with a free claude.ai account

  2. Open Terminal and run:

    curl -LsSf https://raw.githubusercontent.com/homeassistant-ai/ha-mcp/master/scripts/install-linux.sh | sh
  3. Restart Claude Desktop, then ask: "Can you see my Home Assistant?"

Claude Code โ€” official CLI, requires a paid Claude plan:

  1. Install Claude Code: curl -fsSL https://claude.ai/install.sh | bash

  2. Configure ha-mcp, then run claude:

    curl -LsSf https://raw.githubusercontent.com/homeassistant-ai/ha-mcp/master/scripts/install.sh | sh -s -- --claude-code
  3. Start claude, run /mcp to confirm, then ask: "Can you see my Home Assistant?"

Full Linux guide โ†’

  1. Go to claude.ai and sign in (or create a free account)

  2. Open Windows PowerShell (from Start menu) and run:

    irm https://raw.githubusercontent.com/homeassistant-ai/ha-mcp/master/scripts/install-windows.ps1 | iex
  3. Download Claude Desktop (or restart: File โ†’ Exit)

  4. Ask Claude: "Can you see my Home Assistant?"

You're now connected to the demo environment! Connect your own Home Assistant โ†’

๐Ÿง™ Setup Wizard for 15+ clients

Claude Code, Gemini CLI, ChatGPT, Open WebUI, VSCode, Cursor, and more.

Having issues? Check the FAQ & Troubleshooting


Related MCP server: hass-mcp-server

๐Ÿ’ฌ What Can You Do With It?

Just talk to Claude naturally. Here are some real examples:

You Say

What Happens

"Create an automation that turns on the porch light at sunset"

Creates the automation with proper triggers and actions

"Add a weather card to my dashboard"

Updates your Lovelace dashboard with the new card

"The motion sensor automation isn't working, debug it"

Analyzes execution traces, identifies the issue, suggests fixes

"Make my morning routine automation also turn on the coffee maker"

Reads the existing automation, adds the new action, updates it

"Create a script that sets movie mode: dim lights, close blinds, turn on TV"

Creates a reusable script with the sequence of actions

Spend less time configuring, more time enjoying your smart home.


โœจ Features

Category

Capabilities

๐Ÿ” Search

Fuzzy entity search, deep config search, system overview

๐Ÿ  Control

Any service, bulk device control, real-time states

๐Ÿ”ง Manage

Automations, scripts, helpers, dashboards, areas, zones, groups, calendars, blueprints

๐Ÿ“Š Monitor

History, statistics, camera snapshots, automation traces, ZHA devices

๐Ÿ’พ System

Backup/restore, updates, apps, device registry

๐Ÿ”’ Safety

Read Only Mode toggle, per-tool enable/disable, tool security policies (user approval), automatic edit backups

Category

Tools

Apps (add-ons)

ha_get_app, ha_manage_app

Areas & Floors

ha_list_floors_areas, ha_remove_area_or_floor, ha_set_area_or_floor

Assist

ha_manage_pipeline

Automations

ha_config_get_automation, ha_config_remove_automation, ha_config_set_automation

Blueprints

ha_manage_blueprints

Calendar

ha_config_get_calendar_events, ha_config_remove_calendar_event, ha_config_set_calendar_event

Camera

ha_get_camera_image

Dashboard

ha_get_dashboard_screenshot (beta)

Dashboards

ha_config_delete_dashboard_resource, ha_config_delete_dashboard, ha_config_get_dashboard, ha_config_list_dashboard_resources, ha_config_set_dashboard_resource, ha_config_set_dashboard

Developer

ha_dev_manage_server, ha_dev_manage_settings

Device Registry

ha_get_device, ha_remove_device, ha_set_device

Energy

ha_manage_energy_prefs

Entity Registry

ha_get_entity_exposure, ha_get_entity, ha_remove_entity, ha_set_entity

Files

ha_delete_file (beta), ha_list_files (beta), ha_read_file (beta), ha_write_file (beta)

Groups

ha_config_list_groups, ha_config_remove_group, ha_config_set_group

HACS

ha_get_hacs_info, ha_manage_hacs

Helper Entities

ha_config_list_helpers, ha_config_set_helper, ha_remove_helpers_integrations

History & Statistics

ha_get_automation_traces, ha_get_history, ha_get_logs

Integrations

ha_get_integration, ha_get_system_health, ha_set_integration

Labels & Categories

ha_config_get_category, ha_config_get_label, ha_config_remove_category, ha_config_remove_label, ha_config_set_category, ha_config_set_label

Matter

ha_manage_radio

Scenes

ha_config_get_scene, ha_config_remove_scene, ha_config_set_scene

Scripts

ha_config_get_script, ha_config_remove_script, ha_config_set_script

Search & Discovery

ha_get_overview, ha_get_state, ha_search

Service & Device Control

ha_bulk_control, ha_call_event, ha_call_service, ha_get_operation_status, ha_list_services

System

ha_config_get_yaml (beta), ha_config_set_yaml (beta), ha_manage_backup, ha_manage_custom_tool (beta), ha_manage_security_policy, ha_manage_theme, ha_manage_updates, ha_reload_core, ha_restart

Todo Lists

ha_get_todo, ha_remove_todo_item, ha_set_todo_item

Utilities

ha_eval_template, ha_report_issue

Zones

ha_get_zone, ha_remove_zone, ha_set_zone


๐Ÿ†š ha-mcp vs. Home Assistant's built-in MCP Server

Home Assistant ships its own MCP Server integration. It is built on the Assist pipeline, so a connected MCP client can read and control the entities you have exposed to Assist and run the intents Assist understands โ€” handy for voice-style control of already-exposed devices.

ha-mcp is a standalone server built for configuring, building, and debugging your smart home, not just controlling it. On top of device control, it adds capabilities the built-in integration does not have:

Capability

Built-in MCP Server

ha-mcp

Control exposed devices, query states

Yes

Yes

Entity scope

Only entities exposed to Assist

Everything in Home Assistant

Create / edit automations, scripts, scenes

No

Yes

Build & edit dashboards

No

Yes

Debug automations from traces, read history & logs

No

Yes

Manage helpers, areas, zones, labels, groups

No

Yes

Backups, apps, HACS, device & entity registry

No

Yes

Rule of thumb: Use the built-in integration for voice-style control of devices you have already exposed; use ha-mcp when you want an AI assistant that can also build and maintain your Home Assistant setup.


๐Ÿ”Œ Custom Component (ha_mcp_tools) โ€” File & YAML Services

The HA-MCP Custom Component also powers a set of privileged tools that standard Home Assistant APIs can't provide: file system access and YAML config editing. (The same component runs the full server in-process โ€” that's the recommended install in the Get Started section at the top.) Its File & YAML services entry (HA-MCP File & YAML Tools) enables the tools below.

Tools that require the component:

Tool

Description

ha_config_set_yaml (beta)

Safely add, replace, or remove top-level YAML keys in configuration.yaml and package files (automatic backup, validation, and config check)

ha_list_files (beta)

List files in allowed directories

ha_read_file (beta)

Read files from allowed paths (config YAML, logs, and allowed directories)

ha_write_file (beta)

Write files to allowed directories

ha_delete_file (beta)

Delete files from allowed directories

All other tools work without the component. These five return an error with installation instructions if the component is missing.

These tools also require beta feature flags. See Beta Features for how to enable them โ€” including the ENABLE_BETA_FEATURES master flag, which must be on before the filesystem/YAML sub-flags take effect.

Install

Install the HA-MCP File & YAML Tools entry from the same HA-MCP Custom Component:

Open your Home Assistant instance and open a repository inside the Home Assistant Community Store.

To add manually: open HACS > Integrations > three-dot menu > Custom repositories > add https://github.com/homeassistant-ai/ha-mcp-integration (category: Integration) > Download. Or copy custom_components/ha_mcp_tools/ from this repository into your HA config/custom_components/ directory.

After installing, restart Home Assistant, then open Settings > Devices & Services > Add Integration, search for HA-MCP Custom Component, and add the HA-MCP File & YAML Tools entry.

To run the full ha-mcp server in-process through this same component, see the Get Started section at the top and the full in-process server documentation โ†’.


๐Ÿง  Better Results with Agent Skills

This server gives your AI agent tools to control Home Assistant. For better configurations, pair it with Home Assistant Agent Skills โ€” domain knowledge that teaches the agent Home Assistant best practices.

An MCP server can create automations, helpers, and dashboards, but it has no opinion on how to structure them. Without domain knowledge, agents tend to over-rely on templates, pick the wrong helper type, or produce automations that are hard to maintain. The skills fill that gap: native constructs over Jinja2 workarounds, correct helper selection, safe refactoring workflows, and proper use of automation modes.

Bundled Skills (built-in)

Skills from homeassistant-ai/skills are bundled and served as MCP resources via skill:// URIs. Any MCP client that supports resources can discover them automatically โ€” no manual installation needed. For tool-only clients (claude.ai, etc.), the same skills are reachable through the polymorphic ha_get_skill_guide tool โ€” call it with no args to list bundled skills, with a skill arg to list its files, or with skill + file to read content. Resources are not auto-injected into context โ€” clients must explicitly request them, so idle context cost is just the metadata listing.

ha_get_skill_guide is a mandatory tool: the catalog always exposes it (it can't be disabled) so tool-only clients never see a silently missing skill surface.

Skills can still be installed manually for clients that prefer local skill files โ€” see the skills repo for instructions.


๐Ÿ” Tool Discovery for AI Agents

By default, the full tool catalog (~84 tools) is listed to the client through the standard MCP tools/list response. Clients with deferred / on-demand tool loading (claude.ai, Claude Desktop, Claude Code) handle that fine โ€” tools are pulled into context only when needed, so idle context cost is near-zero.

For setups without deferred tool support โ€” models like Claude Haiku, Gemini, OpenAI-compatible local models and smaller open-weights models, or clients that inline all tool schemas regardless of model (e.g. GitHub Copilot CLI) โ€” listing the full tool catalog up front adds a lot of idle context and can overwhelm smaller models. To address that, the server ships with a search-based discovery mode built on top of FastMCP's BM25 search transform.

Smaller or local LLMs (Ollama, etc.)

If your model can't see the tools or your Home Assistant, it may be getting handed the whole tool catalog at once and struggling with it. It's recommended to try the following to see if it helps:

  • Enable tool search (ENABLE_TOOL_SEARCH=true, or the app option below). Instead of listing every tool up front, the server defers the catalog behind a search interface so the model pulls in only the tools it needs, when it needs them.

  • Raise the model's context window above the default. Local runtimes ship with small defaults (Ollama's num_ctx is one example) that can't hold a large tool set plus the conversation โ€” increase it well beyond the default.

Enable search-based discovery

Set ENABLE_TOOL_SEARCH=true (or toggle the option in the HA app). The full catalog is replaced in the tool list with four entry points plus a small set of always-visible "pinned" tools (ha_search, ha_get_overview, ha_report_issue, etc.). All tools remain callable directly by name once discovered:

Tool

Purpose

ha_search_tools

BM25 keyword search across all tools. Returns name, description, parameters, and annotations (readOnlyHint / destructiveHint) so the agent can pick the right one.

ha_call_read_tool

Execute a readOnlyHint tool by name. Safe โ€” clients can auto-approve.

ha_call_write_tool

Execute a write tool that creates or updates data.

ha_call_delete_tool

Execute a tool that removes / deletes data.

The proxy split lets MCP clients apply different permission policies per category (e.g. auto-approve reads, prompt for writes, confirm deletes) without parsing tool docstrings.

Setting

Default

Description

ENABLE_TOOL_SEARCH

false

Replace full tool catalog with search-based discovery (tools deferred behind on-demand search).

TOOL_SEARCH_MAX_RESULTS

5

Max results returned by ha_search_tools (range 2โ€“10).

PINNED_TOOLS

empty

Comma-separated tool names to keep always visible. The web settings UI is the primary way to manage this.

When to enable

  • Claude Haiku, OpenAI-compatible local models, Gemini, or any model without native deferred tool support โ€” large idle-context savings. The same applies to clients that inline all tool schemas regardless of model (e.g. GitHub Copilot CLI, even when running Claude Sonnet/Opus).

  • MCP clients that cap total tool count (some cap at 100) โ€” surfaces a minimal set (~10 tools) instead of 84.

  • Cost-sensitive deployments โ€” fewer idle tokens per turn.

Leave it off in clients with deferred tool loading (claude.ai, Claude Desktop, Claude Code); the full catalog has no idle cost there, direct calls skip the search step, and the client's built-in tool search is the better choice โ€” there is no benefit to running ha-mcp's on top of it. Whether tools are deferred depends on the client and model combination: the same model can behave differently per client โ€” GitHub Copilot CLI running Claude Sonnet/Opus inlines the full catalog and still benefits from tool search here. Some Codex models and ChatGPT include deferred tools too โ€” check your client/model directly to confirm its features so you don't leave this enabled unnecessarily.

๐Ÿ”„ Refresh your client's tool list after changing this (or any) setting. Toggling ENABLE_TOOL_SEARCH (or changing pinned/disabled tools, Read Only Mode, etc.) changes the tools the server exposes, but your AI client keeps serving its cached tool list until it re-fetches. Restarting the app or Home Assistant does not refresh the client โ€” reconnect or refresh the MCP server in your client (e.g. re-add/refresh the connector in ChatGPT, or close and reopen Claude Desktop). If you skip this, newly enabled tools won't appear in the client at all, and tools the server no longer exposes still show as available but return Unknown tool when called. ChatGPT sometimes keeps serving the stale list even after the connector is removed and re-added under the same name โ€” if tools are still missing after re-adding, delete the connector and create a new one with a different name.

For the HA app, the same option is documented in homeassistant-addon/DOCS.md along with the in-app settings UI for fine-grained tool enable/disable/pin.


๐Ÿงช Dev Channel

Want early access to new features and fixes? Dev releases (.devN) are published on every push to master.

Dev Channel Documentation โ€” Instructions for pip/uvx, Docker, and Home Assistant app.


๐Ÿค Contributing

For development setup, testing instructions, and contribution guidelines, see CONTRIBUTING.md.

For comprehensive testing documentation, see tests/README.md.


๐Ÿ”’ Privacy

Ha-mcp runs locally on your machine. Your smart home data stays on your network.

  • No telemetry today โ€” anonymous usage stats are a planned future feature (as of June 2026); when it lands it will follow your Home Assistant analytics/telemetry setting (which you can override), announced prominently in the release notes and the web Settings UI at least one month beforehand

  • No personal data collection โ€” we never collect entity names, configs, or device data

  • User-controlled bug reports โ€” only sent with your explicit approval

For full details, see our Privacy Policy.


๐Ÿ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.


๐Ÿ™ Acknowledgments

  • Home Assistant: Amazing smart home platform (!)

  • FastMCP: Excellent MCP server framework

  • Model Context Protocol: Standardized AI-application communication

  • Claude Code: AI-powered coding assistant

  • PolicyLayer: Argument-path predicate DSL shape (args.domain in [...] with eq/in/regex/contains/exists/...) inspired the per-tool approval rule schema (#966).

๐Ÿ‘ฅ Contributors

Maintainers

Contributors

  • @bigeric08 โ€” Explicit mcp dependency for protocol version 2025-11-25 support.

  • @airlabno โ€” Support for data field in schedule time blocks.

  • @ryphez โ€” Codex Desktop UI MCP quick setup guide.

  • @Danm72 โ€” Entity registry tools (ha_set_entity, ha_get_entity) for managing entity properties.

  • @Raygooo โ€” SOCKS proxy support.

  • @cj-elevate โ€” Integration & entity management tools (enable/disable/delete); person/zone/tag config store routing.

  • @maxperron โ€” Beta testing.

  • @kingbear2 โ€” Windows UV setup guide.

  • @konradwalsh โ€” Financial support via GitHub Sponsors. Thank you! โ˜•

  • @knowald โ€” Area resolution via device registry in ha_get_system_overview for entities assigned through their parent device. Financial support via GitHub Sponsors. Thank you! โ˜•

  • @zorrobyte โ€” Per-client WebSocket credentials in OAuth mode, fixing WebSocket tool failures.

  • @deanbenson โ€” Fixed ha_deep_search timeout on large Home Assistant instances with many automations.

  • @saphid โ€” Config entry options flow tools (initial design, #590).

  • @adraguidev โ€” Fix menu-based config entry flows for group helpers (#647).

  • @transportrefer โ€” Integration options inspection (ha_get_integration schema support, #689).

  • @teh-hippo โ€” Fix blueprint import missing save step.

  • @smenzer โ€” Documentation fix.

  • @The-Greg-O โ€” REST API for config entry deletion.

  • @restriction โ€” Responsible disclosure: python_transform sandbox missing call target validation.

  • @lcrostarosa โ€” Diagnostic and health monitoring tools concept (#675), inspiring system/error logs, repairs, and ZHA radio metrics integration.

  • @roysha1 โ€” Copilot CLI support in the installation wizard; replaced placeholder logo SVGs with real brand icons on the documentation site.

  • @teancom โ€” Fix add-on stats endpoint (/addons/{slug}/stats).

  • @TomasDJo โ€” Category support for automations, scripts, and scenes.

  • @bzelch โ€” python_transform support for automations and scripts.

  • @gcormier โ€” Windows installer improvements: removed unused variable and fixed terminal closing after install.

  • @ekobres โ€” Feature flags for HAMCP_ENABLE_FILESYSTEM_TOOLS and the (since removed) HAMCP_ENABLE_CUSTOM_COMPONENT_INTEGRATION in the app config, with beta tagging in source and docs.

  • @w3z315 โ€” Financial support via GitHub Sponsors. Thank you! โ˜•

  • @griffinmartin โ€” Added OpenCode (by Anomaly) as a selectable AI client in the setup wizard, with both stdio and streamable HTTP support.

  • @hhopke โ€” Fixed app (add-on) API calls to route through HA Core ingress proxy instead of direct container connections, fixing ha_manage_addon (now ha_manage_app) proxy mode on app installs.

  • @tomwilkie โ€” JMESPath middleware exploration (#1147) whose review-time token-measurement data informed the design of #1199 and #1225.

  • @SealKan โ€” fields=/attribute_keys= projection on six read-heavy tools (#1225), ha_call_event tool (#1239), dashboards-list helper refactor (#1207), for:-field duration-math detector in the best-practice checker (#1264), persistent DCR OAuth client registrations across restarts (#1265), and issue-triage prompt token-budgeting (#1522).

  • @KarelTestSpecial โ€” Cached YAML instance to prevent CPU spikes during bulk edits (#1371).

  • @corgan2222 โ€” HA brand assets for custom integration (#1317).

  • @drseanwing โ€” Progress emission via FastMCP Context in long-running tools (#1124); tool-discovery / categorized-search docs (#1123).

  • @fnordpig โ€” Config subentry support (#1393) and Assist pipeline management tool (#1392).

  • @paul43210 โ€” array_patch mode in ha_manage_app for atomic GET-modify-POST (#1063).

  • @L1AD โ€” Filed #966 proposing tool security policies; pointed to PolicyLayer's MCP-security work as prior art that inspired the predicate DSL shape.

  • @nightcityblade โ€” Updated stale Home Assistant Advanced Mode references after HA 2026.6 made formerly advanced options available by default (#1533).

  • @emmelutzer โ€” Financial support via GitHub Sponsors. Thank you! โ˜•

  • @pkkr โ€” ha_knx_get_project tool exposing KNX group addresses from an uploaded ETS project file.

  • @cbowns โ€” Fixed inconsistent hyphen in setup.astro Codex CLI docs.

  • @Shaan-alpha โ€” Extended ha_restart known-good error patterns to cover 502/503 responses from reverse proxies.

  • @rebelancap โ€” Fixed UTC-to-local timezone conversion in add_timezone_metadata.

  • @saevras โ€” Fixed blueprint import E2E test to use local URL instead of host-to-container networking.

  • @jasonjhofmann โ€” Recurring calendar events via rrule support in ha_config_set_calendar_event.

  • @vpciii โ€” Coerce JSON-encoded strings on dict/list tool params.

  • @pburtchaell โ€” Financial support via GitHub Sponsors. Thank you! โ˜•

  • @norpol โ€” Built the OpenAI Tunnel for HA-MCP companion integration, connecting ChatGPT to a firewalled Home Assistant MCP server (#1811).


๐Ÿ’ฌ Community


Star History

Available Tools

78 tools
ha_bulk_controlBulk ControlA
Destructive

Manage explicit operations or one deterministic structural bulk action.

When NOT to use: use ha_call_service for service-specific payloads or backend-native group targeting, and ha_search for fuzzy name discovery.

Operations mode (operations, no selector): put every target in this one call. Parallel execution is the default, and invalid items are reported without aborting valid operations in the same batch โ€” but a batch in which every item fails validation dispatches nothing and fails the call. A batch that targets a group/aggregate entity together with one or more of its own individual members also fails closed (nothing dispatched): Home Assistant applies the action to every member when the group is targeted regardless of what else is listed, so a member row cannot exclude that member from the group's own action. Use selector mode with exclude_entity_ids when a group action must exclude specific members.

Selector mode (selector + action): use exact area or floor IDs when exclusions must be applied after recursively expanding generic aggregate membership. Resolves a frozen visible leaf set before dispatch; it is not transactional, so Home Assistant may still report per-leaf failures. A selector resolving to more than 100 entities (MAX_SELECTOR_ENTITIES) fails closed instead of dispatching a partial/oversized batch โ€” narrow it (a more specific area/floor, or add exclude_entity_ids) and retry. Set dry_run to preview the resolved set without changing state.

ParametersJSON Schema
NameRequiredDescriptionDefault
actionNoOne device action applied to every resolved leaf.
dry_runNo
parallelNo
selectorNoOptional exact structural scope using domain plus area_ids and/or floor_ids, with optional exclude_entity_ids.
operationsNoExplicit entity operations. Use this or selector, never both. Each item requires exact entity_id and action. Use action='off', not service='turn_off'.
parametersNoOptional action parameters for selector mode.
validate_firstNo
timeout_secondsNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only carry destructiveHint=true and openWorldHint=false, so the description bears the burden of behavioral disclosure โ€” and it delivers richly: parallel-by-default execution, invalid items not aborting valid ones, all-fail batches dispatching nothing, group+member batch failing closed, non-transactional selector dispatch, the 100-entity MAX_SELECTOR_ENTITIES fail-closed cap, and dry_run semantics. This far exceeds what the annotations alone communicate.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but front-loaded: purpose first, then when-not-to-use, then mode-specific behavior in labeled sections. Every paragraph carries non-obvious failure semantics that an agent needs before calling. The density is justified by the tool's complexity (two modes, 8 params, multiple failure modes), though it is heavier than the leanest possible version.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a high-complexity tool with 8 parameters, two mutually exclusive modes, and destructive behavior, the description covers all decision-relevant context: mode selection, failure behavior, group/member edge cases, entity-count limits, retry guidance, and dry_run. An output schema exists, so return-value documentation is not required. The only minor omission is top-level validate_first/timeout_seconds semantics, which are addressed in the nested schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With only 50% schema description coverage (dry_run, parallel, validate_first, and timeout_seconds lack top-level schema descriptions), the description compensates by explaining mode-level semantics: which params combine (operations without selector; selector + action), what exclude_entity_ids does after recursive expansion, what dry_run previews, and the shared timeout behavior. It does not explicitly walk through every top-level parameter, but the gaps are mostly covered by the nested operations schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a clear purpose โ€” managing explicit operations or one deterministic structural bulk action โ€” and immediately distinguishes itself from siblings by naming ha_call_service and ha_search in the 'When NOT to use' section. The two-mode structure (operations vs. selector) gives an agent a precise mental model of what the tool does and what it is not.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit when-not-to-use guidance names the exact alternative tools and the conditions that select them: ha_call_service for service-specific payloads/backend-native group targeting, ha_search for fuzzy discovery. It also gives conditional routing within the tool itself, e.g., 'Use selector mode with exclude_entity_ids when a group action must exclude specific members' and 'narrow it ... and retry' for oversized selectors.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_call_eventCall EventA
Destructive

Execute a custom event on the Home Assistant event bus.

When NOT to use: for controlling entities (lights, switches, climate) โ€” use ha_call_service instead. For triggering automations by name, use ha_call_service("automation", "trigger").

Use this to publish custom event types consumed by event-triggered automations, Node-RED flows, or custom integrations that subscribe to specific event types.

Caveats: Events are fire-and-forget; this tool confirms the event was accepted by the bus but does not verify whether any automation or subscriber acted on it.

ParametersJSON Schema
NameRequiredDescriptionDefault
dataNo
event_typeYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond annotations (destructiveHint=true), the description reveals fire-and-forget behavior and that tool confirms bus acceptance but not subscriber action. This adds value and does not contradict annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with a clear first sentence, usage guidelines section, and caveats. It is concise with no wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple tool with two parameters and output schema, the description covers purpose, usage, exclusions, and behavioral caveats. It is fully adequate for an agent to correctly invoke the tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description conveys the meaning of event_type (custom event type) and data (optional payload) through context, though it does not explicitly name or detail each parameter.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it executes a custom event on the Home Assistant event bus, providing a specific verb and resource. It also explicitly distinguishes itself from sibling tools like ha_call_service by stating when not to use.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit when-to-use and when-not-to-use guidance, including specific alternatives (ha_call_service for entity control and automation triggering). It also describes the intended use case for event-triggered automations.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_call_serviceCall ServiceA
Destructive

Execute Home Assistant services to control entities and trigger automations.

This is the universal tool for controlling all Home Assistant entities. Services follow the pattern domain.service (e.g., light.turn_on, climate.set_temperature).

Basic Usage:

# Turn on a light
ha_call_service("light", "turn_on", entity_id="light.living_room")

# Set temperature with parameters
ha_call_service("climate", "set_temperature",
              entity_id="climate.thermostat", data={"temperature": 22})

# Trigger automation
ha_call_service("automation", "trigger", entity_id="automation.morning_routine")

# Universal controls work with any entity
ha_call_service("homeassistant", "toggle", entity_id="switch.porch_light")

Key behavior:

  • Result compaction (default ON): result is trimmed to the targeted entity's record (drops parent-group propagation) and stripped of context / last_* metadata and heavy attribute lists (effect_list, hue_scenes). Escape hatches: verbose=True for the raw changed-state records, or result_fields / result_attribute_keys for explicit per-record projection (mirrors ha_get_state).

For detailed service documentation, use ha_get_skill_guide.

Common patterns: Use ha_get_state() to check current values before making changes. Use ha_search() to find correct entity IDs.

WebSocket command escape hatch (advanced): A few Home Assistant operations are WebSocket-only commands, not registered services โ€” most notably dismissing a Repairs issue. Pass ws_command (instead of domain/service) to send one, with its parameters in data:

# Dismiss a repair (get domain/issue_id from ha_get_overview repairs
# or ha_get_system_health include="repairs")
ha_call_service(ws_command="repairs/ignore_issue",
                data={"domain": "sun", "issue_id": "abc", "ignore": True})

Only one-shot request/response commands are supported; streaming/two-phase and service-invoking commands are rejected, and the other service parameters (entity_id, return_response, etc.) don't apply.

ParametersJSON Schema
NameRequiredDescriptionDefault
dataNoExtra service-call parameters beyond entity_id (e.g. {'temperature': 22} for climate.set_temperature). Also carries the raw command payload when ws_command is set. If entity_id is also present in data, the entity_id parameter wins.
waitNoIf True (default), wait for the entity state to change before returning. Applies only to state-changing services called with a single entity_id. A comma-separated multi-target does not get confirmed by this: it falls through to a legacy path that polls for the literal composite entity_id and times out after 10s. Set wait=False for multi-target calls.
domainNoService domain (e.g. 'light', 'climate', 'automation'). Required for a service call; must be omitted when ws_command is set.
serviceNoService name within domain (e.g. 'turn_on', 'set_temperature', 'trigger'). Required for a service call; must be omitted when ws_command is set.
verboseNoReturn HA's raw changed-state records unchanged (default: False). Use as an escape hatch when you need the full propagation chain or raw attribute payload (debug / inspection). With return_response=True the response data still surfaces once as the top-level service_response key, never nested in result. WARNING: brings back token-bloat for nested-group targets โ€” prefer result_fields / result_attribute_keys for targeted control.
entity_idNoEntity ID(s) the service call targets โ€” one ID ('light.living_room') or several comma-separated ('light.a,light.b'). Optional for services that don't target a specific entity. Must be omitted when ws_command is set.
ws_commandNoAdvanced escape hatch: send a raw one-shot Home Assistant WebSocket command that is NOT a registered service (e.g. 'repairs/ignore_issue' to dismiss a Repairs issue). When set, omit domain/service and the other service params; put the command's parameters in data. Streaming/two-phase and service-invoking commands (call_service, execute_script) are rejected.
result_fieldsNoProject each record in 'result' to only these top-level keys (e.g. ['entity_id', 'state']). Mirrors ha_get_state's fields=. Setting this DISABLES default compaction โ€” no entity-id filter, no metadata strip โ€” and applies the explicit projection instead.
return_responseNoIf True, the service's response data is returned once, as the top-level 'service_response' key โ€” never nested inside 'result' (default: False). Must stay False when ws_command is set.
result_attribute_keysNoProject each record's 'attributes' dict to only these keys (e.g. ['brightness', 'rgb_color']). Mirrors ha_get_state's attribute_keys=. Setting this DISABLES default compaction. Requires 'attributes' to be present in result_fields (or result_fields=None).

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the destructiveHint annotation, the description discloses significant behavior: result compaction defaults, verbose/projection escape hatches, WebSocket command limitations, the multi-target wait timeout fallback, and the priority of entity_id over data. This gives an agent a strong model of what happens when the tool is invoked.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but well-structured with clear sections, code examples, and front-loaded purpose. It is appropriately detailed for a universal 10-parameter tool with multiple modes. Minor redundancy with the schema's parameter descriptions keeps it from being perfect.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex tool with 10 parameters, an output schema, and multiple invocation modes, the description covers everything an agent needs: basic usage, common patterns, result-format behavior, escape hatches, and WebSocket restrictions. The output schema covers return values, so that omission is not a gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description adds value by showing parameter combinations in worked examples, explaining when ws_command replaces domain/service, and clarifying how result_fields/result_attribute_keys interact with default compaction. This is useful context beyond the raw schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('Execute Home Assistant services to control entities and trigger automations') and the resource ('all Home Assistant entities'). It gives the domain.service pattern and concrete examples, making it easy to distinguish from sibling tools like ha_call_event or ha_get_state.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear usage context: use ha_get_state() before changes, ha_search() for entity IDs, and ha_get_skill_guide for detailed service docs. It also explains when the WebSocket escape hatch is needed. However, it does not explicitly call out alternatives like ha_bulk_control or ha_call_event for batch or event-specific operations.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_config_delete_dashboardDelete DashboardA
Destructive

Delete a storage-mode dashboard completely.

WARNING: This permanently deletes the dashboard and all its configuration. Cannot be undone. Does not work on YAML-mode dashboards.

Accepts either the URL path or the internal dashboard ID. HA internal IDs may differ from url_path (e.g. hyphens โ†’ underscores); the tool resolves either form to the actual registry ID before deletion.

EXAMPLES:

  • Delete dashboard: ha_config_delete_dashboard("mobile-dashboard")

Note: The default dashboard cannot be deleted via this method.

ParametersJSON Schema
NameRequiredDescriptionDefault
url_pathYesDashboard URL path or internal ID to delete (e.g., 'my-dashboard' or 'my_dashboard'). Both forms are accepted.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate destructiveHint=true, but the description adds critical details: permanent deletion, irreversibility, ID resolution behavior, and the restriction on default dashboard. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise and well-structured with a clear warning, bullet-point-like explanation, an example, and a note. Every sentence contributes meaning without redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's simplicity (single parameter, destructive operation) and the presence of output schema (not shown but indicated), the description covers all necessary aspects: purpose, limitations, parameter details, and an example. No missing information for an AI agent to use it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The single parameter url_path is fully covered by schema (100%), but the description adds important context: it accepts both URL path and internal ID, explains hyphens vs underscores, and notes the tool resolves to actual registry ID. This adds value beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool deletes a storage-mode dashboard permanently, using a specific verb and resource. It distinguishes from siblings by specifying it works only on storage-mode dashboards, not YAML-mode, and mentions the default dashboard cannot be deleted.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly states when to use (delete storage-mode dashboards) and when not to (YAML-mode, default dashboard). It does not name alternative tools explicitly, but the context implies alternatives like editing config files for YAML-mode.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_config_delete_dashboard_resourceDelete Dashboard ResourceA
Destructive

Delete a dashboard resource.

Removes a resource from Home Assistant. The resource will no longer be loaded on dashboards.

WARNING: Deleting a resource used by custom cards in your dashboards will cause those cards to fail to load.

EXAMPLES: ha_config_delete_dashboard_resource(resource_id="abc123")

Note: Use ha_config_list_dashboard_resources() to find resource IDs before deleting. Ensure no dashboards depend on the resource.

ParametersJSON Schema
NameRequiredDescriptionDefault
resource_idYesResource ID to delete. Get from ha_config_list_dashboard_resources()

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations include destructiveHint: true. The description adds important behavioral context: warns that deleting used resources will cause custom cards to fail to load, which goes beyond the annotation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Concise: action stated first, warning, example, and note. No superfluous words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Complete for a single-parameter delete tool. Covers what happens, prerequisite, example, and warnings. Output schema exists for return values.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema covers resource_id with description. Description reinforces with example and advice to get ID from list function. Adds value beyond schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Delete a dashboard resource' and explains it removes a resource from Home Assistant. It distinguishes from siblings like ha_config_set_dashboard_resource and ha_config_list_dashboard_resources.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides context for when to use (to delete a resource), a warning about consequences, and an example. Mentions using ha_config_list_dashboard_resources() to find IDs, but doesn't explicitly state when not to use or mention alternatives beyond listing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_config_get_automationGet Automation ConfigA
Read-onlyIdempotent

Retrieve Home Assistant automation configuration.

Returns the complete configuration including triggers, conditions, actions, and mode settings.

The returned config_hash is stable across consecutive reads of an unchanged config โ€” compute_config_hash documents the underlying contract.

The returned automation_id is the resolved entity_id (canonical form, e.g. automation.morning_routine) when the registry lookup succeeds, falling back to the input identifier otherwise.

EXAMPLES:

  • Get automation: ha_config_get_automation("automation.morning_routine")

  • Get by unique_id: ha_config_get_automation("my_unique_automation_id")

For comprehensive automation documentation, use ha_get_skill_guide.

read inspect fetch view existing automation config triggers conditions actions get show detail

ParametersJSON Schema
NameRequiredDescriptionDefault
identifierYesAutomation entity_id (e.g., 'automation.morning_routine') or unique_id

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Adds value beyond annotations by explaining config_hash stability across reads, automation_id resolution with fallback, and that it returns the complete config. No contradictions with readOnlyHint and idempotentHint.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well-structured with sections for examples and details. Slightly verbose but not excessive; every sentence adds value. Front-loaded with purpose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the output schema existence and annotations, the description fully explains return fields (config_hash, automation_id) and behavior. No gaps for a get config tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, and description adds meaning by describing identifier as 'Automation entity_id (e.g., 'automation.morning_routine') or unique_id' with examples. Well-explained.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Retrieve Home Assistant automation configuration' and details what is returned (triggers, conditions, actions, mode). It distinguishes from sibling tools like ha_config_set_automation (write) and ha_config_remove_automation (delete) by being a read operation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides examples for calling with entity_id or unique_id, and directs to ha_get_skill_guide for comprehensive docs. While not explicitly stating when not to use, the read-only nature is clear, and examples cover typical usage.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_config_get_calendar_eventsGet Calendar EventsA
Read-onlyIdempotent

Retrieve calendar events from a calendar entity.

Retrieves calendar events within a specified time range.

Parameters:

  • entity_id: Calendar entity ID (e.g., 'calendar.family')

  • start: Start datetime in ISO format (default: now)

  • end: End datetime in ISO format (default: 7 days from start)

  • max_results: Maximum number of events to return (default: 20)

Example Usage:

# Get events for the next week
events = ha_config_get_calendar_events("calendar.family")

# Get events for a specific date range
events = ha_config_get_calendar_events(
    "calendar.work",
    start="2024-01-01T00:00:00",
    end="2024-01-31T23:59:59"
)

Note: To find calendar entities, use ha_search(query='calendar', domain_filter='calendar')

Returns:

  • List of calendar events with summary, start, end, description, location

ParametersJSON Schema
NameRequiredDescriptionDefault
endNoEnd datetime in ISO format (default: 7 days from start)
startNoStart datetime in ISO format (default: now)
entity_idYesCalendar entity ID (e.g., 'calendar.family')
max_resultsNoMaximum number of events to return

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond annotations (readOnlyHint, idempotentHint), the description details defaults for start/end, max_results, and the return format (list with fields). This adds operational context not captured by annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with clear sections: purpose, parameters, example, note, and returns. It is concise and front-loaded, every sentence adds value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the low complexity, full schema coverage, and presence of output schema, the description is complete. It explains purpose, parameters, defaults, example usage, and suggests how to find entity IDs.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3. The description repeats schema descriptions but adds practical context through example usage and a note on finding entities, which provides extra meaning for an AI agent.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'Retrieve' and the resource 'calendar events' from a calendar entity. It is distinct from sibling tools 'ha_config_remove_calendar_event' and 'ha_config_set_calendar_event', making the purpose unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides a note on finding calendar entities via 'ha_search' and shows example usage. While it does not explicitly state when not to use, the context of read-only operation is clear from annotations and sibling names.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_config_get_categoryGet CategoryA
Read-onlyIdempotent

Get category info - list all categories for a scope or get a specific one by ID.

Without a category_id: Lists all Home Assistant categories for the given scope. With a category_id: Returns configuration for that specific category.

Categories are domain-scoped organizational groups for automations, scripts, scenes, and helpers.

CATEGORY PROPERTIES:

  • ID (category_id), Name

  • Icon (optional)

EXAMPLES:

  • List automation categories: ha_config_get_category("automation")

  • List script categories: ha_config_get_category("script")

  • List helper categories: ha_config_get_category("helpers")

  • Get specific category: ha_config_get_category("automation", category_id="my_category_id")

Use ha_config_set_category() to create or update categories. Use ha_set_entity(categories={"automation": "category_id"}) to assign categories to entities.

ParametersJSON Schema
NameRequiredDescriptionDefault
scopeYesDomain scope for categories (e.g., 'automation', 'script', 'scene', 'helpers').
category_idNoID of the category to retrieve. If omitted, lists all categories for the scope.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and idempotentHint=true, indicating a safe, idempotent read. The description confirms read-only behavior (lists, returns configuration). Discloses domain-scoped nature. Does not contradict annotations. Adds details about optional icon, but could mention that the output schema exists (though not shown).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well-organized with sections (overview, properties, examples, related tools). About 10 sentences, but each sentence adds value. Could be slightly more concise by merging the examples into a list, but overall efficient and front-loaded with purpose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's simplicity (2 params) and the presence of an output schema (not shown but context indicates coverage), the description covers all behavioral aspects: parameter behavior, returned properties, usage examples, and even mentions external methods for creation and assignment. It is contextually complete for an agent to invoke correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with both parameters documented. The description adds significant value beyond the schema: clarifies behavior based on category_id presence, lists the returned properties (ID, Name, Icon) not in schema, and provides concrete examples showing parameter usage and expected outputs.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description explicitly states the tool lists categories for a scope or gets a specific one by ID. It distinguishes itself from sibling tools like ha_config_set_category (create/update) and ha_set_entity (assign to entities). The verb+resource is clear and specific.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides clear when-to-use guidance: without category_id lists all categories for a scope, with category_id returns specific. Includes multiple examples. References ha_config_set_category for creating/updating and ha_set_entity for assigning, giving alternatives and related operations.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_config_get_dashboardGet DashboardA
Read-onlyIdempotent

Get dashboard info - list all dashboards, get config, or search for cards.

MODE 1 โ€” List: list_only=True Lists every dashboard's metadata (url_path, title, icon), storage and YAML alike (metadata only โ€” bodies are never included here).

MODE 2 โ€” Search: any of entity_id / card_type / heading provided Finds cards, badges, and header cards matching the criteria, including cards nested inside stacks, grids, conditional cards, button-card custom_fields, and state-switch states. Each match carries a python_path and a jq_path that locate the card for nested as well as top-level cards. The python_path is a Python subscript chain to be appended after config โ€” e.g. python_transform=f'config{m["python_path"]}["icon"] = "mdi:x"' (it is NOT valid on its own without the config prefix). jq_path is the same location in jq dot-notation. Multiple criteria are AND-ed. Always fetches fresh config (force=True). Search covers cards/card/custom_fields/states containers up to a depth bound; if the dashboard carries a non-traversed child-bearing shape (e.g. picture-elements elements), the result carries a warnings entry naming where, so its hidden content is not mistaken for absent. Strategy dashboards are not searchable (no explicit cards).

MODE 3 โ€” Get: Active when list_only=False and no search parameters are provided. Returns the full Lovelace dashboard config, defaulting to the main dashboard if url_path is omitted. Pass view_path=<views[].path> to return ONLY that view: the response then carries view + view_index instead of config, keeping the payload small on multi-view dashboards. config_hash still covers the FULL config, so a follow-up ha_config_set_dashboard(python_transform=...) addressing config['views'][view_index] validates unchanged. An unknown view_path errors and lists the available view paths. include_screenshot=True also returns rendered image(s) of the dashboard (beta feature); when you only need the render and not the config, use the dedicated ha_get_dashboard_screenshot tool instead.

MODE 4 โ€” Search all: mode="search" with query= Answers "which dashboards contain this entity/card" by walking every storage-mode dashboard's views/cards/sections for the query substring. Each match names the url_path, view, card_path, card_type, and the matched field/value. Takes precedence over the other modes (list_only / entity_id / card_type / heading are ignored when mode="search"). YAML-mode dashboards are never searched on either path โ€” the component walk skips them in-process and the component-less legacy walk skips any row tagged mode="yaml" โ€” because HA resolves !secret when loading a YAML Lovelace config, so searching one could surface resolved secrets. On installs without the ha_mcp_tools component, the default (unnamed) dashboard is also not searched โ€” only dashboards with a url_path are.

Return a stable config_hash (Get and Search modes only; not present in list_only mode) across consecutive reads of an unchanged config โ€” compute_config_hash documents the underlying contract.

EXAMPLES:

  • List all dashboards: ha_config_get_dashboard(list_only=True)

  • Get default dashboard: ha_config_get_dashboard(url_path="default")

  • Get custom dashboard: ha_config_get_dashboard(url_path="lovelace-mobile")

  • Get one view only: ha_config_get_dashboard(url_path="lovelace-mobile", view_path="office")

  • Force reload: ha_config_get_dashboard(url_path="lovelace-home", force_reload=True)

  • Find cards by entity: ha_config_get_dashboard(url_path="my-dash", entity_id="light.living_room")

  • Find by wildcard: ha_config_get_dashboard(url_path="my-dash", entity_id="sensor.temperature_*")

  • Find by type: ha_config_get_dashboard(url_path="my-dash", card_type="tile")

  • Find heading: ha_config_get_dashboard(url_path="my-dash", heading="Climate", card_type="heading")

SEARCH WORKFLOW EXAMPLE:

  1. find = ha_config_get_dashboard(url_path="my-dash", entity_id="light.bedroom")

  2. ha_config_set_dashboard( url_path="my-dash", config_hash=find["config_hash"], python_transform=f'config{find["matches"][0]["python_path"]}["icon"] = "mdi:lamp"' )

Note: YAML-mode dashboards (defined in configuration.yaml) are not included in list.

ParametersJSON Schema
NameRequiredDescriptionDefault
modeNoSet to 'search' for a CROSS-dashboard search: which dashboards contain a given entity_id or text (requires query). Leave unset for the default list/get/single-dashboard-search behavior selected by list_only / entity_id / card_type / heading.
queryNoWith mode='search': the entity_id or substring to find across all storage-mode dashboards. Ignored otherwise.
headingNoFind cards by heading/title text (case-insensitive partial match). When provided, activates search mode.
url_pathNoDashboard URL path (e.g., 'lovelace-home'). Use 'default' for default dashboard. If omitted with list_only=True, lists all dashboards.
card_typeNoFind cards by type, e.g. 'tile', 'button', 'heading'. When provided, activates search mode.
entity_idNoFind cards by entity ID. Supports wildcards, e.g. 'sensor.temperature_*'. Matches cards with this entity in 'entity' or 'entities' field, view-level badges, and header cards. When provided, activates search mode (returns matches, not full config).
list_onlyNoIf True, list all dashboards instead of getting config. When True, url_path is ignored.
view_pathNoGet mode: return ONLY the view whose Lovelace views[].path matches (response carries 'view' + 'view_index' instead of the full 'config') โ€” use this to keep multi-view dashboards from blowing up the response when you only need one view. Does not require any beta feature. With include_screenshot, also selects the view to render. Ignored in list/search mode. Omit for the full config.
force_reloadNoForce reload from storage (bypass cache). Not applicable in search mode (search always uses force=True for fresh results).
include_configNoIn search mode: include each matched card's own configuration object in results (increases output size). Note that a matched container card's config contains its descendants, which are themselves separate matches with their own config, so deeply-nested stacks multiply the payload โ€” keep the default (False) unless you need the bodies. Does not affect whether the full dashboard config is returned โ€” search mode always returns matches only, not the full dashboard. Config bodies are surfaced only for dashboards provably in storage mode; for a YAML or unconfirmed dashboard the bodies are withheld (they may carry resolved !secret values) and the response says so, with match locations still reported. Ignored outside search mode.
include_screenshotNoGet mode only: also return rendered image(s) of the dashboard for visual verification. Requires the 'dashboard screenshot' beta feature + engine add-on/sidecar. If the feature is disabled the config is returned with a warning; if the engine is configured but the render fails, the call errors (the screenshot is the requested payload). Ignored in list/search mode. When you already have the config and only need the render, use the dedicated ha_get_dashboard_screenshot tool (registered when the same beta feature is on) โ€” it returns images without echoing the config.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and idempotentHint; the description adds substantial non-obvious behavior on top: search 'Always fetches fresh config (force=True)', YAML dashboards are never searched because 'searching one could surface resolved secrets', config bodies are withheld for unconfirmed storage mode, unknown view_path errors and 'lists the available view paths', and non-traversed shapes produce a `warnings` entry so hidden content 'is not mistaken for absent'. This is far beyond what annotations convey.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long, but the length is earned: 11 parameters and 4 modes make it genuinely complex. MODE headers, a leading summary sentence, and grouped EXAMPLES make navigation easy. Minor redundancy exists โ€” the screenshot guidance appears in both MODE 3 and the include_screenshot parameter โ€” so it is not maximally tight, but no sentence is wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with no output schema and no required parameters, the description covers everything an agent needs: return shapes per mode (metadata vs matches with python_path/jq_path vs config vs view+view_index), config_hash stability contract, error conditions, security caveats, and cross-tool workflow. The only thing absent is a literal response schema, which is not the description's job in this exercise.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3, but the description adds real semantic value for parameters: mode precedence over list_only/entity_id/card_type/heading, view_path returning 'view' + 'view_index' while 'config_hash still covers the FULL config', include_config's descendant-multiplication caveat, and the python_path requiring a `config` prefix to be valid. These behaviors are not derivable from the schema alone.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opening sentence names a specific verb and resource ('Get dashboard info - list all dashboards, get config, or search for cards') and then enumerates four distinct modes with their activation conditions. The read-only purpose is immediately distinguishable from siblings like ha_config_set_dashboard and ha_config_delete_dashboard.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly routes to alternatives: 'use the dedicated ha_get_dashboard_screenshot tool instead' when only a render is needed (stated twice), and the SEARCH WORKFLOW EXAMPLE shows chaining with ha_config_set_dashboard. It also gives precise mode-selection rules ('Takes precedence over the other modes', 'Active when list_only=False and no search parameters are provided') plus exclusions (YAML dashboards, strategy dashboards, default dashboard without the component).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_config_get_labelGet LabelA
Read-onlyIdempotent

Get label info - list all labels or get a specific one by ID.

Without a label_id: Lists all Home Assistant labels with their configurations. With a label_id: Returns configuration for that specific label.

LABEL PROPERTIES:

  • ID (label_id), Name

  • Color (optional), Icon (optional), Description (optional)

EXAMPLES:

  • List all labels: ha_config_get_label()

  • Get specific label: ha_config_get_label("my_label_id")

Use ha_config_set_label() to create or update labels. Use ha_set_entity(labels=["label1", "label2"]) to assign labels to entities.

ParametersJSON Schema
NameRequiredDescriptionDefault
label_idNoID of the label to retrieve. If omitted, lists all labels.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already provide readOnlyHint and idempotentHint, but description adds value by listing label properties and explaining dual behavior (list vs fetch). No contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well-structured with sections, examples. Every sentence adds essential information without fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given low complexity, full schema coverage, and presence of output schema, description is complete with usage, alternatives, and examples.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, but description adds meaning: omitting label_id lists all, providing it fetches specific. Also lists returned properties.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description clearly states it gets label info, lists all labels or a specific one by ID. Differentiates from sibling tools like ha_config_set_label and ha_set_entity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states when to use with or without label_id, provides examples, and mentions alternative tools for create/update and assigning labels.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_config_get_sceneGet Scene ConfigA
Read-onlyIdempotent

Retrieve Home Assistant scene configuration.

Returns the complete configuration for a scene, including the entities dict and other settings (name, icon, id).

EXAMPLES:

  • Get scene: ha_config_get_scene("movie_night")

  • Get scene: ha_config_get_scene("bedroom_dim")

RELATED TOOLS:

  • ha_config_set_scene โ€” pass the returned config_hash for python_transform updates.

For detailed scene configuration help, use ha_get_skill_guide.

ParametersJSON Schema
NameRequiredDescriptionDefault
scene_idYesScene identifier (e.g., 'movie_night')

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate readOnlyHint and idempotentHint. Description adds that it returns complete config including entities dict and other settings. No contradictions. Sufficiently transparent beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two concise sentences for main description, plus examples and related tools in a well-structured format. Every sentence adds value, no fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given output schema exists and annotations are rich, description is complete for a read-only retrieval tool: purpose, return fields, examples, and related modifications covered.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema has 100% coverage with clear description for scene_id. Examples reinforce usage but description adds little beyond schema. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Explicitly states 'Retrieve Home Assistant scene configuration' with clear verb and resource. Distinguishes from sibling ha_config_set_scene. Specifies return fields (entities, name, icon, id).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides examples and related tools section pointing to ha_config_set_scene and mentions passing config_hash for updates. Though no explicit 'when not to use', the context and examples give sufficient guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_config_get_scriptGet Script ConfigA
Read-onlyIdempotent

Retrieve Home Assistant script configuration.

Returns the complete configuration for a script, including sequence, mode, fields, and other settings.

The returned config_hash is stable across consecutive reads of an unchanged config โ€” compute_config_hash documents the underlying contract.

The returned script_id is the canonical bare storage key resolved by the REST client (matching what ha_config_set_script / ha_config_remove_script expect), falling back to the input identifier on the rare path where the REST envelope omits it. A leading script. prefix on the input is stripped before lookup โ€” behavioral parity with ha_config_get_automation (mechanism differs: automations resolve via state lookup; scripts strip the prefix).

EXAMPLES:

  • Get script (bare form): ha_config_get_script("morning_routine")

  • Get script (entity_id form): ha_config_get_script("script.morning_routine")

For detailed script configuration help, use ha_get_skill_guide.

read inspect fetch view existing script config sequence actions get show detail

ParametersJSON Schema
NameRequiredDescriptionDefault
script_idYesScript identifier โ€” bare storage key ('morning_routine') or entity_id form ('script.morning_routine'); a leading 'script.' prefix is stripped before lookup.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Adds rich behavioral details beyond annotations: config_hash stability contract, script_id resolution fallback, prefix stripping mechanism. The annotations already mark idempotent and read-only, which the description complements without contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well-structured with clear sections and examples. The trailing keyword list ('read inspect fetch...') is slightly extraneous but does not detract from clarity. Overall concise and front-loaded with the core purpose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the existence of an output schema (not shown but assumed comprehensive), the description provides sufficient context on return values (config_hash, script_id) and behavior. Mentions skill guide for further help, completing the user's informational needs.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema covers script_id with 100% documentation, but the description adds significant value by explaining the returned script_id resolution, prefix stripping, and behavioral parity with ha_config_get_automation, enhancing the parameter meaning beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Explicitly states 'Retrieve Home Assistant script configuration' and details the returned content (sequence, mode, fields). Distinguishes from sibling tools like ha_config_set_script and ha_config_remove_script by referencing them in the script_id resolution behavior.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides clear usage context with input examples and notes about prefix stripping. Mentions ha_get_skill_guide for detailed help. Does not explicitly state when not to use this tool, but the read-only nature and sibling relationships are implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_config_list_dashboard_resourcesList Dashboard ResourcesA
Read-onlyIdempotent

List Lovelace dashboard resources (custom cards, themes, CSS/JS).

Returns one page of registered resources; total_count and has_more report the full set. For inline resources (created with ha_config_set_dashboard_resource(content=...)), shows a preview of the content instead of the full encoded URL to save tokens.

inline_count and by_type summarise every resource, not just this page.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMax resources to return per page (default: 100)
offsetNoNumber of resources to skip for pagination (default: 0)
include_contentNoInclude full decoded content for inline resources. Default False to save tokens (shows 150-char preview instead).

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations indicate readOnlyHint, openWorldHint, and idempotentHint. The description adds valuable behavioral details: pagination via 'one page' and 'total_count'/'has_more', preview for inline resources to save tokens, and summary fields. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise (three sentences) with the main purpose in the first sentence. Every sentence provides essential information without redundancy. It is well-structured and front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the presence of an output schema, the description covers key return fields (total_count, has_more, inline_count, by_type) and explains inline resource behavior. It is sufficient for an agent to use the tool correctly, though it does not detail every field in the output.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3. The description enhances parameter understanding by explaining the practical effect of 'include_content' (preview vs. full content to save tokens), adding context not in the schema. This adds meaningful value beyond the schema alone.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool lists Lovelace dashboard resources and specifies types (custom cards, themes, CSS/JS). It is distinct from sibling list tools like ha_config_list_helpers, but lacks explicit differentiation. However, the purpose is unambiguous and well-communicated.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage (listing registered resources) but does not provide explicit when-to-use or when-not-to-use guidance. It does not mention alternatives like ha_config_set_dashboard_resource or ha_config_delete_dashboard_resource, leaving the agent to infer appropriate contexts.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_config_list_groupsList GroupsA
Read-onlyIdempotent

List Home Assistant entity groups with their member entities.

Returns one page of groups created via group.set service or YAML configuration; total_count and has_more report the full set. Each group includes:

  • Entity ID (group.xxx)

  • Friendly name

  • State (on/off based on member states)

  • Member entities

  • Icon (if set)

  • All mode (if all entities must be on)

EXAMPLES:

  • First page of groups: ha_config_list_groups()

  • Next page: ha_config_list_groups(offset=100)

NOTE: This returns old-style groups (created via group.set or YAML). Platform-specific groups (light groups, cover groups) are separate entities.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMax groups to return per page (default: 100)
offsetNoNumber of groups to skip for pagination (default: 0)

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, and openWorldHint. The description adds significant behavioral context: pagination (one page, limit/offset, total_count and has_more reporting), and the specific fields returned. No contradictions with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise and well-structured: a clear opening sentence, a bullet list of returned fields, two examples, and a clarifying note. Every sentence is necessary and earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the presence of an output schema, comprehensive annotations, and the description covering purpose, pagination, scope, and field list, the description is complete. No gaps are evident for this tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with descriptions for limit and offset. The description adds value by explaining pagination behavior ('one page' and examples showing usage), which goes beyond the schema's parameter descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'List Home Assistant entity groups with their member entities,' specifying the verb and resource. It differentiates from sibling tools by noting that this returns old-style groups created via group.set or YAML, while platform-specific groups are separate entities.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implicitly provides usage context: it is for listing old-style groups, and platform-specific groups are not included. However, it lacks explicit 'when to use' vs alternatives or 'when not to use' guidance, though the note offers some differentiation.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_config_list_helpersList HelpersA
Read-onlyIdempotent

List Home Assistant helpers of a specific type with their configurations.

Returns one page of helpers; total_count and has_more report the full set. Each record carries the complete configuration for its helper, including:

  • id (immutable storage key), entity_id (current โ€” address the helper by this, where available), name (current display name), original_name (creation-time name), icon

  • Type-specific settings (min/max for input_number, options for input_select, etc.)

  • Area and label assignments

For a helper renamed in the UI, id/original_name keep the storage values while entity_id/name reflect the current entity registry (entity_id is the identifier ha_config_set_helper resolves against, so prefer it over id for a renamed helper). entity_id/original_name are present only for storage-collection helpers matched in the entity registry โ€” types with no backing entity (e.g. tag), and every record when the registry read degrades, carry only id/name (a warning flags the degraded case).

SUPPORTED HELPER TYPES:

  • input_button: Virtual buttons for triggering automations

  • input_boolean: Toggle switches/checkboxes

  • input_select: Dropdown selection lists

  • input_number: Numeric sliders/input boxes

  • input_text: Text input fields

  • input_datetime: Date/time pickers

  • counter: Counters with increment/decrement/reset

  • timer: Countdown timers with start/pause/cancel

  • schedule: Weekly schedules with time ranges (on/off per day)

  • zone: Geographical zones for presence detection

  • person: Person entities linked to device trackers

  • tag: NFC/QR tags for automation triggers

EXAMPLES:

  • List all number helpers: ha_config_list_helpers("input_number")

  • List all counters: ha_config_list_helpers("counter")

  • List all zones: ha_config_list_helpers("zone")

  • List all persons: ha_config_list_helpers("person")

  • List all tags: ha_config_list_helpers("tag")

  • List every helper type at once: ha_config_list_helpers("all")

  • Next page: ha_config_list_helpers("input_boolean", offset=100)

NOTE: Storage types list what HA's {type}/list command returns: the storage-backed helpers (created via UI/API), not the YAML-defined ones. person is the exception โ€” HA lists its YAML-configured persons alongside the storage ones, so both appear here.

Flow-based types (template / group / utility_meter / derivative / etc.) require the ha_mcp_tools custom component (>= 1.1.0) and are served only through it; storage types are listed on all installs. Requesting a flow type without the component returns a COMPONENT_NOT_INSTALLED error.

Pass helper_type="all" to enumerate every helper type in a single call. Each record carries its own helper_type. This mode is component-only (there is no single built-in command that lists all types): without the ha_mcp_tools component it returns a COMPONENT_NOT_INSTALLED error rather than a partial or empty list.

For detailed helper documentation, use ha_get_skill_guide.

list all helpers input_boolean input_number input_text counter timer input_datetime input_select

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMax helpers to return per page (default: 100)
offsetNoNumber of helpers to skip for pagination (default: 0)
helper_typeYesHelper type to list. Storage types are listed on all installs; flow-based types require the ha_mcp_tools custom component. Pass 'all' to list every helper type in one call (also requires the ha_mcp_tools component).

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses crucial behavioral details: the distinction between storage-based and flow-based types, the handling of renamed helpers (entity_id vs id), the fallback behavior when the registry read degrades, and the fact that each record includes its own helper_type. It also notes that 'all' mode requires the component. These transparency points exceed the bare annotation hints (readOnlyHint, idempotentHint) and provide valuable expectations for callers.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness2/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is excessively verbose and repetitive. It lists the same set of helper types in at least two separate blocks (SUPPORTED HELPER TYPES and EXAMPLES) and again within the note about storage vs flow. It includes redundant examples and a seemingly accidental trailing line 'list all helpers input_boolean input_number input_text counter timer input_datetime input_select'. The overall structure could be streamlined significantly without losing information, making it harder to parse quickly.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description is comprehensive: it covers error cases (COMPONENT_NOT_INSTALLED), explains the distinction between storage and flow types, details pagination, clarifies the 'all' mode, and mentions integration with the skill guide. Given the tool's complexity (multiple helper types, conditional behavior, pagination), it provides all necessary context for correct usage.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema fully documents all three parameters (helper_type, limit, offset) with descriptions and ranges. The description goes beyond the schema by explaining the significance of helper_type values, the storage vs flow split, and the behavior of 'all'. It also clarifies pagination semantics. Schema coverage is 100%, and the description adds substantial context, so this dimension is well covered.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: to list Home Assistant helpers of a specific type. It distinguishes from sibling tools like ha_config_get_helper (retrieves a single helper) and ha_config_set_helper (modifies helpers). The mention of 'list all helpers' and the enumeration of supported types makes the intent unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit guidance on when to use this tool, including pagination via limit and offset, the special 'all' mode, and the requirement for the ha_mcp_tools component for flow-based types. It also explains error conditions (COMPONENT_NOT_INSTALLED) and how to enumerate all types. This is thorough and actionable.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_config_remove_automationRemove AutomationA
DestructiveIdempotent

Delete a Home Assistant automation.

The returned automation_id is the resolved entity_id (canonical form, e.g. automation.morning_routine) when the registry lookup succeeded before the delete, falling back to the input identifier otherwise.

EXAMPLES:

  • Delete automation: ha_config_remove_automation("automation.old_automation")

  • Delete by unique_id: ha_config_remove_automation("my_unique_id")

WARNING: Deleting an automation removes it permanently from your Home Assistant configuration.

ParametersJSON Schema
NameRequiredDescriptionDefault
waitNoWait for automation to be fully removed before returning. Default: True.
identifierYesAutomation entity_id (e.g., 'automation.old_automation') or unique_id to delete

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate destructiveness, and the description adds the return value behavior and a warning about permanent deletion. No contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise with a clear front-loaded purpose, followed by return value explanation, examples, and warning. No unnecessary content.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a deletion tool with annotations and output schema, the description covers purpose, return behavior, examples, and warning. Could mention error handling or prerequisites but is fairly complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Input schema covers both parameters fully, so baseline is 3. The description adds explanation of the return value depending on identifier but does not elaborate on the 'wait' parameter.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it deletes a Home Assistant automation, with specific verb and resource. It distinguishes from sibling tools by targeting automations specifically.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for deleting automations and provides examples, but does not explicitly state when to use this vs other removal tools, nor any prerequisites or when-not-to-use.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_config_remove_calendar_eventRemove Calendar EventA
DestructiveIdempotent

Delete an event from a calendar.

Deletes a calendar event via the WebSocket calendar/event/delete command. HA's calendar component only registers create_event and get_events as REST services โ€” delete and update live on the WebSocket API only.

Parameters:

  • entity_id: Calendar entity ID (e.g., 'calendar.family')

  • uid: Unique identifier of the event to delete

  • recurrence_id: Optional recurrence ID for recurring events

  • recurrence_range: Optional recurrence range ('THIS_AND_FUTURE' to delete this and future occurrences)

Example Usage:

# Delete a single event
result = ha_config_remove_calendar_event(
    "calendar.family",
    uid="event-12345"
)

# Delete a recurring event instance and future occurrences
result = ha_config_remove_calendar_event(
    "calendar.work",
    uid="recurring-event-67890",
    recurrence_id="20240115T100000",
    recurrence_range="THIS_AND_FUTURE"
)

Note: To get the event UID, first use ha_config_get_calendar_events() to list events. The UID is returned in each event's data.

Returns:

  • Success status and deletion confirmation

ParametersJSON Schema
NameRequiredDescriptionDefault
uidYesUnique identifier of the event to delete
entity_idYesCalendar entity ID (e.g., 'calendar.family')
recurrence_idNoOptional recurrence ID for recurring events
recurrence_rangeNoOptional recurrence range ('THIS_AND_FUTURE' to delete this and future occurrences)

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and idempotentHint=true, covering safety and idempotency. The description adds useful context: it uses the WebSocket 'calendar/event/delete' command, returns success status and confirmation, and clarifies that delete is only available via WebSocket. This supplements the annotations without contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with a clear title, short purpose statement, detailed parameter list, example usage, a note on prerequisite, and return value. Every sentence serves a purpose, and the format is easy to scan. It is appropriately sized for a tool with 4 parameters and an output schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's moderate complexity (4 parameters, 2 required, output schema exists), the description covers the essential workflow: obtaining the UID, using required and optional parameters, and understanding the return. It could benefit from mentioning error handling or permission requirements, but overall it is sufficiently complete for an agent to use correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has 100% description coverage, so baseline is 3. The description repeats parameter descriptions exactly as in the schema and includes examples demonstrating usage. While examples are helpful, they do not add new semantic information beyond what the schema already provides (e.g., recurrence_range values are already documented).

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Delete an event from a calendar', using a specific verb and resource. It distinguishes itself from sibling tools like ha_config_get_calendar_events (get events) and ha_config_set_calendar_event (set/create event) by explicitly focusing on deletion. The mention of the WebSocket command further clarifies the action.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides a prerequisite note: use ha_config_get_calendar_events to obtain the event UID before deletion. It also explains that delete operations only exist on WebSocket, contrasting with REST services for create/get. However, it does not explicitly exclude usage for modifications or specify when not to use this tool, leaving a minor gap.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_config_remove_categoryRemove CategoryA
DestructiveIdempotent

Delete a Home Assistant category.

Removes the category from the category registry for the given scope (e.g., 'automation', 'script', 'scene', 'helpers'). This will also remove the category assignment from all entities in that scope.

EXAMPLES:

  • Delete category: ha_config_remove_category("automation", "my_category_id")

Use ha_config_get_category() to find category IDs.

WARNING: Deleting a category will remove it from all assigned entities. This action cannot be undone.

ParametersJSON Schema
NameRequiredDescriptionDefault
scopeYesDomain scope for the category (e.g., 'automation', 'script', 'scene', 'helpers').
category_idYesID of the category to delete

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and idempotentHint=true. The description adds crucial context: 'This will also remove the category assignment from all entities in that scope' and 'This action cannot be undone.' This goes beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise: a clear opening sentence, followed by effect, example, reference to get_category, and warning. Every sentence adds value and the structure is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the presence of an output schema (not shown), the description adequately covers the delete operation's effect and irreversibility. It does not mention error conditions, but this is acceptable for a simple destructive tool with good annotations.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with descriptions for both parameters. The description adds example usage with parameter names but no additional semantic details beyond what the schema already provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Delete a Home Assistant category' with specific verb+resource. Among sibling tools, it is distinct from other removal tools like ha_remove_zone or ha_remove_entity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains the scope of use (category registry, given scope) and provides an example. It advises using ha_config_get_category() to find IDs. It could be more explicit about when not to use this tool versus alternatives, but gives sufficient context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_config_remove_groupRemove GroupA
DestructiveIdempotent

Remove a service-based Home Assistant entity group via the group.remove service.

When NOT to use: for groups created through ha_config_set_helper(helper_type="group", ...), use ha_remove_helpers_integrations. Those config-entry-backed groups are not reachable via the group.remove service.

When to use: removing groups created with ha_config_set_group or defined in YAML via group: configuration. Config-entry-backed deletion tools cannot find these.

EXAMPLES:

  • Remove group: ha_config_remove_group("living_room_lights")

Use ha_config_list_groups() to find existing groups.

WARNING:

  • Removing a group used in automations may cause those automations to fail.

  • Groups defined in YAML can be removed at runtime but will reappear after restart.

  • This only removes old-style groups, not platform-specific groups.

ParametersJSON Schema
NameRequiredDescriptionDefault
waitNoWait for group to be fully removed before returning. Default: True.
object_idYesGroup identifier without 'group.' prefix (e.g., 'living_room_lights')

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Adds important behavioral warnings beyond annotations: automations may fail, YAML groups reappear after restart, only removes old-style groups. Annotations already indicate destructiveHint, but description provides specifics.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well-structured with clear sections, warnings, and an example. Front-loaded with main purpose, then conditional guidance. No wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers purpose, usage, behavioral traits, and mentions runtime behavior. Missing details on permissions or side effects beyond automations, but overall comprehensive given output schema exists.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so parameters are well-documented. Description adds minimal value beyond schema (only an example usage of object_id). Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Clearly states the action (remove), resource (service-based Home Assistant entity group), and method (via group.remove service). Differentiates from sibling tools by specifying which groups are covered.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit 'When NOT to use' with reference to sibling tool ha_remove_helpers_integrations, and 'When to use' with examples. Also suggests listing groups first with ha_config_list_groups().

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_config_remove_labelRemove LabelA
DestructiveIdempotent

Delete a Home Assistant label.

Removes the label from the label registry. This will also remove the label from all entities, devices, and areas that have it assigned.

EXAMPLES:

  • Delete label: ha_config_remove_label("my_label_id")

Use ha_config_get_label() to find label IDs.

WARNING: Deleting a label will remove it from all assigned entities. This action cannot be undone.

ParametersJSON Schema
NameRequiredDescriptionDefault
label_idYesID of the label to delete

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description explains that deleting a label removes it from all entities, devices, and areas, and that the action cannot be undone. This adds significant behavioral context beyond the annotations (destructiveHint true, idempotentHint true).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured: clear purpose, then details, then example, then warning. Each sentence is informative and necessary.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the single required parameter, annotations, and presence of an output schema, the description fully covers what the tool does and its effects.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema describes label_id as 'ID of the label to delete' (100% coverage). The description adds value by mentioning where to find label IDs (ha_config_get_label()).

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Delete a Home Assistant label' and explains the action (remove from registry and assigned entities). It distinguishes itself from sibling tools like ha_config_set_label and ha_config_get_label by its delete operation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides an example command and suggests using ha_config_get_label() to find label IDs. It warns about irreversible removal, but does not explicitly state when to use this tool over alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_config_remove_sceneRemove SceneA
DestructiveIdempotent

Delete a Home Assistant scene.

EXAMPLES:

  • Delete scene: ha_config_remove_scene("old_scene")

  • Delete scene: ha_config_remove_scene("temporary_scene")

IMPORTANT LIMITATION: This tool can only delete scenes created via the Home Assistant UI. Scenes defined in YAML configuration files (scenes.yaml or configuration.yaml) cannot be deleted through the API and will return a 405 Method Not Allowed error.

To remove YAML-defined scenes, you must edit the configuration file directly.

WARNING: Deleting a scene that is referenced by automations or scripts (via scene.turn_on) may cause those to fail.

ParametersJSON Schema
NameRequiredDescriptionDefault
waitNoWait for scene to be fully removed before returning. Default: True.
scene_idYesScene identifier to delete (e.g., 'old_scene')

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate destructive and idempotent behavior. Description adds critical context: the tool fails with 405 for YAML scenes and may cause automation failures if referenced. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well-structured with examples, an important limitation section, and a warning. Each element adds value, though the description could be slightly tighter without losing clarity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the output schema exists, the description adequately covers purpose, limitations, and caveats. It addresses the key behavioral aspects and constraints, making it sufficiently complete for an agent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents both parameters. The description does not add new meaning beyond what the schema provides, meeting the baseline expectation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description states 'Delete a Home Assistant scene.' This is a clear verb+resource pair. It distinguishes the tool's scope (scenes) from sibling tools that remove other entities, though it doesn't explicitly differentiate.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit guidance: only UI-created scenes can be deleted; YAML-defined scenes require editing configuration. Also warns about references in automations/scripts causing failures. This clearly tells the agent when to use and when not to use.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_config_remove_scriptRemove ScriptA
DestructiveIdempotent

Delete a Home Assistant script.

EXAMPLES:

  • Delete script: ha_config_remove_script("old_script")

  • Delete script: ha_config_remove_script("temporary_script")

IMPORTANT LIMITATION: This tool can only delete scripts created via the Home Assistant UI. Scripts defined in YAML configuration files (scripts.yaml or configuration.yaml) cannot be deleted through the API and will return a 405 Method Not Allowed error.

To remove YAML-defined scripts, you must edit the configuration file directly.

WARNING: Deleting a script that is used by automations may cause those automations to fail.

ParametersJSON Schema
NameRequiredDescriptionDefault
waitNoWait for script to be fully removed before returning. Default: True.
script_idYesScript identifier to delete โ€” bare storage key ('old_script') or entity_id form ('script.old_script'); a leading 'script.' prefix is stripped before lookup.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already provide destructiveHint=true, but the description adds critical behavioral details: the tool only works on UI-created scripts and may break automations. It does not discuss idempotency, but overall adds value beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Description is well-structured with sections (examples, limitation, warning). Each part adds value, though slightly verbose. Could be more concise but remains clear and organized.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers purpose, usage, limitations, side effects, and examples. Given the tool's simplicity (2 params, destructive) and presence of output schema, the description is thorough and leaves no important gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, baseline 3. Description adds meaning: explains script_id can be bare key or entity_id with prefix stripping, and clarifies wait default. This extra context merits a 4.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Delete a Home Assistant script' and distinguishes it from sibling tools like automation or scene removal by specifying scripts. The limitation about UI vs YAML-created scripts adds further specificity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit guidance on when to use (deleting UI-created scripts) and when not to (YAML-defined scripts, instructing to edit configuration directly). Warns about potential automation failures, giving clear context for tool selection.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_config_set_automationCreate or Update AutomationA
Destructive

Create or update a Home Assistant automation.

MUST call ha_get_skill_guide OR refer to your locally installed skills first.

PREFER NATIVE SOLUTIONS OVER TEMPLATES (read this before writing any {{ ... }}): Native triggers/conditions/actions are validated at config load, fail loudly, and do not bypass HA's schema. Templates fail silently at runtime and obscure intent.

  • condition: numeric_state instead of {{ states('x') | float > N }}

  • condition: state (with state: list) instead of {{ is_state(...) }} / {{ states(x) in [...] }}

  • condition: time instead of {{ now().hour ... }} or {{ now().weekday() ... }}

  • condition: sun instead of {{ is_state('sun.sun', ...) }}

  • Native for: field on state/numeric_state triggers and state conditions over {{ now() - X.last_changed > timedelta(...) }} duration math.

  • wait_for_trigger instead of wait_template

  • choose action instead of template-based service names

  • For one-shot date firing, use a time trigger plus automation.turn_off on a hardcoded entity_id โ€” not {{ now().date() ... }}.

  • Hardcode target.entity_id literals โ€” never {{ this.entity_id }}. Templates are appropriate ONLY in data.* fields, notification message/title, event_data, and variables. The reactive best-practice checker on this tool will surface anything in a logic position that should be native; consult the best_practice_warnings field on the response and fix before re-submitting. The relevant skill section is auto-embedded under skill_content on warnings, and the full automation-patterns.md + template-guidelines.md references ship under skill_content proactively by default. For comprehensive guidance beyond that, call ha_get_skill_guide.

The returned automation_id is the resolved entity_id (canonical form, e.g. automation.morning_routine) when entity registration succeeds, falling back to the input identifier (update path) or the generated unique_id from the upsert response (fresh create when no identifier was passed).

Before reaching for ha_config_set_automation, consider whether a dedicated tool fits the use case better:

  • State snapshot of one or more entities (capture-then-replay, no trigger needed) -> ha_config_set_scene

  • State-derived value that recomputes when its inputs change (template sensor / binary sensor / number / select) -> ha_config_set_helper(helper_type='template')

  • Stateful counter / timer / schedule / boolean / etc. -> ha_config_set_helper(helper_type='counter' | 'timer' | ...)

Supports two modes: full config replacement OR Python transformation.

WHEN TO USE WHICH MODE:

  • python_transform: RECOMMENDED for edits to existing automations. Surgical updates.

  • config: Use for creating new automations or full restructures.

IMPORTANT: python_transform requires 'identifier' and 'config_hash' from ha_config_get_automation().

PYTHON TRANSFORM EXAMPLES (operate on the fetched config, which uses HA's canonical plural root keys 'triggers'/'actions'/'conditions'):

  • Update action: python_transform="config['actions'][0]['data']['brightness'] = 255"

  • Add trigger: python_transform="config['triggers'].append({'trigger': 'state', 'entity_id': 'binary_sensor.motion', 'to': 'on'})"

  • Remove last action: python_transform="config['actions'].pop()"

Creates a new automation (if identifier omitted) or updates existing automation with provided configuration.

AUTOMATION TYPES:

  1. Regular Automations - Define triggers and actions directly

  2. Blueprint Automations - Use pre-built templates with customizable inputs

REQUIRED FIELDS (Regular Automations):

  • alias: Human-readable automation name

  • triggers: List of triggers (time, state, event, etc.)

  • actions: List of actions to execute

REQUIRED FIELDS (Blueprint Automations):

  • alias: Human-readable automation name

  • use_blueprint: Blueprint configuration

    • path: Blueprint file path (e.g., "motion_light.yaml")

    • input: Dictionary of input values for the blueprint

OPTIONAL CONFIG FIELDS (Regular Automations):

  • description: Detailed description of the user's intent (RECOMMENDED: helps safely modify implementation later)

  • category: Category ID for organization (use ha_config_get_category to list, ha_config_set_category to create)

  • conditions: Additional conditions that must be met

  • mode: 'single' (default), 'restart', 'queued', 'parallel'

  • max: Maximum concurrent executions (for queued/parallel modes)

  • initial_state: Whether automation starts enabled (true/false)

  • variables: Variables for use in automation

BASIC EXAMPLES:

Simple time-based automation: ha_config_set_automation(config={ "alias": "Morning Lights", "description": "Turn on bedroom lights at 7 AM to help wake up", "triggers": [{"trigger": "time", "at": "07:00:00"}], "actions": [{"action": "light.turn_on", "target": {"area_id": "bedroom"}}] })

Motion-activated lighting โ€” for: on the off-transition replaces action-delay: ha_config_set_automation(config={ "alias": "Motion Light", "triggers": [ {"trigger": "state", "entity_id": "binary_sensor.motion", "to": "on", "id": "motion_on"}, {"trigger": "state", "entity_id": "binary_sensor.motion", "to": "off", "for": {"minutes": 5}, "id": "motion_off"} ], "actions": [ {"choose": [ {"conditions": [ {"condition": "trigger", "id": "motion_on"}, {"condition": "sun", "after": "sunset"} ], "sequence": [{"action": "light.turn_on", "target": {"entity_id": "light.hallway"}}]}, {"conditions": [{"condition": "trigger", "id": "motion_off"}], "sequence": [{"action": "light.turn_off", "target": {"entity_id": "light.hallway"}}]} ]} ] })

Update existing automation: ha_config_set_automation( identifier="automation.morning_routine", config={ "alias": "Updated Morning Routine", "triggers": [{"trigger": "time", "at": "06:30:00"}], "actions": [ {"action": "light.turn_on", "target": {"area_id": "bedroom"}}, {"action": "climate.set_temperature", "target": {"entity_id": "climate.bedroom"}, "data": {"temperature": 22}} ] } )

BLUEPRINT AUTOMATION EXAMPLES:

Create automation from blueprint: ha_config_set_automation(config={ "alias": "Motion Light Kitchen", "use_blueprint": { "path": "homeassistant/motion_light.yaml", "input": { "motion_entity": "binary_sensor.kitchen_motion", "light_target": {"entity_id": "light.kitchen"}, "no_motion_wait": 120 } } })

Update blueprint automation inputs: ha_config_set_automation( identifier="automation.motion_light_kitchen", config={ "alias": "Motion Light Kitchen", "use_blueprint": { "path": "homeassistant/motion_light.yaml", "input": { "motion_entity": "binary_sensor.kitchen_motion", "light_target": {"entity_id": "light.kitchen"}, "no_motion_wait": 300 } } } )

TRIGGER TYPES: time, time_pattern, sun, state, numeric_state, event, device, zone, template, and more CONDITION TYPES: state, numeric_state, time, sun, template, device, zone, and more ACTION TYPES: action calls, delays, wait_for_trigger, wait_template, if/then/else, choose, repeat, parallel

For comprehensive automation documentation with all trigger/condition/action types and advanced examples:

TROUBLESHOOTING:

  • Use ha_get_state() to verify entity_ids exist

  • Use ha_search() to find correct entity_ids

  • IF you must use Jinja2 and have no native alternative, test it first with ha_eval_template() before embedding it in the automation config โ€” catches syntax errors and unresolved entity_ids before they fail silently at runtime

  • Use ha_search(domain_filter='automation') to find existing automations

create update modify edit automation triggers conditions actions new automation write save

ParametersJSON Schema
NameRequiredDescriptionDefault
waitNoWait for automation to be queryable before returning. Default: True. Set to False for bulk operations.
configNoComplete automation configuration with required fields: 'alias', 'triggers', 'actions'. Optional: 'description', 'conditions', 'mode', 'max', 'initial_state', 'variables'. Purpose-specific triggers/conditions (HA 2026.7+ default: 'trigger': '<domain>.<name>' with 'target'/'options') are valid config. Mutually exclusive with python_transform.
categoryNoCategory ID to assign to this automation. Use ha_config_get_category(scope='automation') to list available categories, or ha_config_set_category() to create one.
identifierNoAutomation entity_id or unique_id for updates. Required for python_transform. Omit to create new automation with generated unique_id.
config_hashNoConfig hash from ha_config_get_automation for optimistic locking. REQUIRED for python_transform (validates automation unchanged). Optional for config updates (validates before full replacement if provided).
MandatoryBPSNo
BestPracticeKeyNoRead-receipt for the home-assistant-best-practices skill; required when strict best-practices mode is enabled. Not a secret or credential: the current value is an attestation phrase published openly at the top of the skill content served by ha_get_skill_guide. Read that content, then pass the value back verbatim โ€” this round-trip is the server's designed protocol confirming the practices were read before writing.
python_transformNoPython expression to transform existing automation config. Mutually exclusive with config. Requires identifier and config_hash for validation. WARNING: Expressions with infinite loops will hang the server. Examples: Simple: python_transform="config['actions'][0]['data']['brightness'] = 255" Pattern: python_transform="for a in config['actions']: if a.get('alias') == 'My Step': a['data']['value'] = 100" PYTHON TRANSFORM SECURITY: โœ… ALLOWED: - Dictionary/list access: config['views'][0]['cards'][1] - Slicing: config['views'][0]['cards'][1:3] - Assignment: config['key'] = 'value' - Deletion: del config['key'] or config.pop('key') - List methods: append, insert, pop, remove, clear, extend - Dict methods: update, get, setdefault, keys, values, items - Loops: for, if/else, pass, break, continue - Comprehensions: [x for x in ...], {k: v for ...}, (x for x in ...) - Ternary: x if condition else y - Iterable unpacking (* in calls/literals): f(*xs), [*xs, y] - Dict unpacking (**) in calls and dict literals: {**d, 'k': v} - Keyword arguments: func(key=value) - Lambdas (e.g. for `key=`): sorted(items, key=lambda x: x['score']) - String methods: startswith, endswith, lower, upper, strip, split, join, replace - Safe builtins: isinstance, len, range, enumerate, zip, sorted, reversed, min, max, sum, abs, any, all, round, str, int, float, bool, list, dict, tuple, set โŒ FORBIDDEN: - Imports: import, from, __import__ - File operations: open, read, write - Dunder access: __class__, __bases__, __subclasses__ - Dangerous builtins: eval, exec, compile, getattr, setattr, delattr, hasattr - Function definitions: def, class - Exception handling: try/except (validate with isinstance/in/.get() instead) - While loops: use bounded for loops or comprehensions instead ๐ŸŽฏ PATTERNS: - Filter cards: cards = [c for c in cards if keep(c)] - Skip in a loop: prefer `continue` over an empty `pass` branch (clearer) - Conditionally include: build a new list and `.append(x)` only the cards you want, instead of iterating the original and using if/pass branches to drop entries - Modify in place when possible (single pass, fewer surprises) over reconstructing the entire list

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare destructiveHint=true, and the description reinforces this by detailing that updates are possible. Beyond annotations, it explains the return value (automation_id), warns about templates vs native solutions, mentions best practice warnings, and describes the two operational modes. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but well-structured with clear section headers, bullet points, and examples. It front-loads critical info (purpose, native vs templates, modes) and then provides detailed examples. Some redundancy in examples, but the complexity of automation creation justifies the length. Could be slightly more concise.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (multiple automation types, two modes, template guidelines, python transform security, output schema exists), the description covers all necessary aspects: return values, prerequisites, best practices, troubleshooting, and references to other tools. It is remarkably complete for an AI agent to use correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 88% schema description coverage, the schema already documents most parameters, but the description adds significant meaning: detailed examples for config, extensive security rules and examples for python_transform, explanation of identifier and config_hash usage, and the BestPracticeKey parameter. The description elevates understanding beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Create or update a Home Assistant automation.' It differentiates between creation and update, covers two modes (config and python_transform), and explicitly distinguishes from sibling tools like ha_config_set_scene and ha_config_set_helper by providing comparisons in the 'Before reaching for' section.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides extensive usage guidelines: when to use config vs python_transform, prerequisites for python_transform (identifier and config_hash), and alternatives for different use cases. It includes explicit 'when to use which mode' and 'Before reaching for' guidance, making it very clear for the agent to decide.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_config_set_calendar_eventCreate or Update Calendar EventA
Destructive

Create a new event in a calendar.

Creates a one-off event via the calendar.create_event service, or a recurring series via the WebSocket calendar/event/create command when rrule is provided (the REST service schema does not accept recurrence rules).

When NOT to use:

  • To retrieve calendar events, use ha_config_get_calendar_events.

  • To delete an event, use ha_config_remove_calendar_event.

Example Usage:

# Create a simple event
result = ha_config_set_calendar_event(
    "calendar.family",
    summary="Doctor appointment",
    start="2024-01-15T14:00:00",
    end="2024-01-15T15:00:00"
)

# Create a recurring event (every Monday, 10 occurrences)
result = ha_config_set_calendar_event(
    "calendar.work",
    summary="Team meeting",
    start="2024-01-15T10:00:00",
    end="2024-01-15T11:00:00",
    rrule="FREQ=WEEKLY;BYDAY=MO;COUNT=10"
)

# Create an all-day event (date-only, no time component). The end
# date is EXCLUSIVE, so this spans 2026-07-04 through 2026-07-10.
result = ha_config_set_calendar_event(
    "calendar.family",
    summary="Vacation",
    start="2026-07-04",
    end="2026-07-11"
)

Note: Passing date-only values (YYYY-MM-DD) for both start and end creates an all-day event; passing full ISO datetimes creates a timed event. The two forms cannot be mixed โ€” a date-only start with a datetime end (or vice versa) is rejected. Because the all-day end date is exclusive, a single-day all-day event must set end to start + 1 day.

Not every calendar integration supports event creation; recurring events additionally require the integration to support recurrence (the built-in Local Calendar does).

Returns:

  • Success status and event details

ParametersJSON Schema
NameRequiredDescriptionDefault
endYesEvent end date or datetime in ISO format. For all-day events (date-only) the end date is exclusive; a single-day all-day event needs end = start + 1 day.
rruleNoOptional RFC 5545 recurrence rule, without 'RRULE:' prefix (e.g., 'FREQ=WEEKLY;BYDAY=MO' or 'FREQ=MONTHLY;BYDAY=3SA'). Creates a recurring event series.
startYesEvent start date or datetime in ISO format
summaryYesEvent title/summary
locationNoOptional event location
entity_idYesCalendar entity ID (e.g., 'calendar.family')
descriptionNoOptional event description

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark destructiveHint=true, but the description adds crucial context: exclusive end date for all-day events, requirement for recurrence support, and failure modes for mixed date formats. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-organized into clear sections (purpose, when not to, examples, notes, returns). Every sentence adds value without unnecessary fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 7 parameters, 4 required, and an output schema, the description covers all critical aspects: differences between event types, integration limitations, return values, and common pitfalls (date mixing, exclusive end). A complete guide for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3, but the description adds meaning through examples (all-day vs timed events, rrule format) and notes on exclusive end dates, which clarifies parameter interaction beyond the schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool creates calendar events, distinguishes between one-off and recurring, and explicitly contrasts with sibling tools for retrieval (ha_config_get_calendar_events) and deletion (ha_config_remove_calendar_event).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides a dedicated 'When NOT to use' section naming specific alternatives, along with multiple examples and detailed notes on date format mixing and integration support. This is explicit guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_config_set_categoryCreate or Update CategoryA
Destructive

Create or update a Home Assistant category.

Creates a new category if category_id is not provided, or updates an existing category if category_id is provided.

Categories are domain-scoped organizational groups for automations, scripts, scenes, and helpers. Unlike labels (which are cross-domain), categories are specific to a single domain scope.

EXAMPLES:

  • Create automation category: ha_config_set_category("Lighting", scope="automation")

  • Create with icon: ha_config_set_category("Security", scope="automation", icon="mdi:shield")

  • Update category: ha_config_set_category("Updated Name", scope="automation", category_id="my_category_id")

After creating a category, use ha_set_entity(categories={"automation": "category_id"}) to assign it.

ParametersJSON Schema
NameRequiredDescriptionDefault
iconNoMaterial Design Icon (e.g., 'mdi:tag', 'mdi:label')
nameYesDisplay name for the category
scopeYesDomain scope for the category (e.g., 'automation', 'script', 'scene', 'helpers').
category_idNoCategory ID for updates. If not provided, creates a new category.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description reveals the tool can create or update, implying mutation. This aligns with the destructiveHint=true annotation. It adds context about domain scoping and update behavior (providing category_id updates). No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with clear sections: summary, explanation, and examples. It is front-loaded with the core purpose and is not overly verbose. The examples add length but are helpful.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the presence of an output schema, the description does not need to explain return values. It covers creation vs update, scoping, and provides examples for typical use cases. It also references a related tool (ha_set_entity) for assigning categories, making it complete for the user.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema handles basic meaning. The description adds value through examples that clarify usage of icon and category_id, and emphasizes the create/update distinction. While schema already describes each parameter, the examples provide practical context.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool creates or updates a Home Assistant category, specifying the resource (category) and action (create/update). It distinguishes from labels by noting categories are domain-scoped, but does not explicitly differentiate from sibling tools like ha_config_get_category or ha_config_remove_category.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear guidance on when to use the tool: create new (no category_id) or update existing (with category_id). It includes examples for each case and references ha_set_entity for assigning categories. However, it does not explicitly state when not to use it or mention alternatives beyond the label comparison.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_config_set_dashboardCreate or Update DashboardA
Destructive

Create or update a Home Assistant dashboard.

MUST call ha_get_skill_guide OR refer to your locally installed skills first.

Creates a new dashboard or updates an existing one with the provided configuration. Supports two modes: full config replacement OR Python transformation.

Use 'default' or 'lovelace' to target the built-in default dashboard. New dashboards require a hyphenated url_path (e.g., 'my-dashboard').

WHEN TO USE WHICH MODE:

  • python_transform: RECOMMENDED for edits. Surgical/pattern-based updates, works on all platforms.

  • config: New dashboards only, or full restructure. Replaces everything.

IMPORTANT: After delete/add operations, indices shift! Subsequent python_transform calls must use fresh config_hash from ha_config_get_dashboard() to get updated structure. Chain multiple ops in ONE expression when possible.

TIP: Use ha_config_get_dashboard(entity_id=...) to get the path for any card.

TIP: return_screenshot=True bundles rendered image(s) with the write result (beta feature); for visual re-checks after the write, use the dedicated ha_get_dashboard_screenshot tool instead of re-sending config.

PYTHON TRANSFORM EXAMPLES (RECOMMENDED):

  • Update card icon: 'config["views"][0]["cards"][0]["icon"] = "mdi:thermometer"'

  • Add card: 'config["views"][0]["cards"].append({"type": "button", "entity": "light.bedroom"})'

  • Delete card: 'del config["views"][0]["cards"][2]'

  • Pattern-based update: 'for card in config["views"][0]["cards"]: if "light" in card.get("entity", ""): card["icon"] = "mdi:lightbulb"'

  • Multi-operation: 'config["views"][0]["cards"][0]["icon"] = "mdi:a"; config["views"][0]["cards"][1]["icon"] = "mdi:b"'

MODERN DASHBOARD BEST PRACTICES:

  • Use "sections" view type (default) with grid-based layouts

  • Use "tile" cards as primary card type (replaces legacy entity/light/climate cards)

  • Use "grid" cards for multi-column layouts within sections

  • Create multiple views with navigation paths (avoid single-view endless scrolling)

  • Use "area" cards with navigation for hierarchical organization

DISCOVERING ENTITY IDs FOR DASHBOARDS: Do NOT guess entity IDs - use these tools to find exact entity IDs:

  1. ha_get_overview(include_entity_id=True) - Get all entities organized by domain/area

  2. ha_search(query, domain_filter, area_filter, search_types) - Find entities and config-body references in one call

If unsure about entity IDs, ALWAYS use one of these tools first.

DASHBOARD DOCUMENTATION:

  • dashboard-guide.md and dashboard-cards.md ship in this response under skill_content by default โ€” layout patterns, card-type taxonomy, and worked examples.

  • ha_get_skill_guide โ€” deeper card-type and configuration guidance.

EXAMPLES:

Create empty dashboard: ha_config_set_dashboard( url_path="mobile-dashboard", title="Mobile View", icon="mdi:cellphone" )

Create dashboard with modern sections view: ha_config_set_dashboard( url_path="home-dashboard", title="Home Overview", config={ "views": [{ "title": "Home", "type": "sections", "sections": [{ "title": "Climate", "cards": [{ "type": "tile", "entity": "climate.living_room", "features": [{"type": "target-temperature"}] }] }] }] } )

Create strategy-based dashboard (auto-generated): ha_config_set_dashboard( url_path="my-home", title="My Home", config={ "strategy": { "type": "home", "favorite_entities": ["light.bedroom"] } } )

Note: Strategy dashboards cannot be converted to custom dashboards via this tool. Use the "Take Control" feature in the Home Assistant interface to convert them.

Update existing dashboard config: ha_config_set_dashboard( url_path="existing-dashboard", config={ "views": [{ "title": "Updated View", "type": "sections", "sections": [{ "cards": [{"type": "markdown", "content": "Updated!"}] }] }] } )

Note: When updating an existing dashboard, title/icon/require_admin/show_in_sidebar are also updated if explicitly provided alongside (or instead of) a config change.

STORAGE-MODE vs YAML-MODE DASHBOARDS: This tool only manages storage-mode dashboards (created via UI/API and stored in Home Assistant's storage backend). It does NOT touch YAML-defined dashboards. Two distinct YAML cases exist and this tool covers neither:

  • "YAML-mode" dashboards: written in their own .yaml file referenced from configuration.yaml under lovelace: dashboards:. The dashboard itself lives in a separate YAML file but its registration is in configuration.yaml.

  • Dashboards inlined directly in configuration.yaml under the lovelace: key (legacy single-dashboard mode). For either YAML case, edit the dashboard's .yaml file directly. ha_config_set_yaml can update the lovelace: registration entry in configuration.yaml but does NOT touch the dashboard body in the referenced .yaml file.

ParametersJSON Schema
NameRequiredDescriptionDefault
iconNoMDI icon name (e.g., 'mdi:home', 'mdi:cellphone'). Defaults to 'mdi:view-dashboard'
titleNoDashboard display name shown in sidebar
configNoDashboard configuration with views and cards. Omit or set to None to create dashboard without initial config. Mutually exclusive with python_transform.
url_pathYesDashboard URL path (e.g., 'my-dashboard'). Use 'default' or 'lovelace' for the default dashboard. New dashboards must use a hyphenated path.
view_pathNoWith return_screenshot: stable Lovelace views[].path to render.
config_hashNoConfig hash from ha_config_get_dashboard for optimistic locking. REQUIRED for python_transform (validates dashboard unchanged). Optional for config (validates before full replacement if provided).
MandatoryBPSNo
require_adminNoRestrict dashboard to admin users only. For existing dashboards, only updated when explicitly provided.
BestPracticeKeyNoRead-receipt for the home-assistant-best-practices skill; required when strict best-practices mode is enabled. Not a secret or credential: the current value is an attestation phrase published openly at the top of the skill content served by ha_get_skill_guide. Read that content, then pass the value back verbatim โ€” this round-trip is the server's designed protocol confirming the practices were read before writing.
show_in_sidebarNoShow dashboard in sidebar navigation. For existing dashboards, only updated when explicitly provided.
python_transformNoPython expression to transform existing dashboard config. Mutually exclusive with config. Requires config_hash for validation. See PYTHON TRANSFORM SECURITY below for allowed operations. Examples: Simple: python_transform="config['views'][0]['cards'][0]['icon'] = 'mdi:lamp'" Pattern: python_transform="for card in config['views'][0]['cards']: if 'light' in card.get('entity', ''): card['icon'] = 'mdi:lightbulb'" Multi-op: python_transform="config['views'][0]['cards'][0]['icon'] = 'mdi:lamp'; del config['views'][0]['cards'][2]" PYTHON TRANSFORM SECURITY: โœ… ALLOWED: - Dictionary/list access: config['views'][0]['cards'][1] - Slicing: config['views'][0]['cards'][1:3] - Assignment: config['key'] = 'value' - Deletion: del config['key'] or config.pop('key') - List methods: append, insert, pop, remove, clear, extend - Dict methods: update, get, setdefault, keys, values, items - Loops: for, if/else, pass, break, continue - Comprehensions: [x for x in ...], {k: v for ...}, (x for x in ...) - Ternary: x if condition else y - Iterable unpacking (* in calls/literals): f(*xs), [*xs, y] - Dict unpacking (**) in calls and dict literals: {**d, 'k': v} - Keyword arguments: func(key=value) - Lambdas (e.g. for `key=`): sorted(items, key=lambda x: x['score']) - String methods: startswith, endswith, lower, upper, strip, split, join, replace - Safe builtins: isinstance, len, range, enumerate, zip, sorted, reversed, min, max, sum, abs, any, all, round, str, int, float, bool, list, dict, tuple, set โŒ FORBIDDEN: - Imports: import, from, __import__ - File operations: open, read, write - Dunder access: __class__, __bases__, __subclasses__ - Dangerous builtins: eval, exec, compile, getattr, setattr, delattr, hasattr - Function definitions: def, class - Exception handling: try/except (validate with isinstance/in/.get() instead) - While loops: use bounded for loops or comprehensions instead ๐ŸŽฏ PATTERNS: - Filter cards: cards = [c for c in cards if keep(c)] - Skip in a loop: prefer `continue` over an empty `pass` branch (clearer) - Conditionally include: build a new list and `.append(x)` only the cards you want, instead of iterating the original and using if/pass branches to drop entries - Modify in place when possible (single pass, fewer surprises) over reconstructing the entire list
return_screenshotNoAfter writing, also return rendered image(s) of the dashboard so you can see what it looks like in a single call (the dashboard creation/iteration loop). Requires the 'dashboard screenshot' beta feature + engine add-on/sidecar; if unavailable, the write result is returned with a warning. For visual re-checks after the write (no config round-trip), use the dedicated ha_get_dashboard_screenshot tool instead.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No contradiction with the destructiveHint annotation - the description openly states 'Replaces everything,' 'After delete/add operations, indices shift!,' and shows deletion expressions, so the destructive profile is consistent. It adds substantial behavioral context beyond the annotation: optimistic locking via config_hash, the index-shift gotcha requiring fresh hashes, the storage-mode vs YAML-mode scope boundary, the strategy-dashboard conversion limitation, and the rule that title/icon/require_admin/show_in_sidebar only update when explicitly provided.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but well-structured with headers, scannable bullets, code examples, and front-loaded critical information (mode selection, index-shift warning, default-dashboard targeting). It carries some redundancy - the python_transform examples overlap with the schema's own extensive examples, and the MODERN DASHBOARD BEST PRACTICES section is content guidance arguably better placed in the skill guide.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive 12-parameter tool with no output schema, the description is unusually complete: prerequisites, mode semantics, optimistic locking, YAML-mode exclusion, strategy-dashboard limitation, and entity-discovery workflow are all covered. Remaining gaps are minor but real - MandatoryBPS is never explained, and the write-result/return format is not described.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 92%, so the baseline is 3, but the description adds genuine value beyond the schema: the hyphenated url_path rule for new dashboards, the mode-selection semantics mapping python_transform to edits and config to full replacement, and the rationale for always fetching a fresh config_hash after structural changes. The one gap is MandatoryBPS, which remains unexplained in both the schema and the description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening sentence 'Create or update a Home Assistant dashboard' pairs specific verbs (create/update) with a concrete resource, and the two-mode breakdown (config vs python_transform) makes the operation unambiguous. It is easily distinguished from siblings like ha_config_get_dashboard (read), ha_config_delete_dashboard (delete), and ha_config_set_scene (scenes).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when-to-use guidance: 'python_transform: RECOMMENDED for edits... config: New dashboards only, or full restructure.' It also names alternatives for adjacent tasks - ha_config_get_dashboard for fetching structure/hashes, ha_get_overview/ha_search for entity discovery, ha_get_dashboard_screenshot for visual re-checks, and ha_config_set_yaml with a clear exclusion for YAML-mode dashboards. The MUST-call ha_get_skill_guide prerequisite is also stated up front.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_config_set_dashboard_resourceSet Dashboard ResourceA
Destructive

Create or update a dashboard resource (inline code or external URL).

Provide exactly one of:

  • content: Inline JavaScript or CSS code (embedded in the resource URL as a data: URI โ€” no file storage or external hosting involved)

  • url: External resource URL (/local/, /hacsfiles/, or https://...)

INLINE MODE (content=):

  • Custom card code written inline

  • CSS styling for dashboards

  • Self-contained files up to ~128KB

  • URLs are deterministic (same content = same URL)

  • Content must be self-contained: a data: URI has no base URL, so relative imports inside a module and relative url() references inside CSS cannot resolve (use fully-qualified URLs instead)

  • If Home Assistant is behind a reverse proxy that injects a Content-Security-Policy without 'data:' in script-src/style-src, the browser blocks these resources: this call still succeeds and the card simply never renders. Register the code as a file and use url='/local/...' on such a deployment. (HA itself ships no CSP.)

  • Supports 'module' and 'css' types only (not 'js')

URL MODE (url=):

  • Files in /config/www/ directory (/local/...)

  • HACS-installed cards (/hacsfiles/...)

  • External CDN resources (https://...)

  • Supports all types: 'module', 'js', 'css'

RESOURCE TYPES:

  • module: ES6 JavaScript modules (recommended for custom cards)

  • js: Legacy JavaScript files (older custom cards, url mode only)

  • css: CSS stylesheets (themes, global styles)

EXAMPLES:

Inline custom card: ha_config_set_dashboard_resource( content=""" class MyCard extends HTMLElement { setConfig(config) { this.config = config; } set hass(hass) { this.innerHTML = <ha-card>Hello ${hass.states[this.config.entity]?.state}</ha-card>; } } customElements.define('my-card', MyCard); """, resource_type="module" )

Add custom card from www/ directory: ha_config_set_dashboard_resource( url="/local/my-custom-card.js", resource_type="module" )

Add HACS card (after installing via ha_manage_hacs(action='download')): ha_config_set_dashboard_resource( url="/hacsfiles/lovelace-mushroom/mushroom.js", resource_type="module" )

Update existing resource: ha_config_set_dashboard_resource( url="/local/my-card-v2.js", resource_type="module", resource_id="abc123" )

Note: After adding a resource, clear browser cache or hard refresh (Ctrl+Shift+R) to load changes.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlNoURL of the resource. Can be: /local/file.js (www/ directory), /hacsfiles/component/file.js (HACS), https://cdn.example.com/card.js (external). Mutually exclusive with content.
contentNoJavaScript or CSS code to host inline (max ~128KB). The code is embedded directly in the resource URL as a data: URI - no file storage or external hosting involved. Mutually exclusive with url. Supports 'module' and 'css' types only.
resource_idNoResource ID to update. If omitted, creates a new resource. Get IDs from ha_config_list_dashboard_resources()
resource_typeNoResource type: 'module' for ES6 modules (modern cards, default), 'js' for legacy JavaScript (url mode only), 'css' for stylesheetsmodule

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description extensively discloses behaviors beyond destructiveHint: true, such as inline content being stored as data: URI, deterministic URLs, ~128KB limit, CSP blocking issues, and supported types per mode. No contradictions with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is verbose but well-structured with sections, bullet points, and examples. It front-loads the core purpose. Some redundancy exists (e.g., examples could be condensed), but every sentence adds meaningful information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (4 parameters, output schema present), the description covers all aspects: purpose, modes, parameters, limitations, examples, and update mechanism. It is fully complete for an AI agent to use correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Although schema coverage is 100%, the description adds significant value by explaining mutual exclusivity of url and content, inline mode limitations (supports only 'module' and 'css'), and the source of resource_id (from list). Examples demonstrate parameter combinations.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Create or update a dashboard resource (inline code or external URL).' It distinguishes two modes (inline vs URL) and specifies resource types, making the purpose specific and distinct from sibling tools like deletion or listing.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear when-to-use guidance by detailing inline vs URL modes, including prerequisites for URL mode (e.g., files in /config/www/ for /local/) and alternatives for CSP-blocked environments. It lacks explicit 'when not to use' but sufficiently implies context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_config_set_groupCreate or Update GroupA
Destructive

Create or update a service-based Home Assistant entity group via the group.set service.

When NOT to use: for typical "combine these entities into one controllable group" requests, prefer ha_config_set_helper(helper_type="group", ...). Config-entry-backed groups are registered in the entity registry, so ha_set_entity can assign them to areas and they are deletable via ha_remove_helpers_integrations.

When to use: compatibility with existing groups already configured via group.set or YAML, or the rare case where entity-registry membership is explicitly unwanted. Groups created here are only removable via ha_config_remove_group โ€” ha_remove_helpers_integrations will not find them.

For NEW groups: Provide object_id and entities (required). For EXISTING groups: Provide object_id and any fields to update.

EXAMPLES:

  • Create group: ha_config_set_group("bedroom_lights", entities=["light.lamp", "light.ceiling"])

  • Create with name: ha_config_set_group("sensors", entities=["sensor.temp"], name="All Sensors")

  • Update name: ha_config_set_group("lights", name="Living Room Lights")

  • Add entities: ha_config_set_group("lights", add_entities=["light.extra"])

  • Remove entities: ha_config_set_group("lights", remove_entities=["light.old"])

  • Replace all entities: ha_config_set_group("lights", entities=["light.new1", "light.new2"])

NOTE: entities, add_entities, and remove_entities are mutually exclusive.

ParametersJSON Schema
NameRequiredDescriptionDefault
iconNoMaterial Design Icon (e.g., 'mdi:lightbulb-group')
nameNoFriendly display name for the group
waitNoWait for group to be queryable before returning. Default: True. Set to False for bulk operations.
all_onNoIf True, all entities must be on for group to be on (default: False)
entitiesNoList of entity IDs for the group. Required when creating new group. When updating, replaces all entities (mutually exclusive with add_entities/remove_entities).
object_idYesGroup identifier without 'group.' prefix (e.g., 'living_room_lights')
add_entitiesNoAdd these entities to an existing group (mutually exclusive with entities)
remove_entitiesNoRemove these entities from an existing group (mutually exclusive with entities)

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

While annotations provide destructiveHint: true, the description adds critical context: groups are only removable via ha_config_remove_group (not ha_remove_helpers_integrations) and notes mutex condition among entities, add_entities, remove_entities. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with clear sections (When NOT to use, When to use, For NEW groups, For EXISTING groups, EXAMPLES, NOTE). It is front-loaded with essential information, no unnecessary words, and each sentence serves a purpose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With 8 parameters and 1 required, the description covers all key use cases (create, update, add/remove entities) and addresses lifecycle considerations. It also notes the existence of an output schema (though not shown). The description is fully adequate for the tool's complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3. The description adds value by clarifying that entities is required for new groups, explaining the mutex condition, and providing examples that demonstrate parameter usage. This surpasses the schema alone.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Create or update a service-based Home Assistant entity group via the group.set service.' It uses specific verbs (create, update) and resource (group), and distinguishes itself from the sibling tool ha_config_set_helper for typical group creation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly provides when NOT to use (prefer ha_config_set_helper) and when to use (compatibility with existing groups, entity-registry membership unwanted). It also gives clear examples for new and existing groups.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_config_set_helperCreate or Update HelperA
Destructive

Create or update Home Assistant helper entities and config subentries (30 types, unified interface).

MUST call ha_get_skill_guide OR refer to your locally installed skills first.

SIMPLE/FLOW helper create requires name; SIMPLE/FLOW helper update requires helper_id. Config subentry create requires entry_id and subentry_type; config subentry update also requires subentry_id.

SIMPLE types (structured params, WebSocket API): input_boolean, input_button, input_select, input_number, input_text, input_datetime, counter, timer, schedule, zone, person, tag.

FLOW types (pass config dict, Config Entry Flow API): template, group, utility_meter, derivative, min_max, threshold, integration, statistics, trend, random, filter, tod, generic_thermostat, switch_as_x, generic_hygrostat, history_stats, mold_indicator. Note: tod is the purpose-built "is-current-time-in-range" indicator (supports cross-midnight ranges, unlike schedule). Note: otp is a helper in the HA UI but is not offered here โ€” its flow requires a live TOTP code. Create it with ha_set_integration(domain="otp"), as with any other helper-domain flow outside this list.

CONFIG_SUBENTRY type (Config Subentry Flow API): config_subentry. Pass entry_id, subentry_type, and config. Pass subentry_id to reconfigure an existing subentry; omit it to create a new subentry.

For flow-type updates, pass the existing entry_id as helper_id. Options flows reject the name key on update โ€” to rename a flow helper, delete and recreate.

Behavior notes:

  • UPDATE preserves type-specific fields not re-passed (rename never wipes initial/icon/etc. for any simple helper). Flow-helper and config subentry updates behave the same way: a field omitted from config keeps its current value, and a field set to null is cleared where the schema allows that field to be empty.

  • Pass action="create" or action="update" to disambiguate intent. For SIMPLE/FLOW helpers, omitted action falls back to the implicit helper_id-presence discriminator. For config subentries, omitted action falls back to the subentry_id-presence discriminator.

  • For flow-based helpers, config keys not declared by any step's data_schema are silently ignored by HA; submit once and the validation error returns the data_schema for that helper so subsequent calls use the correct field names.

  • Validation errors raised by this tool carry the helper's data_schema in the response context (and menu_options for menu-rooted helpers like template/group when no sub-type is chosen yet) so a follow-up call can self-correct without a separate schema-discovery round-trip.

  • Flows that present more than one menu (e.g. an MQTT device subentry reconfigure looping through its summary menu) take next_step_id as a LIST of successive selections, consumed one per menu encounter.

EXAMPLES (menu-based types + tod, where first-call payload is non-obvious):

  • template sensor: ha_config_set_helper(helper_type="template", name="Room Temp", config={"next_step_id": "sensor", "state": "{{ states('sensor.x')|float }}", "unit_of_measurement": "ยฐC"})

  • group (light): ha_config_set_helper(helper_type="group", name="Kitchen Lights", config={"group_type": "light", "entities": ["light.a", "light.b"]})

  • tod (time-of-day indicator, cross-midnight OK): ha_config_set_helper(helper_type="tod", name="Quiet Hours", config={"after_time": "22:00:00", "before_time": "07:00:00"})

  • config subentry (create under an existing integration): ha_config_set_helper(helper_type="config_subentry", entry_id="01HXYZ...", subentry_type="conversation", config={"name": "Local agent", "model": "gemma3:27b"})

helper-selection.md ships in this response under skill_content by default โ€” decision matrix for picking the right helper type plus worked examples and per-type field tables. For deeper helper-design guidance beyond what ships here, call ha_get_skill_guide.

create update new add helper input_boolean input_button input_number input_text input_datetime input_select counter timer schedule zone person tag template group utility_meter derivative min_max threshold integration statistics trend random filter tod generic_thermostat switch_as_x generic_hygrostat history_stats mold_indicator

ParametersJSON Schema
NameRequiredDescriptionDefault
iconNoMaterial Design Icon (e.g., 'mdi:bell', 'mdi:toggle-switch')
modeNoDisplay mode: 'box'/'slider' for input_number, 'text'/'password' for input_text
nameNoDisplay name for simple/flow helper creation. Required when creating a helper without helper_id. Optional on helper update. Ignored for helper_type='config_subentry', which uses entry_id/subentry_type/subentry_id instead. For flow-based helper updates (template, group, utility_meter, ...), this is typically ignored because options flows don't expose renaming. Rename a flow helper by deleting and recreating instead.
stepNoStep/increment value for input_number or counter
waitNoWait for helper entity to be queryable before returning. Default: True. Set to False for bulk operations.
actionNoExplicit intent: 'create' a new helper or 'update' an existing one. When omitted, falls back to the implicit discriminator: presence of helper_id => update, absence => create. Pass 'create' or 'update' to disambiguate (e.g. so a typo in helper_id surfaces as a clear 'helper not found' error instead of being mistaken for a create call).
configNoConfig dict for flow-based helper types and helper_type='config_subentry' (template, group, utility_meter, derivative, min_max, threshold, integration, statistics, trend, random, filter, tod, generic_thermostat, switch_as_x, generic_hygrostat, history_stats, mold_indicator). Ignored for simple helper types. On update it is a patch: a field you omit keeps its current value, and a field set to null is cleared where the schema allows that field to be empty. A field two steps declare gets your one value both times; pass step_values={'<step_id>': {'<field>': <value>}} to give a step its own value, or to leave it out of that step; a LIST of those objects supplies one per encounter when the flow presents a step more than once. Field set is delivered as data_schema on the first validation error.
fridayNoSchedule time ranges for Friday. List of {'from': 'HH:MM', 'to': 'HH:MM'} dicts. Optional 'data' dict for additional attributes.
labelsNoLabels to categorize the helper
mondayNoSchedule time ranges for Monday. List of {'from': 'HH:MM', 'to': 'HH:MM'} dicts. Optional 'data' dict for additional attributes (e.g. {'from': '07:00', 'to': '22:00', 'data': {'mode': 'comfort'}})
radiusNoRadius in meters for zone (default: 100)
sundayNoSchedule time ranges for Sunday. List of {'from': 'HH:MM', 'to': 'HH:MM'} dicts. Optional 'data' dict for additional attributes.
tag_idNoTag ID for tag. On create, omit to auto-generate a unique uuid4 hex (HA's tag/create requires this field; the tool fills it in for you). On update, the tag's existing tag_id is required (passed via helper_id).
area_idNoArea/room ID to assign the helper to
initialNoInitial value for applicable helper types. For input_boolean, input_select, input_number, input_text, and input_datetime: setting `initial` โ€” even to false/0 โ€” disables last-state restore and forces that value on every HA restart; omit unless you want the helper to reset to that value on every restart instead of restoring its last state. For counter, `initial` is just the starting value โ€” restore-on-restart is controlled separately by `restore` (default True).
optionsNoList of options for input_select (required for input_select)
passiveNoPassive zone (won't trigger state changes for person entities)
pictureNoPicture URL for person entity
restoreNoRestore state after restart (counter, timer). Defaults to True for counter, False for timer
tuesdayNoSchedule time ranges for Tuesday. List of {'from': 'HH:MM', 'to': 'HH:MM'} dicts. Optional 'data' dict for additional attributes.
user_idNoUser ID to link to person entity
categoryNoCategory ID to assign to this helper. Use ha_config_get_category(scope='helpers') to list available categories, or ha_config_set_category() to create one.
durationNoDefault duration for timer in format 'HH:MM:SS' or seconds (e.g., '0:05:00' for 5 minutes)
entry_idNoParent config entry ID when helper_type='config_subentry'. Use ha_get_integration() to find entry IDs.
has_dateNoInclude date component for input_datetime
has_timeNoInclude time component for input_datetime
latitudeNoLatitude for zone (required for zone)
saturdayNoSchedule time ranges for Saturday. List of {'from': 'HH:MM', 'to': 'HH:MM'} dicts. Optional 'data' dict for additional attributes.
thursdayNoSchedule time ranges for Thursday. List of {'from': 'HH:MM', 'to': 'HH:MM'} dicts. Optional 'data' dict for additional attributes.
helper_idNoREQUIRED when updating an existing helper. Bare ID ('my_button') or full entity ID ('input_button.my_button'). Omit to create a new helper.
longitudeNoLongitude for zone (required for zone)
max_valueNoMaximum value (input_number/counter) or maximum length (input_text). Also accepts shorthand 'max'.
min_valueNoMinimum value (input_number/counter) or minimum length (input_text). Also accepts shorthand 'min'.
wednesdayNoSchedule time ranges for Wednesday. List of {'from': 'HH:MM', 'to': 'HH:MM'} dicts. Optional 'data' dict for additional attributes.
descriptionNoDescription for tag
helper_typeYesType of helper entity to create or update
subentry_idNoExisting config subentry ID to reconfigure when helper_type='config_subentry'. Omit to create.
MandatoryBPSNo
subentry_typeNoIntegration-defined subentry type when helper_type='config_subentry'.
BestPracticeKeyNoRead-receipt for the home-assistant-best-practices skill; required when strict best-practices mode is enabled. Not a secret or credential: the current value is an attestation phrase published openly at the top of the skill content served by ha_get_skill_guide. Read that content, then pass the value back verbatim โ€” this round-trip is the server's designed protocol confirming the practices were read before writing.
device_trackersNoList of device_tracker entity IDs for person
unit_of_measurementNoUnit of measurement for input_number (e.g., 'ยฐC', '%', 'W'). Also accepts shorthand 'unit'.
show_advanced_optionsNoWhen helper_type='config_subentry', ask older Home Assistant versions to expose advanced flow options. No-op on HA 2026.6+; pending removal before HA 2027.6.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the destructiveHint=true annotation, the description discloses rich behavioral traits: update patch semantics (omitted fields keep current value, null clears), silent ignoring of undeclared config keys (with the submit-once-then-read-data_schema recovery protocol), the rename trap ('Options flows reject the name key on update โ€” to rename a flow helper, delete and recreate'), and the multi-menu `next_step_id`-as-list behavior. It also explains that validation errors carry data_schema and menu_options in the response context for self-correction. No contradiction with the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Long (~550 words) but structurally justified for a 30-type, 43-parameter tool. It is front-loaded: purpose, prerequisite, type taxonomy, required-parameter patterns, then behavior notes, then examples. The main blemish is minor redundancy โ€” update-preservation semantics and the rename-delete-recreate rule appear in both the description and the schema's `config`/`name` descriptions, and the MUST-call instruction is stated twice.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For the most complex tool in its family, the description covers everything needed for a correct first call: required arguments per operation type (name vs helper_id vs entry_id/subentry_type/subentry_id), update semantics, silent-failure handling, error self-correction protocol, routing to alternatives, and worked examples for the non-obvious first-call payloads (template, group, tod, config subentry). With an output schema present and annotations covering safety, nothing essential is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 98% and the schema itself is exemplary (e.g., `initial` restore-disable semantics, `tag_id` auto-generation, `config` patch rules, `name` flow-update note). The description adds the cross-cutting semantics the schema cannot express: the SIMPLE/FLOW/CONFIG_SUBENTRY taxonomy that maps which parameters apply to which type, entry_id doubling as helper_id for flow updates, and the action-fallback discriminator. This is meaningful added value, though individual parameter meaning was already well covered.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening sentence 'Create or update Home Assistant helper entities and config subentries (30 types, unified interface)' states a specific verb pair, a concrete resource, and the scope in one line. It also distinguishes itself from siblings by explicitly routing the excluded `otp` case to ha_set_integration and clarifying that this is the create/update counterpart to list/remove tools like ha_config_list_helpers and ha_remove_helpers_integrations.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description states a hard prerequisite ('MUST call ha_get_skill_guide OR refer to your locally installed skills first'), names the one alternative for an excluded case (ha_set_integration(domain='otp')), and points to the helper-selection.md decision matrix shipped in skill_content. It also gives precise when-to guidance for the `action` parameter, explaining the implicit helper_id/subentry_id presence discriminators and when to disambiguate explicitly.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_config_set_labelCreate or Update LabelA
Destructive

Create or update a Home Assistant label.

Creates a new label if label_id is not provided, or updates an existing label if label_id is provided.

Labels are a flexible tagging system that can be applied to entities, devices, and areas for organization and automation purposes.

EXAMPLES:

  • Create simple label: ha_config_set_label("Critical")

  • Create colored label: ha_config_set_label("Outdoor", color="green")

  • Create label with icon: ha_config_set_label("Battery Powered", icon="mdi:battery")

  • Create full label: ha_config_set_label("Security", color="red", icon="mdi:shield", description="Security-related devices")

  • Update label: ha_config_set_label("Updated Name", label_id="my_label_id", color="blue")

After creating a label, use ha_set_entity(labels=["label_id"]) to assign it to entities.

ParametersJSON Schema
NameRequiredDescriptionDefault
iconNoMaterial Design Icon (e.g., 'mdi:tag', 'mdi:label')
nameYesDisplay name for the label
colorNoColor for the label (e.g., 'red', 'blue', 'green', or hex like '#FF5733')
label_idNoLabel ID for updates. If not provided, creates a new label.
descriptionNoDescription of the label's purpose

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses that the tool modifies state (create/update), consistent with destructiveHint annotation. It adds context about the purpose of labels and how assignments work, going beyond the annotation's simple destructive flag.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise, front-loading the core action, followed by a brief explanation and well-structured examples. Every sentence is useful with no redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the schema coverage, annotations, and presence of an output schema, the description is complete. It explains the create/update behavior, provides examples for all parameters, and links to a related tool for assignment.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema covers all 5 parameters with descriptions (100% coverage). The tool description adds value through concrete examples showing how to use parameters like color, icon, and description in context, which aids understanding beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool creates or updates a Home Assistant label, with explicit differentiation between create (no label_id) and update (with label_id). It distinguishes from siblings like ha_config_get_label and ha_config_remove_label.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains when to use create vs update based on label_id presence, and provides examples for various use cases. It also advises on subsequent steps (use ha_set_entity to assign). While it doesn't explicitly state when not to use it, sibling tools cover other operations.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_config_set_sceneCreate or Update SceneA
Destructive

Create or update a Home Assistant scene.

MUST call ha_get_skill_guide OR refer to your locally installed skills first.

Supports two modes: full config replacement (config) or Python transformation of an existing scene (python_transform). See the field descriptions for python_transform examples and the config shape contract.

WHEN TO USE:

  • python_transform: surgical edits to an existing scene (add/remove/update a single entity entry). Requires config_hash from ha_config_get_scene() for optimistic locking.

  • config: creating a new scene, or wholesale replacement.

WHEN NOT TO USE:

  • To activate a scene at runtime, use ha_call_service(domain="scene", service="turn_on", target=...) โ€” this tool only manages scene configuration, not the runtime turn-on/off side.

  • To list or look up existing scenes, use ha_search(domain_filter="scene").

SCENE SHAPE: entities is a dict keyed by entity_id (e.g., {'light.kitchen': {'state': 'on', 'brightness': 200}}), NOT a list. Automations use a list of actions; scenes capture a snapshot of states as a dict.

EXAMPLE:

ha_config_set_scene(scene_id="movie_night", config={ "name": "Movie Night", "entities": { "light.living_room": {"state": "on", "brightness": 50}, }, "icon": "mdi:movie", })

The top-level SKILL.md for home-assistant-best-practices ships in this response under skill_content by default โ€” generic best-practice index covering entity-naming and safe-refactoring patterns that intersect with scene authoring. For detailed scene configuration help beyond that, use ha_get_skill_guide.

ParametersJSON Schema
NameRequiredDescriptionDefault
waitNoWait for scene to be queryable before returning. Default: True. Set to False for bulk operations.
configNoScene configuration dictionary. Must include 'entities' (a dict keyed by entity_id, NOT a list). Optional fields: 'name' (defaults to scene_id), 'icon', 'id'. Mutually exclusive with python_transform.
categoryNoCategory ID to assign to this scene. Use ha_config_get_category(scope='scene') to list available categories, or ha_config_set_category() to create one.
scene_idYesScene identifier (e.g., 'movie_night')
config_hashNoConfig hash from ha_config_get_scene for optimistic locking. REQUIRED for python_transform (validates scene unchanged). Optional for config updates (validates before full replacement if provided).
MandatoryBPSNo
BestPracticeKeyNoRead-receipt for the home-assistant-best-practices skill; required when strict best-practices mode is enabled. Not a secret or credential: the current value is an attestation phrase published openly at the top of the skill content served by ha_get_skill_guide. Read that content, then pass the value back verbatim โ€” this round-trip is the server's designed protocol confirming the practices were read before writing.
python_transformNoPython expression to transform existing scene config. Mutually exclusive with config. Requires config_hash for validation. WARNING: Expressions with infinite loops will hang the server. Examples: Add entity: python_transform="config['entities']['light.bed'] = {'state': 'on'}" Update brightness: python_transform="config['entities']['light.kitchen']['brightness'] = 50" Remove entity: python_transform="del config['entities']['light.kitchen']" PYTHON TRANSFORM SECURITY: โœ… ALLOWED: - Dictionary/list access: config['views'][0]['cards'][1] - Slicing: config['views'][0]['cards'][1:3] - Assignment: config['key'] = 'value' - Deletion: del config['key'] or config.pop('key') - List methods: append, insert, pop, remove, clear, extend - Dict methods: update, get, setdefault, keys, values, items - Loops: for, if/else, pass, break, continue - Comprehensions: [x for x in ...], {k: v for ...}, (x for x in ...) - Ternary: x if condition else y - Iterable unpacking (* in calls/literals): f(*xs), [*xs, y] - Dict unpacking (**) in calls and dict literals: {**d, 'k': v} - Keyword arguments: func(key=value) - Lambdas (e.g. for `key=`): sorted(items, key=lambda x: x['score']) - String methods: startswith, endswith, lower, upper, strip, split, join, replace - Safe builtins: isinstance, len, range, enumerate, zip, sorted, reversed, min, max, sum, abs, any, all, round, str, int, float, bool, list, dict, tuple, set โŒ FORBIDDEN: - Imports: import, from, __import__ - File operations: open, read, write - Dunder access: __class__, __bases__, __subclasses__ - Dangerous builtins: eval, exec, compile, getattr, setattr, delattr, hasattr - Function definitions: def, class - Exception handling: try/except (validate with isinstance/in/.get() instead) - While loops: use bounded for loops or comprehensions instead ๐ŸŽฏ PATTERNS: - Filter cards: cards = [c for c in cards if keep(c)] - Skip in a loop: prefer `continue` over an empty `pass` branch (clearer) - Conditionally include: build a new list and `.append(x)` only the cards you want, instead of iterating the original and using if/pass branches to drop entries - Modify in place when possible (single pass, fewer surprises) over reconstructing the entire list

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Discloses destructive nature (destructiveHint true) and adds extensive behavior: optimistic locking, mutual exclusivity of parameters, infinite loop risk in python_transform, and a complete list of allowed/forbidden Python operations. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well-structured with clear sections, front-loaded with purpose and mode overview. The python_transform security section, while lengthy, is justified by the need for safe execution. Could trim slightly but maintains clarity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Handles tool complexity comprehensively: covers two modes, prerequisites, security, alternatives, and required preparatory steps (skill guide). With output schema present, return value documentation is unnecessary. No gaps remain.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Adds significant meaning beyond schema (88% coverage): explains config shape (entities as dict, not list), provides python_transform examples and security rules, clarifies config_hash role, and describes BestPracticeKey protocol. Adds example and context for each key parameter.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Clearly states 'Create or update a Home Assistant scene', distinguishing from sibling tools like ha_call_service for runtime activation and ha_search for listing. Explicitly contrasts with ha_config_get_scene and ha_config_remove_scene by defining its role.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit WHEN TO USE and WHEN NOT TO USE sections, detailing two modes (python_transform vs config) with specific prerequisites (config_hash), and names alternative tools (ha_call_service, ha_search) and prerequisite calls (ha_get_skill_guide).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_config_set_scriptCreate or Update ScriptA
Destructive

Create or update a Home Assistant script.

MUST call ha_get_skill_guide OR refer to your locally installed skills first.

PREFER NATIVE ACTIONS OVER TEMPLATES (read this before writing any {{ ... }}): Native actions are validated at config load, fail loudly, and do not bypass HA's schema. Templates in logic positions fail silently and obscure intent.

  • choose / if/then/else instead of template-based service names

  • wait_for_trigger instead of wait_template

  • Native for: field on state conditions inside choose/if, and on state/numeric_state triggers in wait_for_trigger, instead of {{ now() - X.last_changed > timedelta(...) }} duration math.

  • repeat with for_each instead of template loops

  • Hardcode target.entity_id literals โ€” never {{ this.entity_id }}. Templates are appropriate ONLY in data.* fields, notification message/title, event_data, and variables. The reactive best-practice checker on this tool will surface anything in a logic position that should be native; consult the best_practice_warnings field on the response and fix before re-submitting. The relevant skill section is auto-embedded under skill_content on warnings, and the full automation-patterns.md + template-guidelines.md references ship under skill_content proactively by default. For comprehensive guidance beyond that, call ha_get_skill_guide.

Supports two modes: full config replacement OR Python transformation.

WHEN TO USE WHICH MODE:

  • python_transform: RECOMMENDED for edits to existing scripts. Surgical updates.

  • config: Use for creating new scripts or full restructures.

IMPORTANT: python_transform requires 'config_hash' from ha_config_get_script().

PYTHON TRANSFORM EXAMPLES:

  • Update step: python_transform="config['sequence'][0]['data']['message'] = 'Hello'"

  • Add step: python_transform="config['sequence'].append({'delay': {'seconds': 5}})"

  • Remove last step: python_transform="config['sequence'].pop()"

Creates a new script or updates an existing one with the provided configuration. Supports both regular scripts (with sequence) and blueprint-based scripts.

Required config fields (choose one): - sequence: List of actions to execute (for regular scripts) - use_blueprint: Blueprint configuration (for blueprint-based scripts)

Optional config fields: - alias: Display name (defaults to script_id) - description: Script description - icon: Icon to display - mode: Execution mode ('single', 'restart', 'queued', 'parallel') - max: Maximum concurrent executions (for queued/parallel modes) - fields: Input parameters for the script

SCRIPTS vs AUTOMATIONS: Scripts use 'sequence', NOT 'trigger' or 'action'. If you need trigger-based execution, use ha_config_set_automation instead.

EXAMPLES:

Create basic delay script: ha_config_set_script(script_id="wait_script", config={ "sequence": [{"delay": {"seconds": 5}}], "alias": "Wait 5 Seconds", "description": "Simple delay script" })

Create service call script: ha_config_set_script(script_id="blink_light", config={ "sequence": [ {"action": "light.turn_on", "target": {"entity_id": "light.living_room"}}, {"delay": {"seconds": 2}}, {"action": "light.turn_off", "target": {"entity_id": "light.living_room"}} ], "alias": "Light Blink", "mode": "single" })

Create script with parameters: ha_config_set_script(script_id="backup_script", config={ "alias": "Backup with Reference", "description": "Create backup with optional reference parameter", "fields": { "reference": { "name": "Reference", "description": "Optional reference for backup identification", "selector": {"text": None} } }, "sequence": [ { "action": "hassio.backup_partial", "data": { "compressed": False, "homeassistant": True, "homeassistant_exclude_database": True, "name": "Backup_{{ reference | default('auto') }}{{ now().strftime('%Y%m%d%H%M%S') }}" } } ] })

Update script: ha_config_set_script(script_id="morning_routine", config={ "sequence": [ {"action": "light.turn_on", "target": {"area_id": "bedroom"}}, {"action": "climate.set_temperature", "target": {"entity_id": "climate.bedroom"}, "data": {"temperature": 22}} ], "alias": "Updated Morning Routine" })

Create blueprint-based script: ha_config_set_script(script_id="notification_script", config={ "alias": "My Notification Script", "use_blueprint": { "path": "notification_script.yaml", "input": { "message": "Hello World", "title": "Test Notification" } } })

Update blueprint script inputs: ha_config_set_script(script_id="notification_script", config={ "alias": "My Notification Script", "use_blueprint": { "path": "notification_script.yaml", "input": { "message": "Updated message", "title": "Updated Title" } } })

Note: Scripts use Home Assistant's action syntax. Check the documentation for advanced features like conditions, variables, parallel execution, and service call options.

create update modify edit script sequence actions new script write save

ParametersJSON Schema
NameRequiredDescriptionDefault
waitNoWait for script to be queryable before returning. Default: True. Set to False for bulk operations.
configNoScript configuration dictionary. Must include EITHER 'sequence' (for regular scripts) OR 'use_blueprint' (for blueprint-based scripts). Optional fields: 'alias', 'description', 'icon', 'mode', 'max', 'fields'. Mutually exclusive with python_transform.
categoryNoCategory ID to assign to this script. Use ha_config_get_category(scope='script') to list available categories, or ha_config_set_category() to create one.
script_idYesScript identifier โ€” bare storage key ('morning_routine') or entity_id form ('script.morning_routine'); a leading 'script.' prefix is stripped before lookup.
config_hashNoConfig hash from ha_config_get_script for optimistic locking. REQUIRED for python_transform (validates script unchanged). Optional for config updates (validates before full replacement if provided).
MandatoryBPSNo
BestPracticeKeyNoRead-receipt for the home-assistant-best-practices skill; required when strict best-practices mode is enabled. Not a secret or credential: the current value is an attestation phrase published openly at the top of the skill content served by ha_get_skill_guide. Read that content, then pass the value back verbatim โ€” this round-trip is the server's designed protocol confirming the practices were read before writing.
python_transformNoPython expression to transform existing script config. Mutually exclusive with config. Requires config_hash for validation. WARNING: Expressions with infinite loops will hang the server. Examples: Simple: python_transform="config['sequence'][0]['data']['message'] = 'Hello'" Pattern: python_transform="for step in config['sequence']: if step.get('alias') == 'My Step': step['data']['value'] = 100" PYTHON TRANSFORM SECURITY: โœ… ALLOWED: - Dictionary/list access: config['views'][0]['cards'][1] - Slicing: config['views'][0]['cards'][1:3] - Assignment: config['key'] = 'value' - Deletion: del config['key'] or config.pop('key') - List methods: append, insert, pop, remove, clear, extend - Dict methods: update, get, setdefault, keys, values, items - Loops: for, if/else, pass, break, continue - Comprehensions: [x for x in ...], {k: v for ...}, (x for x in ...) - Ternary: x if condition else y - Iterable unpacking (* in calls/literals): f(*xs), [*xs, y] - Dict unpacking (**) in calls and dict literals: {**d, 'k': v} - Keyword arguments: func(key=value) - Lambdas (e.g. for `key=`): sorted(items, key=lambda x: x['score']) - String methods: startswith, endswith, lower, upper, strip, split, join, replace - Safe builtins: isinstance, len, range, enumerate, zip, sorted, reversed, min, max, sum, abs, any, all, round, str, int, float, bool, list, dict, tuple, set โŒ FORBIDDEN: - Imports: import, from, __import__ - File operations: open, read, write - Dunder access: __class__, __bases__, __subclasses__ - Dangerous builtins: eval, exec, compile, getattr, setattr, delattr, hasattr - Function definitions: def, class - Exception handling: try/except (validate with isinstance/in/.get() instead) - While loops: use bounded for loops or comprehensions instead ๐ŸŽฏ PATTERNS: - Filter cards: cards = [c for c in cards if keep(c)] - Skip in a loop: prefer `continue` over an empty `pass` branch (clearer) - Conditionally include: build a new list and `.append(x)` only the cards you want, instead of iterating the original and using if/pass branches to drop entries - Modify in place when possible (single pass, fewer surprises) over reconstructing the entire list

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already set destructiveHint=true. The description adds significant behavioral context: optimistic locking via config_hash, python transform security restrictions (allowed/forbidden operations), wait parameter for bulk operations, and best-practice checker that surfaces warnings. This exceeds annotation expectations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but well-structured with sections, bullet points, and examples. It is front-loaded with critical usage guidance. Some redundancy exists (e.g., repeated examples), but given tool complexity, the structure is appropriate and earns a 4.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 8 parameters, two modes, Python transform security, and integration with best-practice skills, the description covers all necessary aspects. Includes examples for both config and python_transform, references to related tools, and proactive skill content. Output schema exists, so return values are not required.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 88%, but description adds extensive meaning: explains config sub-keys (sequence, use_blueprint, alias, etc.), python_transform with examples and allowed patterns, wait behavior, category linking to other tools, and BestPracticeKey attestation. Every parameter is well-explained.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Create or update a Home Assistant script', distinguishes two modes (config vs python_transform), and explicitly differentiates from sibling tool ha_config_set_automation via the 'SCRIPTS vs AUTOMATIONS' section. The verb and resource are specific, and examples confirm purpose.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit when-to-use guidance: python_transform for edits, config for new/full restructures. Requires config_hash for python_transform. Details prerequisites, best-practice preferences (native over templates), and when to use automation instead. Examples cover multiple scenarios.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_eval_templateEvaluate TemplateA
Read-onlyIdempotent

Evaluate Jinja2 templates using Home Assistant's template engine.

This tool allows testing and debugging of Jinja2 template expressions that are commonly used in Home Assistant automations, scripts, and configurations. It provides real-time evaluation with access to all Home Assistant states, functions, and template variables.

When NOT to use this for automation/script logic: Templates have legitimate uses (notification bodies, dynamic data.* values, debugging existing templates), but condition: / trigger: positions and action service names are better expressed as native HA constructs: native constructs are schema-validated at config load and surface structural errors loudly, whereas equivalent template logic only errors at runtime โ€” and a template that renders a non-truthy value is silently treated as false. Prefer:

  • condition: numeric_state over {{ states('x') | float > N }}

  • condition: state over {{ is_state(...) }}

  • condition: time / condition: sun over now().hour / is_state('sun.sun', ...)

  • Native for: field on state/numeric_state triggers and state conditions over {{ now() - X.last_changed > timedelta(...) }} duration math

  • choose action over templated service: / action: strings See ha_get_skill_guide (best-practices skill) for the full anti-pattern list.

When to use (reach for this tool, don't compute it yourself): Any one-shot question whose answer is DERIVED from current HA state โ€” an average/sum/min/max across sensors, a count of entities matching a condition, a boolean comparison, or a rendered message with live values. One render call beats fetching N states and doing the math yourself, and it is the canonical way to test a template before embedding it. This is for one-shot answers and template testing only โ€” NOT for putting templates into automation logic; for condition: / trigger: positions native constructs win.

  • "average temperature across the bedroom sensors" -> {{ ([states('sensor.a'), states('sensor.b')] | map('float', 0) | sum) / 2 }}

  • "how many lights are on" -> {{ states.light | selectattr('state', 'eq', 'on') | list | count }} NOT for a plain single-entity value ("what's the state of X") โ€” that is ha_get_state / ha_search; rendering {{ states('X') }} there is over-use.

Parameters:

  • template: The Jinja2 template string to evaluate

  • timeout: Maximum evaluation time in seconds (default: 3)

  • report_errors: Whether to return detailed error information (default: True)

Common Template Functions:

State Access:

{{ states('sensor.temperature') }}              # Get entity state value
{{ states.sensor.temperature.state }}           # Alternative syntax
{{ state_attr('light.bedroom', 'brightness') }} # Get entity attribute
{{ is_state('light.living_room', 'on') }}       # Check if entity has specific state

Numeric Operations:

{{ states('sensor.temperature') | float(0) }}   # Convert to float with default
{{ states('sensor.humidity') | int(0) }}        # Convert to integer with default
{{ (states('sensor.temp') | float(0) + 5) | round(1) }} # Math operations

Time and Date:

{{ now() }}                                     # Current datetime
{{ now().strftime('%H:%M:%S') }}               # Format current time
{{ as_timestamp(now()) }}                      # Convert to Unix timestamp
{{ now().hour }}                               # Current hour (0-23)
{{ now().weekday() }}                          # Day of week (0=Monday)

Conditional Logic (for display strings โ€” not for condition: positions):

{{ 'Day' if now().hour < 18 else 'Night' }}    # Ternary operator
{% if is_state('alarm_control_panel.home', 'armed_away') %}
  Alarm is armed
{% else %}
  Alarm is disarmed
{% endif %}

Lists and Loops:

{% for entity in states.light %}
  {{ entity.entity_id }}: {{ entity.state }}
{% endfor %}

{{ states.light | selectattr('state', 'eq', 'on') | list | count }} # Count on lights

String Operations:

{{ states('sensor.weather') | title }}         # Title case
{{ 'Hello ' + states('input_text.name') }}     # String concatenation
{{ states('sensor.data') | regex_replace('pattern', 'replacement') }}

Device and Area Functions:

{{ device_entities('device_id_here') }}        # Get entities for device
{{ area_entities('living_room') }}             # Get entities in area
{{ device_id('light.bedroom') }}               # Get device ID for entity

Common Use Cases (legitimate template positions):

Dynamic Service Data:

# Dynamic brightness based on time
{{ 255 if now().hour < 22 else 50 }}

# Message with current values
"Temperature is {{ states('sensor.temp') }}ยฐC, humidity {{ states('sensor.humidity') }}%"

Examples:

Test basic state access:

ha_eval_template("{{ states('light.living_room') }}")

Test a string expression (e.g. for a notification body):

ha_eval_template("{{ 'Day' if now().hour < 18 else 'Night' }}")

Test mathematical operations:

ha_eval_template("{{ (states('sensor.temperature') | float(0) + 5) | round(1) }}")

Test entity counting:

ha_eval_template("{{ states.light | selectattr('state', 'eq', 'on') | list | count }}")

IMPORTANT NOTES:

  • Templates have access to all current Home Assistant states and attributes

  • Use this tool to test templates before using them in automations or scripts

  • Template evaluation respects Home Assistant's security model and timeouts

  • Complex templates may affect Home Assistant performance - keep them efficient

  • Use default values (e.g., | float(0)) to handle missing or invalid states

For template documentation: https://www.home-assistant.io/docs/configuration/templating/

ParametersJSON Schema
NameRequiredDescriptionDefault
timeoutNo
templateYes
report_errorsNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already provide readOnlyHint, idempotentHint, openWorldHint. Description adds context about access to all HA states, security model, timeouts, and performance impact. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well-structured with sections and examples, but overly verbose with a large catalog of common template functions. Could be more concise while retaining essential information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers purpose, usage guidelines, parameter details, common functions, examples, and important notes. Output schema exists, so return values need not be described. Complete for the tool's complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, but the description compensates with a 'Parameters:' section giving clear one-line explanations for each parameter (template, timeout, report_errors). Adds meaning beyond the bare schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Clearly states 'Evaluate Jinja2 templates using Home Assistant's template engine', with specific verb and resource. Distinguishes from sibling tools like ha_get_state and ha_search by explicitly stating when not to use for plain state queries and providing alternatives.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit when-to-use (one-shot derived answers, template testing) and when-not-to-use (automation/script logic) guidance, with specific alternatives for native constructs. Includes examples and references to ha_get_skill_guide for best practices.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_get_appGet Apps (add-ons)A
Read-onlyIdempotent

Get installed or available Home Assistant apps (add-ons), or details for one.

Do not use this tool to change app state or configuration; use ha_manage_app. Use slug for details, source="installed" for an inventory, or source="available" for store discovery.

Requires Home Assistant OS or Supervised. include_stats applies only to installed-app listings.

ParametersJSON Schema
NameRequiredDescriptionDefault
slugNoApp (add-on) slug for detailed info (e.g., '<prefix>_nodered'). Slug prefixes vary by app repository โ€” omit to list all apps and discover the actual installed slug.
queryNoApp (add-on) name/description filter (only for source='available')
sourceNoApp (add-on) source: 'installed' (default) for currently installed apps, 'available' for apps in the store that can be installed.
repositoryNoFilter by repository slug, e.g., 'core', 'community' (only for source='available')
include_statsNoInclude CPU/memory usage statistics (only for source='installed')

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover read-only/idempotent behavior, and the description adds beyond that: the requirement for Home Assistant OS or Supervised and the mode-specific applicability of include_stats. No contradiction with the annotations; it doesn't discuss potential failures or return shape, but the output schema covers return details.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short paragraphs front-load the purpose, then give routing guidance and constraints. Every sentence carries useful information, and there is no filler or redundant explanation.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given five optional parameters with mode-specific behavior, an output schema, and read-only annotations, the description covers the essential usage modes, exclusions, and environment requirements. An agent has enough context to select and call the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The main description rephrases the schema's mode guidance (slug, source, include_stats) but does not add substantive new meaning to the parameters beyond what the schema already documents.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Get installed or available Home Assistant apps (add-ons), or details for one.' It clearly distinguishes this read-only retrieval tool from the sibling ha_manage_app by stating it is not for changing state or configuration.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit routing: use ha_manage_app for changes, slug for details, source='installed' for inventory, and source='available' for store discovery. It also states the environment prerequisite (Home Assistant OS or Supervised), leaving little ambiguity about when to invoke this tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_get_automation_tracesGet Automation TracesA
Read-onlyIdempotent

Retrieve execution traces for automations and scripts to debug issues.

Traces show what happened during automation/script runs:

  • What triggered the automation

  • Which conditions passed or failed

  • What actions were executed

  • Any errors that occurred

  • Variable values during execution

USAGE MODES:

  1. List recent traces (omit run_id): ha_get_automation_traces("automation.motion_light") Returns a summary of recent execution runs with timestamps, triggers, and status. Use offset to page deeper when has_more is true, or order="oldest" to start from the earliest stored trace instead of the most recent.

  2. Get detailed trace (provide run_id): ha_get_automation_traces("automation.motion_light", run_id="1705312800.123456") Returns full execution details including trigger info, condition results, action trace with timing, and context variables.

  3. Get detailed trace with logbook (provide run_id and detailed=True): ha_get_automation_traces("automation.motion_light", run_id="1705312800.123456", detailed=True) Returns the formatted trace plus logbook entries and context metadata. Useful when the standard trace summary doesn't reveal enough for debugging. Note: script-style action paths (sequence/, numeric) are always matched regardless of this flag.

  4. Get full variables without deduplication (provide run_id and deduplicate=False): ha_get_automation_traces("automation.motion_light", run_id="1705312800.123456", deduplicate=False) Returns the formatted trace with full variables at every action step.

DEBUGGING EXAMPLES:

Automation not triggering:

  • Check if traces exist (automation may not be triggered)

  • Look at trigger info to see what event was received

Automation runs but conditions fail:

  • Get detailed trace to see condition_results

  • Each condition shows whether it passed (true) or failed (false)

Unexpected behavior in actions:

  • Get detailed trace to see action_trace

  • Shows each action step with result and any errors

  • For 'choose' actions, shows which branch was taken

Template debugging:

  • Detailed trace shows evaluated template values in context

  • Trigger variables available under trigger_variables

NOTES:

  • Traces are stored for a limited time by Home Assistant

  • Works for both automations and scripts (use full entity_id)

  • The 'state' field shows: 'stopped' (completed), 'running', or error state

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum number of traces to return when listing (default: 10, max: 50).
orderNoOrder traces are returned in. 'newest' (default) returns most-recent first; 'oldest' returns chronological-first.newest
offsetNoNumber of traces to skip from the start of the requested order. Use with `limit` to page through stored traces when `total_available > limit`.
run_idNoSpecific trace run_id to retrieve detailed trace. Omit to list recent traces.
detailedNoInclude extra diagnostic data: logbook entries and context metadata (default: False). Use when standard trace lacks detail for debugging.
sectionsNoComma-separated list of trace sections to return. Valid values: trigger, conditions, actions, config, error, logbook, context. Omit to return all sections. Example: 'actions' or 'trigger,conditions'.
deduplicateNoDeduplicate variables across action steps (default: True). Set to False to include full variables at every step.
automation_idYesAutomation or script entity_id (e.g., 'automation.motion_light' or 'script.morning_routine')

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description goes far beyond annotations (readOnlyHint, idempotentHint) by explaining trace storage limits, behavior of pagination, effect of parameters like detailed and deduplicate, and expected state field values. This fully discloses behavioral traits.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-organized with clear headings (USAGE MODES, DEBUGGING EXAMPLES, NOTES), front-loaded purpose, and no redundant text. Every sentence adds value, making it easy to scan and understand quickly.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (8 parameters, automation debugging), the description covers all usage modes, parameter behavior, debugging scenarios, and limitations. An output schema exists, so return values are handled; the description is fully self-contained.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description adds significant meaning beyond the input schema by demonstrating parameter usage in concrete examples (e.g., omitting run_id for listing, providing it for details, using detailed=True for extra diagnostics). Schema coverage is 100%, but the description enriches each parameter's role.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it retrieves execution traces for automations and scripts to debug issues, detailing what traces show (triggers, conditions, actions, errors, variables). It is unambiguous and distinct from sibling tools, which focus on logs, history, or other operations.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides extensive usage modes and debugging examples, guiding when to use each mode (list vs. detailed vs. logbook). However, it does not explicitly state when not to use this tool or mention alternatives, missing the full 'when-not' guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_get_blueprintGet BlueprintA
Read-onlyIdempotent

Get blueprint information - list all blueprints or get details for a specific one.

Without a path: Lists all installed blueprints for the specified domain. With a path: Returns the blueprint's metadata and input definitions. The full body (triggers/conditions/actions for automations, sequence for scripts) is included under config ONLY when the ha_mcp_tools custom component is installed โ€” core's blueprint API exposes metadata alone, so without the component the body cannot be read.

EXAMPLES:

  • List all automation blueprints: ha_get_blueprint(domain="automation")

  • List script blueprints: ha_get_blueprint(domain="script")

  • Get specific blueprint: ha_get_blueprint(path="homeassistant/motion_light.yaml", domain="automation")

RETURNS (when listing):

  • List of blueprints with path, name, and domain information

  • Count of blueprints found

RETURNS (when getting specific blueprint):

  • Blueprint metadata (name, description, author, source_url)

  • Input definitions with selectors and defaults

  • config: the full parsed blueprint body (only with the ha_mcp_tools component; !input substitution points appear as {"__input__": name})

ParametersJSON Schema
NameRequiredDescriptionDefault
pathNoBlueprint path to get details for (e.g., 'homeassistant/motion_light.yaml'). If omitted, lists all blueprints in the domain.
domainNoBlueprint domain: 'automation' or 'script'automation

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Discloses critical behavior: the `config` key is only available with the ha_mcp_tools custom component. Annotations already indicate readOnly, idempotent, open world, and description adds no contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well-structured with sections for general description, mode explanation, examples, and return values. Front-loaded with main purpose. Slightly long but every sentence adds value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Fully covers the tool's complexity: two modes, conditional behavior of `config`, return structures. No gaps given the output schema exists and is described.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema covers 100% of parameters with descriptions. The description adds context by explaining the effect of each parameter (e.g., path omission triggers listing) and provides examples.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Clearly states the tool gets blueprint information, distinguishing between listing all blueprints and getting details for a specific one. The verb and resource are explicit, and it differentiates from sibling tools like ha_import_blueprint.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Describes when to use without path (list all) and with path (get details), with concrete examples. Does not explicitly compare to alternatives but the context is sufficient.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_get_camera_imageGet Camera ImageA
Read-onlyIdempotent

Retrieve a snapshot image from a Home Assistant camera entity.

This tool fetches the current camera image and returns it directly for visual analysis. Use this when you need to see what a camera is currently viewing.

Parameters:

  • entity_id: Camera entity ID (e.g., 'camera.front_door', 'camera.living_room')

  • width: Optional width to resize the image (reduces token usage for large images)

  • height: Optional height to resize the image

Use Cases:

  • Security checks: "Is someone at the front door?"

  • Pet monitoring: "Is my dog still on the couch?"

  • Delivery verification: "Did my package get delivered?"

  • Visual confirmation: "Did the garage door actually close?"

  • Incident investigation: "What triggered the motion sensor?"

Example Usage:

# Get current snapshot from front door camera
ha_get_camera_image(entity_id="camera.front_door")

# Get resized image to reduce token usage
ha_get_camera_image(entity_id="camera.backyard", width=640, height=480)

Notes:

  • Only cameras exposed to Home Assistant are accessible

  • The existing HA authentication/authorization applies

  • Images are returned in their native format (JPEG, PNG, or GIF)

  • Use width/height parameters for large high-resolution cameras to reduce token usage when full resolution is not needed

Related Services:

  • camera.snapshot: Save snapshot to file on HA server

  • camera.turn_on/turn_off: Control camera power

  • camera.enable_motion_detection: Enable motion detection

ParametersJSON Schema
NameRequiredDescriptionDefault
widthNo
heightNo
entity_idYes

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and idempotentHint=true. The description adds further behavioral detail: images are returned in native format, token usage can be reduced via width/height, and only cameras exposed to HA are accessible. No contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well-structured with sections: description, parameters, use cases, example, notes, related services. Front-loaded with main purpose. Every sentence adds valueโ€”no fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite no output schema, description explains return format (JPEG/PNG/GIF), authentication, camera availability, and token optimization. Covers all essential aspects for correct invocation and expectation setting.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Input schema has 0% parameter description coverage, so the description must compensate. It lists all three parameters with explanations (entity_id format, width/height purpose to 'reduce token usage') and provides example values inline, greatly enriching the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a clear verb+resource: 'Retrieve a snapshot image from a Home Assistant camera entity.' It specifies the exact action and target, and given the sibling list includes many other HA tool types, this tool is well-distinguished as the only one focused on camera snapshots.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit use cases (security, pet monitoring, etc.) and example usage with code. Also lists 'Related Services' that contrast with this tool (e.g., camera.snapshot saves to file), giving the agent clear when-to-use and when-not-to-use guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_get_deviceGet Device (incl. Zigbee/ZHA/Z2M, Z-Wave and Matter)A
Read-onlyIdempotent

Get device information with pagination, including Zigbee (ZHA/Z2M) and Z-Wave JS devices.

Without device_id/entity_id: Lists devices with optional filters and pagination. With device_id or entity_id: Returns full detail for that specific device.

List devices (paginated):

  • First page: ha_get_device()

  • Next page: ha_get_device(offset=50)

  • By area: ha_get_device(area_id="living_room")

  • By integration: ha_get_device(integration="zigbee2mqtt")

  • Full details in list: ha_get_device(detail_level="full", limit=10)

Single device lookup (always full detail):

  • By device_id: ha_get_device(device_id="abc123")

  • By entity_id: ha_get_device(entity_id="light.living_room")

Zigbee: integration="zha" or "zigbee2mqtt". Returns ieee_address, radio metrics. Z-Wave: integration="zwave_js". Returns node_id, node_status. Matter: integration="matter". Returns node_diagnostics (network type, reachability, IPs, fabrics). For management use ha_manage_radio.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMax devices to return per page in list mode (default: 50)
offsetNoNumber of devices to skip for pagination (default: 0)
area_idNoFilter devices by area ID (e.g., 'living_room')
device_idNoDevice ID to retrieve details for. If omitted, lists devices.
entity_idNoEntity ID to find the associated device for (e.g., 'light.living_room')
integrationNoFilter devices by integration: 'zha', 'zigbee2mqtt', 'zwave_js', 'mqtt', 'hue', etc.
detail_levelNo'summary': basic device info and protocol identifiers (default for list mode). 'full': include entities and all integration details. Single device lookups always return full detail.summary
manufacturerNoFilter devices by manufacturer name (e.g., 'Philips')

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark the tool as read-only and idempotent. The description adds rich behavioral context: pagination behavior, default limits, mode switching via device_id/entity_id, integration-specific return fields (e.g., ieee_address, node_id), and detail level effects. No contradictions with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-organized with clear sections, examples, and formatting. It is concise yet comprehensive, using bullet points and code blocks efficiently. No unnecessary text; every sentence adds value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite the tool's complexity (multiple modes, many parameters, integration specifics), the description covers all aspects: pagination, filtering, detail levels, single lookup, integration details, and even a pointer to a sibling tool (ha_manage_radio). With an output schema present, the description is more than complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, and the description enhances every parameter with real-world examples and contextual meaning. It explains how device_id/entity_id switch modes, how detail_level affects output, and what integration values imply. Examples like ha_get_device(offset=50) clarify pagination semantics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool retrieves device information with pagination, distinguishing between listing devices and single lookup. It specifies coverage of Zigbee, Z-Wave, and Matter integrations. While not explicitly differentiating from siblings, the purpose is highly specific and unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit usage patterns: list vs single lookup, pagination examples, filtering by area/integration, and detail levels. It also notes when to use ha_manage_radio for radio management, offering clear guidance on alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_get_entityGet EntityA
Read-onlyIdempotent

Get entity registry information for one or more entities.

Returns detailed entity registry metadata including area assignment, custom name/icon, enabled/hidden state, aliases, labels, and more.

RESOLVER MODE: Pass unique_id (instead of entity_id) to resolve a stable integration unique_id to its entity_id(s). Since the registry's unique key is (domain, platform, unique_id), the same unique_id can match multiple platforms โ€” all matches are returned in entity_entries with a matches count. Narrow with domain/platform. Resolver reads as_partial_dict, so aliases and the device_class override come back as defaults ([]/null).

RELATED TOOLS:

  • ha_set_entity(): Modify entity properties (area, name, icon, enabled, hidden, aliases)

  • ha_get_state(): Get current state/attributes (on/off, temperature, etc.)

  • ha_search(): Find entities by name, domain, or area

EXAMPLES:

  • Single entity: ha_get_entity("sensor.temperature")

  • Multiple entities: ha_get_entity(["light.living_room", "switch.porch"])

RESPONSE FIELDS:

  • entity_id: Full entity identifier

  • name: Custom display name (null if using original_name)

  • original_name: Default name from integration

  • icon: Custom icon (null if using default)

  • area_id: Assigned area/room ID (null if unassigned)

  • disabled_by: Why disabled (null=enabled, "user"/"integration"/etc)

  • hidden_by: Why hidden (null=visible, "user"/"integration"/etc)

  • enabled: Boolean shorthand (True if disabled_by is null)

  • hidden: Boolean shorthand (True if hidden_by is not null)

  • aliases: Voice assistant aliases

  • labels: Assigned label IDs

  • categories: Category assignments (dict mapping scope to category_id)

  • device_class: User "Show As" override (null = use original_device_class)

  • original_device_class: Default device class from the integration

  • options: Per-domain registry options (e.g. sensor display_precision). Voice-assistant exposure is also stored here but should be set/cleared via the ha_set_entity(expose_to=...) parameter, not the options dict.

  • platform: Integration platform (e.g., "hue", "zwave_js")

  • device_id: Associated device ID (null if standalone)

  • config_entry_id: Parent config entry's ID (null for YAML-only entities). When non-null โ€” e.g. for UI-created template/group/ utility_meter/derivative/... helpers โ€” pass it to ha_get_integration(entry_id=..., include_options=True) to read the helper's current config (template body, group members, etc.) without scanning a domain list.

  • unique_id: Integration's unique identifier

Resolved-name enrichment (present only when the ha_mcp_tools component advertises it; otherwise these keys are absent):

  • area: Assigned area NAME (device-inherited when the entity has none; resolves area_id above)

  • floor: Floor NAME of the assigned area

  • label_names: Assigned label NAMES (resolves the label ids in labels) Resolved label names live under label_names HERE (this tool's base labels already carries the label ids); ha_search result_fields and ha_get_entity_exposure instead emit the resolved names under labels.

get entity state attributes details single specific entity_id

ParametersJSON Schema
NameRequiredDescriptionDefault
domainNoResolver filter (unique_id mode only): restrict matches to this entity domain, e.g. 'sensor'.
platformNoResolver filter (unique_id mode only): restrict matches to this integration platform, e.g. 'hue'.
entity_idNoEntity ID or list of entity IDs to retrieve (e.g., 'sensor.temperature' or ['light.living_room', 'switch.porch']). Mutually exclusive with unique_id.
unique_idNoResolve a stable integration unique_id to its entity_id(s) (entity_id is mutable, unique_id is not). Mutually exclusive with entity_id. Optionally narrow with domain/platform.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate readOnlyHint=true and idempotentHint=true. The description adds substantial behavioral context: explains resolver mode behavior, details response fields including resolved-name enrichment, warns about aliases/device_class defaults in resolver mode, and provides guidance on using config_entry_id for helper configuration retrieval. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Description is long but well-structured with clear sections (RESOLVER MODE, RELATED TOOLS, EXAMPLES, RESPONSE FIELDS). Information is front-loaded with the core purpose. While some technical details could be compressed, the structure is logical and aids readability.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool complexity (4 parameters, output schema, annotations), the description is exceptionally complete. It explains all response fields, includes rich behavioral details, and links to complementary tools. The resolved-name enrichment caveat adds valuable context. No gaps identified.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3. The description adds value by explaining resolver mode, mutual exclusivity of entity_id and unique_id, and the role of domain/platform filters. It does not repeat schema details but provides contextual meaning beyond the parameter descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Get entity registry information for one or more entities.' It uses a specific verb ('get') and resource ('entity registry information'), and distinguishes from sibling tools like ha_set_entity (modify), ha_get_state (current state), and ha_search (find entities).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains the resolver mode for unique_id, provides examples for single/multiple entities, and lists related tools with brief descriptions. However, it does not explicitly state when not to use this tool or when alternatives are preferred beyond the related tools list.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_get_entity_exposureGet Entity ExposureA
Read-onlyIdempotent

Get entity exposure settings - list all or get settings for a specific entity.

Without an entity_id: Lists all entities and their exposure status to voice assistants (Alexa, Google Assistant, Assist).

With an entity_id: Returns which voice assistants the specific entity is exposed to.

EXAMPLES:

  • List all exposures: ha_get_entity_exposure()

  • Filter by assistant: ha_get_entity_exposure(assistant="cloud.alexa")

  • Get specific entity: ha_get_entity_exposure(entity_id="light.living_room")

RETURNS (when listing):

  • exposed_entities: Dict mapping entity_ids to their exposure status

  • summary: Count of entities exposed to each assistant

RETURNS (when getting specific entity):

  • exposed_to: Dict of assistant -> True/False for each assistant

  • is_exposed_anywhere: True if exposed to at least one assistant

When the ha_mcp_tools component advertises the exposure capability, each record is additively enriched with the entity's name/area so no second ha_search is needed to identify it: friendly_name, domain, area, floor, and labels (plus state for entities that have one) on a single-entity lookup, and a parallel entity_info map keyed by entity_id when listing. These fields are absent when the component is unavailable.

ParametersJSON Schema
NameRequiredDescriptionDefault
assistantNoFilter by assistant: 'conversation', 'cloud.alexa', or 'cloud.google_assistant'. If not specified, returns all.
entity_idNoEntity ID to check exposure settings for. If omitted, lists all entities with exposure settings.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description goes beyond annotations by detailing the return structure for both listing and single-entity cases, explaining conditional enrichment when the ha_mcp_tools component is available, and noting which fields are absent otherwise. This fully discloses behavioral traits.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with sections for general behavior, examples, and return values. It is slightly verbose due to detailed return info, but every sentence adds value. It is front-loaded with the main purpose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with only 2 optional parameters and an output schema, the description covers all necessary aspects: multiple usage modes, filtering, conditional enrichment, and detailed return format. It is fully complete given the tool's complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with descriptions for both parameters. The tool description adds extra value by providing usage examples and explaining the effect of omitting entity_id (list vs specific), which enriches understanding beyond the schema alone.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool gets entity exposure settings, with two distinct modes: listing all entities or getting a specific entity. The verb 'get' and resource 'entity exposure' are specific and unambiguous. It distinguishes itself from sibling tools like ha_get_entity and ha_get_state by focusing exclusively on voice assistant exposure settings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear usage context through examples for listing all, filtering by assistant, and getting a specific entity. It implicitly differentiates from other entity tools by its specialized purpose, but lacks explicit 'when not to use' guidance or direct comparison with alternatives like ha_get_entity.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_get_hacs_infoGet HACS InfoA
Read-onlyIdempotent

Get HACS (Home Assistant Community Store) data โ€” search the store or fetch repository details.

Use action="search" to search/browse/list store repositories, or action="info" for one repository's full details (README, versions, GitHub stats). This tool is read-only; to install or add repositories use ha_manage_hacs, and for non-HACS entities/config use the domain-specific tools.

DASHBOARD TIP: action="search", installed_only=True, category="lovelace" discovers installed custom cards to wire into ha_config_set_dashboard().

Examples:

  • Search the store: ha_get_hacs_info(action="search", query="mushroom", category="lovelace")

  • List installed: ha_get_hacs_info(action="search", installed_only=True)

  • Repository details: ha_get_hacs_info(action="info", repository_id="441028036")

Caveats: info fetches full repository detail from GitHub, so it can hit GitHub rate limits / needs HACS's configured GitHub token; search reads HACS's locally cached repository index. repository_id accepts a numeric HACS ID or an owner/repo path.

ParametersJSON Schema
NameRequiredDescriptionDefault
queryNoSearch keyword (action='search')
actionYes'search' the store, or 'info' for one repository
offsetNoResults to skip for pagination (action='search', default: 0)
categoryNoFilter by category (action='search')
max_resultsNoMaximum number of results (action='search', default: 10, max: 100)
repository_idNoNumeric HACS ID or 'owner/repo' path (action='info')
installed_onlyNoOnly return installed repositories (action='search', default: False)

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate readOnly, openWorld, idempotent. Description adds critical caveats: GitHub rate limits for info action, local cache for search, and format for repository_id. No contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well-structured with overview, usage guidance, dashboard tip, examples, and caveats. Every sentence adds value without redundancy. Efficiently front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 7 parameters, two modes, and existing output schema, description covers all necessary aspects: behavior, parameter details, constraints, and integration with ecosystem. Complete for a complex tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, baseline 3. Description adds substantial value beyond schema: explains actions, provides dashboard tip, examples, and caveats for repository_id. Demonstrates parameter usage effectively.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it retrieves HACS data with two actions (search and info). It distinguishes from sibling tools like ha_manage_hacs for installation and non-HACS domain-specific tools, providing a specific verb and resource.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly explains when to use search vs info, and when not to use this tool (e.g., for installation, use ha_manage_hacs; for non-HACS entities, use other tools). Includes a dashboard tip and examples.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_get_historyGet Entity History or StatisticsA
Read-onlyIdempotent

Retrieve historical data from Home Assistant's recorder.

Sources:

  • "history" (default): Raw state changes, ~10 day retention, full resolution

  • "statistics": Pre-aggregated data, permanent retention, requires state_class

Shared params: entity_ids, start_time, end_time, limit, offset History params: minimal_response, significant_changes_only Statistics params: period, statistic_types

Default time range: 24h for history, 30 days for statistics

Use ha_get_history (default) when:

  • Troubleshooting why a value changed ("Why was my bedroom cold last night?")

  • Checking event sequences ("Did my garage door open while I was away?")

  • Analyzing recent patterns ("What time does motion usually trigger?")

Use ha_get_history(source="statistics") when:

  • Tracking long-term trends beyond 10 days ("Energy use this month vs last month?")

  • Computing period averages ("Average living room temperature over 6 months?")

  • Entities must have state_class (measurement, total, total_increasing)

WARNING: limit and offset apply per entity (not globally across all entities). All data is fetched from HA before slicing; limit/offset are client-side. With multiple entity_ids, offset must be 0 โ€” use a single entity_id for offset > 0. Use has_more and next_offset from the response to paginate.

Example -- history (default):

ha_get_history(entity_ids="sensor.bedroom_temperature", start_time="24h")
ha_get_history(entity_ids=["sensor.temperature", "sensor.humidity"], start_time="7d", limit=500)
# Default order="desc" returns newest states first.
# To paginate oldest-first, use order="asc":
ha_get_history(entity_ids="sensor.temperature", start_time="7d", limit=100, offset=100, order="asc")

Example -- statistics:

ha_get_history(source="statistics", entity_ids="sensor.total_energy_kwh", start_time="30d", period="day")
ha_get_history(source="statistics", entity_ids="sensor.living_room_temperature",
               start_time="6m", period="month", statistic_types=["mean", "min", "max"])
ha_get_history(source="statistics", entity_ids="sensor.energy_kwh",
               start_time="30d", period="5minute", limit=100, offset=200)
ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMax entries per entity. Default: 100, Max: 1000. For source="history": state changes. For source="statistics": aggregated rows. With multiple entity_ids, offset must be 0 and total rows returned can reach limit ร— len(entity_ids).
orderNoSort order for history entries. "desc" (default): newest first. "asc": oldest first (chronological, as returned by HA API). Ignored when source="statistics".desc
fieldsNoReturn only the specified top-level response keys to reduce response size. None = full response (default). History keys: success, source, entities, period, query_params. Statistics keys: success, source, entities, period_type, time_range, statistic_types, query_params, warnings.
offsetNoNumber of entries to skip per entity for pagination. Default: 0. Offset > 0 requires a single entity_id. Use with limit and has_more/next_offset in the response.
periodNoAggregation period: "5minute", "hour", "day", "week", "month", "year". Default: "day". Ignored when source="history"day
sourceNoData source: "history" (default) for raw state changes (~10 day retention), or "statistics" for pre-aggregated long-term data (permanent, requires state_class).history
end_timeNoEnd time: ISO datetime. Default: now
entity_idsYesEntity ID(s) to query. Can be a single ID, comma-separated string, or JSON array.
start_timeNoStart time: ISO datetime or relative (e.g., '24h', '7d', '30d'). Default: 24h ago for history, 30d ago for statistics
statistic_typesNoStatistics types: "mean", "min", "max", "sum", "state", "change". Default: all. Ignored when source="history"
minimal_responseNoReturn only states/timestamps without attributes. Default: true. Ignored when source="statistics"
significant_changes_onlyNoFilter to significant state changes only. Default: true. Ignored when source="statistics"

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate readOnlyHint=true and idempotentHint=true, but the description adds significant behavioral context: data retention durations (10 days for history, permanent for statistics), client-side slicing of limit/offset, per-entity application of pagination, and the fact that order is ignored for statistics. This goes well beyond the annotations to fully disclose tool behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with sections for sources, shared/history/statistics params, warnings, and examples. It is front-loaded with the core purpose, uses bullet points for readability, and every sentence provides useful information. Despite its length, it is concise and avoids redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (two data sources, pagination, multiple parameter interactions), the description covers all essential aspects: default time ranges, offset limitations, client-side slicing, order behavior, and examples for both modes. With an output schema present, no further detail on return values is needed. The description is fully complete for agent decision-making.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Although the input schema already has 100% description coverage, the description adds substantial meaning by explaining parameter behavior across sources, providing defaults, and offering examples that illustrate parameter combinations. It clarifies interactions like limit and offset per entity, and which parameters are ignored in each mode, adding value beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool retrieves historical data from Home Assistant's recorder, specifying two distinct sources ('history' and 'statistics') and their use cases. This distinguishes it from sibling tools like ha_get_state or ha_get_entity, which handle current state or entity configuration. The purpose is specific and actionable.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit when-to-use guidance for each source, with concrete examples like 'Troubleshooting why a value changed' for history and 'Tracking long-term trends beyond 10 days' for statistics. It also includes warnings about limit/offset behavior, offset constraints with multiple entities, and pagination hints, making it clear when and how to use the tool correctly.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_get_integrationGet IntegrationA
Read-onlyIdempotent

Get integration (config entry) information with pagination.

Without an entry_id: Lists all configured integrations with optional filters. With an entry_id: Returns detailed information including full options/configuration.

EXAMPLES:

  • List all integrations: ha_get_integration()

  • Paginate: ha_get_integration(offset=50)

  • Search: ha_get_integration(query="zigbee")

  • Get specific entry: ha_get_integration(entry_id="abc123")

  • Get entry with editable fields: ha_get_integration(entry_id="abc123", include_schema=True)

  • Get entry with diagnostics dump: ha_get_integration(entry_id="abc123", include_diagnostics=True)

  • Get device-scoped diagnostics: ha_get_integration(entry_id="abc123", include_diagnostics=True, device_id="dev123")

  • Get the parsed KNX ETS project (group-address table): ha_get_integration(entry_id="", include_knx_project=True)

  • Walk a sub-tree: ha_get_integration(entry_id="abc123", include_diagnostics=True, diagnostics_data_path="")

  • Paginate a large list: ha_get_integration(entry_id="abc123", include_diagnostics=True, diagnostics_data_path="", diagnostics_data_limit=10, diagnostics_data_offset=20)

  • List config subentries: ha_get_integration(entry_id="abc123", include_subentries=True)

  • Inspect subentry create schema: ha_get_integration(entry_id="abc123", include_subentry_schema=True, subentry_type="conversation")

  • Inspect subentry reconfigure schema: ha_get_integration(entry_id="abc123", include_subentry_schema=True, subentry_type="conversation", subentry_id="sub123")

  • List template entries: ha_get_integration(domain="template")

STATES: 'loaded', 'setup_error', 'setup_retry', 'not_loaded', 'failed_unload', 'migration_error'.

OPTIONS: options reflect the entry's persisted values; a field that was never set may be absent (rather than shown at its schema default). Values that match a secrets.yaml entry are returned as "**redacted**". Use include_schema=True to see every editable field and its default/type. Nested option sections (e.g. a template helper's advanced_options) are additively flattened one level โ€” each section's leaf keys are copied to the top of options (mirroring the OptionsFlow-derived read) while the raw nested section is preserved for fidelity, and an existing top-level key is never overwritten.

Each entry carries:

  • log_level: the canonical Python logger level name (DEBUG/INFO/WARNING/ERROR/CRITICAL) when the integration has a logger.set_level override, or "DEFAULT" (uppercase sentinel) when no override is set.

  • log_level_raw: the original numeric level (e.g. 10 for DEBUG) when HA returned an int, None otherwise (no override set, or HA provided a level name as a string).

This is distinct from the add-on side, where ha_get_app returns Supervisor's lowercase "default" literal โ€” do not cross-compare.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMax entries to return per page in list mode (default: 50)
queryNoWhen listing, search by domain or title. Uses exact substring matching by default; set exact_match=False for fuzzy.
domainNoFilter by integration domain (e.g. 'template', 'group'). When set, includes the full options/configuration for each entry.
offsetNoNumber of entries to skip for pagination (default: 0)
entry_idNoConfig entry ID to get details for. If omitted, lists all integrations.
device_idNoOptional. When set with include_diagnostics=True, returns the device-scoped diagnostics dump for that specific device under the integration (rather than the full integration dump). Some integrations only expose config-entry-level dumps; others expose both.
exact_matchNoUse exact substring matching for query filter (default: True). Set to False for fuzzy matching when the query may contain typos.
subentry_idNoExisting subentry ID used with include_subentry_schema=True to inspect a reconfigure flow.
subentry_typeNoIntegration-defined subentry type used with include_subentry_schema=True.
include_schemaNoWhen entry_id is set, also return the options flow schema (available fields and their types). Use before ha_config_set_helper to understand what can be updated. Only applies when supports_options=true.
include_optionsNoInclude the options object for each entry. Automatically enabled when domain filter is set. For UI-created flow-based helpers (template, group, utility_meter, derivative, ...), the current config โ€” template body, group members, source entity, etc. โ€” is surfaced here by probing the options flow. Prefer this over include_schema when you only need to read the current values; use include_schema when you also need the field types or selector metadata.
diagnostics_fieldsNoOptional list of top-level keys to keep from the diagnostics data payload (e.g. ['home_assistant', 'issues']). Trims the payload before it hits the LLM context budget. Accepts a JSON list or comma-separated string. Only applies when include_diagnostics=True and the data payload is a dict. Unknown keys are silently dropped and surfaced via the omitted_fields sub-key.
include_subentriesNoWhen entry_id is set, include config subentries for the integration entry. Useful for integrations that expose conversation agents, devices, or other extension points as subentries.
include_diagnosticsNoWhen entry_id is set, also fetch the integration's diagnostics dump โ€” integration-defined JSON (commonly includes redacted config, device list, state snapshots; exact top-level keys vary by integration). The canonical artifact users grab via Settings โ†’ Devices & Services โ†’ [integration] โ†’ โ‹ฏ โ†’ Download diagnostics. Use when triaging integration bugs or filing ha_report_issue for a specific integration. Payloads can be large (Hue ~290 KB, ZHA/MQTT/ESPHome several MB) โ€” pair with diagnostics_fields or diagnostics_truncate_at_bytes to fit the LLM context budget.
include_knx_projectNoWhen entry_id is a KNX config entry, also return the parsed ETS project: the full group-address table (address, name, DPT, description) under knx_project.group_addresses, plus the group-range hierarchy and project metadata. This is the parsed-project GA table that is NOT in the diagnostics dump; per-entity GA assignments are already covered by include_diagnostics (config_store / configuration_yaml). Ignored (with a warning) when the entry is not a KNX integration. The KNX integration exposes a single project, so the result is the same regardless of which KNX entry_id is used.
diagnostics_data_pathNoOptional dotted path into the diagnostics data sub-tree (e.g. '<list-valued path>' for per-device records, 'home_assistant.version' for HA core version; the exact key path varies by integration version). Walks into the post-fields payload. Resolution failures replace data with null and surface data_path_error. Use this when the interesting payload lives several levels deep โ€” top-level diagnostics_fields can't address sub-trees on integrations where the bulk lives under one key (ZHA, MQTT, ESPHome). Only applies when include_diagnostics=True.
show_advanced_optionsNoWhen include_subentry_schema=True, ask older Home Assistant versions to expose advanced flow options. No-op on HA 2026.6+; pending removal before HA 2027.6.
diagnostics_data_limitNoPagination window size for list-valued diagnostics_data_path results. When set with a list-resolved path, swaps data for a pagination envelope {path, items, offset, limit, total, has_more}. Default None returns the full resolved value. Workflow: probe with a list-valued diagnostics_data_path and diagnostics_data_limit=10 to walk a large list one page at a time (the exact path varies by integration version). Only applies when include_diagnostics=True.
diagnostics_data_offsetNoPagination start index (default 0) for list-valued diagnostics_data_path results. Ignored when diagnostics_data_path is unset, diagnostics_data_limit is unset, or the resolved value is not a list. Only applies when include_diagnostics=True.
include_subentry_schemaNoWhen entry_id is set, return introspection-only config subentry schema information; no subentry is created. Pair with subentry_type, and optionally subentry_id for reconfigure schema.
diagnostics_truncate_at_bytesNoOptional byte cap on the serialized diagnostics payload (after diagnostics_fields and diagnostics_data_path have been applied). On hit, drops data and emits truncated=true, bytes_total, byte_cap, plus available_fields (when the capped value is a dict). Recommended starting point: 20000 bytes. Only applies when include_diagnostics=True.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and idempotentHint=true, but the description adds substantial behavioral detail: pagination semantics, secrets.yaml values returned as '**redacted**', nested option sections flattened additively, log_level sentinel behavior, diagnostics byte-truncation behavior, and KNX project parsing. No contradictions with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but well-structured with clear sections: overview, examples, states, options behavior, per-entry fields, and cross-tool distinction. The first sentence immediately states the core purpose. Every section earns its place given the tool's 21 parameters and complex diagnostic/schema-probing behavior.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with 21 optional parameters, an output schema, and annotations, the description is exceptionally complete. It covers all major modes (list, detail, schema, diagnostics, subentries, KNX project, pagination), includes edge cases like redacted secrets and log_level sentinel, and provides usage guidance that complements the structured schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3, but the description goes far beyond the schema by explaining real-world semantics: how include_options surfaces flow-based helper config, how diagnostics_data_path walks sub-trees, how diagnostics_fields trims payloads, and the distinction between include_schema and include_options. The extensive examples map parameter combinations to concrete use cases.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Get integration (config entry) information with pagination.' It clearly distinguishes the two primary modes (list all without entry_id vs. detailed single-entry lookup with entry_id) and includes concrete examples. This separates it cleanly from sibling tools like ha_get_app and ha_set_integration.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit when-to-use guidance, including 'Prefer include_options over include_schema when you only need to read the current values' and 'use include_schema when you also need the field types or selector metadata.' It also warns not to cross-compare ha_get_integration's log_level sentinel with ha_get_app's Supervisor literal, naming the alternative tool directly.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_get_logsGet LogsA
Read-onlyIdempotent

Get Home Assistant logs from various sources.

Sources:

  • "logbook" (default): Entity state change history with pagination

  • "system": Structured system log entries (errors, warnings) via system_log/list

  • "error_log": Raw log text (home-assistant.log on container/pip installs; HA Core's journald stream on Supervisor-backed installs)

  • "supervisor": App (add-on) container logs (requires slug = app slug)

  • "system_service": HA-Supervisor-managed system service logs (requires slug โˆˆ {supervisor, host, core, dns, audio, cli, multicast, observer})

  • "logger": Effective log level per integration via logger/log_info (confirms logger.set_level changes took effect)

Prefer source='system' for triage. It returns HA's own deduplicated system_log entries with counts, first_occurred and full tracebacks; of those only the tracebacks are unrecoverable from the structured error_log summary โ€” they are present in the raw text, so structured=False gets them back. Its counts also run since each error first occurred, while structured error_log counts only what is inside the fetched window (reported as window_start/window_end; every install now reads a capped window). Use error_log with structured=True for entries below system_log's WARNING+ ~50-entry cap, or for the per-component rollup.

Shared params: limit, search (keyword filter on entries/lines; matches integration domain for source='logger') Order: order='newest' (default) returns most-recent first; order='oldest' returns chronological-first. Applies to all time-ordered sources (logbook, system, error_log, supervisor, system_service); ignored for source='logger' and for error_log with structured=True. For raw-text sources (error_log, supervisor, system_service) it sets the read direction of the most-recent window. Logbook params: hours_back, entity_id, end_time, compact (default True โ€” strips attribute dicts to save context) Pagination (logbook + error_log): offset pages deeper; ignored for the other sources. Logbook responses carry has_more plus a pagination_hint. On error_log, offset counts raw log lines back from the newest entry (journald entries on Supervisor-backed installs), both modes read a bounded window per call โ€” so level/search filter and limit slice within that window only, and window_lines reports the size actually requested โ€” and the response carries has_more with a next_offset to pass back while it stays true. System/error_log params: level (ERROR, WARNING, INFO, DEBUG, CRITICAL) error_log params: structured, top_n. In structured mode search matches the message and logger name only, whereas on the raw path it matches the whole line; limit/order do not apply, issues are ranked by count, then severity, then recency, and the summary covers a fixed deep window rather than the caller's limit. Supervisor params: slug = app slug, e.g. "core_mosquitto" (use ha_get_app() to list installed slugs) System-service params: slug = service name. The slug "supervisor" here means the Supervisor service's own logs, NOT an app with that name โ€” the source param disambiguates.

ParametersJSON Schema
NameRequiredDescriptionDefault
slugNo
levelNo
limitNo
orderNoSort order for time-ordered sources (logbook, system, error_log, supervisor, system_service): 'newest' (default) returns most-recent first; 'oldest' returns chronological-first. Ignored for source='logger', and for source='error_log' with structured=True (that summary is ranked by occurrence count, not by time).newest
top_nNoMax distinct issues to return when structured=True (default 20, capped at 500). Bounds the response regardless of log size.
offsetNoPage deeper into source='logbook' and source='error_log' (ignored for other sources). On error_log it counts raw log lines back from the newest entry; pass the response's 'next_offset' to continue while 'has_more' is true.
searchNo
sourceNologbook
compactNo
end_timeNo
entity_idNo
hours_backNo
structuredNosource='error_log' only. When True, return a deduplicated, component-grouped summary of the log (counted issues sorted by frequency) instead of raw text. Use this on busy instances where the raw log is large enough to exhaust context. Ignored for other sources.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, openWorldHint=false, and idempotentHint=true, and the description adds substantial behavioral context beyond those: pagination semantics, bounded windows, per-source ordering behavior, structured-mode ranking, and what response fields like has_more and next_offset mean. It also exposes nuanced caveats like system_log counts running since first occurrence versus error_log's windowed counts. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long, but the structure is excellent: bold source headers, bulleted groups, and shared-parameter sections make it scannable. Some sentences are dense and could be trimmed, but for a 13-parameter, six-source tool the length is largely justified.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity, the description covers all essential operational concerns: source selection, default source, pagination, ordering, structured versus raw modes, slug requirements, and filtering. An output schema exists, so the description does not need to re-document return values. Nothing an agent needs to call or route this tool correctly appears missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 31%, so the description carries the burden, and it does so thoroughly. It explains shared params (limit, search), source-specific params (level, structured, top_n, slug), when order is ignored, how offset paginates for logbook versus error_log, and what compact strips. Every parameter is given semantic meaning beyond its bare schema type.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'Get Home Assistant logs from various sources,' then enumerates six distinct log sources with clear semantics. This differentiates ha_get_logs from sibling tools like ha_get_history and ha_get_system_health without ambiguity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit routing guidance, such as 'Prefer source="system" for triage' and when to use error_log with structured=True. It also names ha_get_app as the way to list installed slugs. It does not explicitly contrast this tool with ha_get_history, so it stops short of full alternative-exclusion guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_get_operation_statusGet Operation StatusA
Read-only

Get the status of one or more device operations with real-time WebSocket verification.

Pass a single operation_id string to check one operation, or a list of IDs to check multiple operations at once (bulk status).

The timeout_seconds wait window bounds both modes. Bulk checks poll all operations concurrently under one shared window and report per-item failures inside detailed_results instead of aborting the batch.

Use this to track operations initiated by ha_bulk_control or ha_call_service. For current entity states, use ha_get_state instead.

ParametersJSON Schema
NameRequiredDescriptionDefault
operation_idYesSingle operation ID or list of operation IDs to check. Use a single string for one operation, or a list for bulk status checks.
timeout_secondsNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, and the description adds substantial behavior beyond that: real-time WebSocket verification, concurrent polling of bulk operations under one shared timeout window, and per-item failures surfacing in detailed_results rather than aborting the batch. These are exactly the non-obvious behaviors an agent needs to know.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Compact and efficiently front-loaded: purpose in sentence one, usage modes in the next, timeout semantics, then routing guidance. Every sentence earns its place, and the structure mirrors how an agent would reason about the tool.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers both invocation modes, shared timeout behavior, bulk failure semantics, and the relationship to sibling tools. An output schema exists so return-value details needn't be spelled out, and nothing an agent needs to call this correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 50% โ€” operation_id is fully documented in the schema, but timeout_seconds has no schema description. The description compensates by explaining the timeout wait window bounds both modes and that bulk checks share one window, adding real meaning beyond the schema's default/minimum values.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb-resource statement โ€” 'Get the status of one or more device operations' โ€” and adds the distinguishing real-time WebSocket verification detail. It differentiates from siblings by explicitly pointing to ha_get_state for entity states, so an agent can select it correctly without inspecting other definitions.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit when-to-use guidance: 'Use this to track operations initiated by ha_bulk_control or ha_call_service,' and an explicit exclusion: 'For current entity states, use ha_get_state instead.' This is model usage guidance with named alternatives and conditions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_get_overviewGet System OverviewA
Read-onlyIdempotent

Get AI-friendly system overview with intelligent categorization.

Returns comprehensive system information at the requested detail level, including Home Assistant base_url, version, location, timezone, entity overview, and active persistent notifications (if any). Use 'minimal' (default) for most queries. Domain counts and states_summary are always complete regardless of entity pagination. Standard/full modes paginate entities (default 200 per page) โ€” use offset to fetch more. Use 'domains' filter to narrow scope.

Use fields= to project the response to only the keys you need โ€” a significantly smaller payload when fetching a single sub-section (e.g. fields=["system_info"] returns just that section instead of the full overview).

When (and only when) the ha-mcp settings-UI sidecar is running (stdio mode, e.g. Claude Desktop / Claude Code), the response includes a settings_url field โ€” the local URL to the tool-configuration page. Hand this URL to the user when they ask how to enable or disable tools or change server settings. settings_url is emitted regardless of fields= projection (so it stays discoverable even when callers minimize the response) but only when the sidecar URL file actually exists.

In standalone HTTP / Docker modes, when an HTTP settings prefix is advertised, there is no sidecar URL file and the server can't know its externally reachable host. The response instead carries a settings_url_hint string telling the user where the page is mounted and how to find or construct the full URL. Hand whichever of the two fields is present to the user.

The response also carries an ha_mcp_update object {current, latest, update_available} reporting whether a newer ha-mcp release is available (PyPI for pip/Docker, the Supervisor add-on store for the add-on) โ€” proactively tell the user when update_available is true. Emitted regardless of fields=; omitted only for the unknown version and when HA_MCP_DISABLE_UPDATE_CHECK is set.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMax total entities across all domains (default: unlimited for minimal, 200 for standard/full). Counts and states always complete. Use with offset for pagination.
fieldsNoReturn only the specified top-level response keys to reduce response size (e.g. ["system_info", "domains"]). None = full response (default). Available keys: success, system_summary, domain_stats, area_analysis, ai_insights, pagination, partial, warnings, device_types, service_availability, system_info, notification_count, notifications, repair_count, dismissed_repair_count, repairs, repairs_error, tool_discovery, settings_url, settings_url_hint, read_only_mode, read_only_mode_hint, ha_mcp_update. Note: ``settings_url`` (stdio mode), ``settings_url_hint`` (standalone HTTP/Docker mode), the ``read_only_mode`` / ``read_only_mode_hint`` pair (only while Read Only Mode is on), and ``ha_mcp_update`` (when an update check applies) are emitted regardless of ``fields=`` projection so the settings page, the active mode, and a newer ha-mcp release stay discoverable; see the tool description.
offsetNoNumber of entities to skip for pagination (default: 0)
domainsNoFilter to specific domains (e.g. 'light,sensor' or ['light','sensor']). None = all domains. Useful to avoid context window overload.
detail_levelNo'minimal': 10 entities/domain, top-5 states (default); 'standard': 200 entities/page, top-10 states (use offset for more); 'full': 200 entities/page + entity_id + state + full states. Use 'domains', 'limit', or max_entities_per_domain to control sizeminimal
include_stateNoInclude state field for entities (None = auto based on level). Full defaults to True.
include_entity_idNoInclude entity_id field for entities (None = auto based on level). Full defaults to True.
include_notificationsNoInclude active persistent notifications (default: True). Set False to skip.
max_entities_per_domainNoOverride default entity cap per domain (minimal=10, standard/full=unlimited). 0 = no limit on entities or states.
include_dismissed_repairsNoInclude user-dismissed/ignored repairs (default: False). Matches the HA Repairs UI which hides dismissed items by default. To dismiss/ignore a repair, call ha_call_service with ws_command="repairs/ignore_issue" and data={"domain": ..., "issue_id": ..., "ignore": true}.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses non-obvious behaviors beyond annotations: settings_url only appears when the sidecar is running and is emitted regardless of fields= projection; settings_url_hint appears in HTTP/Docker modes; ha_mcp_update is omitted under unknown version or HA_MCP_DISABLE_UPDATE_CHECK; counts/states_summary are complete regardless of pagination. This is rich, actionable behavioral context that annotations alone do not provide.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but every sentence adds unique information, and it is front-loaded with the core purpose and default behavior before edge cases. The structure is coherent (main purpose, pagination, fields projection, settings_url, update object). It slightly overexplains settings_url variants, but the added detail is operationally relevant for the agent.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool has 10 optional parameters, an output schema, and complex conditional behavior. The description covers mode-dependent fields, override behavior, user handoff instructions, and update-check logic. The output schema covers return values, so the description reasonably focuses on conditions and side effects. Nothing needed for correct invocation appears to be missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents every parameter. The description adds context for fields= and detail_level and mentions offset/domains, but most parameter semantics are already in the schema. Baseline 3 applies; the description doesn't need to compensate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Get'), a clear resource ('system overview'), and adds 'AI-friendly ... with intelligent categorization', which sets it apart from sibling getters like ha_get_system_health and ha_get_entity. It names the main contents (base_url, version, location, timezone, entity overview, notifications), so an agent can tell exactly what this tool returns.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit guidance is abundant: 'Use minimal (default) for most queries', 'Use fields= to project the response', 'Use domains filter to narrow scope', and 'Use with offset for pagination'. It also directs user-facing handling of settings_url and ha_mcp_update. This clearly tells the agent when and how to use the tool, including alternatives like pagination controls.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_get_skill_guideGet Home Assistant Best Practices Skill GuideA
Read-onlyIdempotent

Get bundled Home Assistant best-practice skill guides. No skill bundles are currently available on this server โ€” the skills directory is missing, empty, or all SKILL.md files failed to parse. Calls return an empty listing; ask the operator to verify the skills-vendor submodule is initialized.

Use BEFORE: creating or editing automations, scripts, scenes, helpers, or dashboards; writing triggers, conditions, actions, wait_template, or service calls; renaming entities or migrating device_id to entity_id; calling ha_config_set_automation, ha_config_set_script, ha_config_set_helper, ha_config_set_dashboard, or ha_set_entity.

Replaces (and supersedes) the prior tools: ha_list_resources, ha_read_resource, and ha_get_skill_home_assistant_best_practices. If you were going to call any of those, call this instead.

best practices skill skills guide guides reference references documentation docs help tutorial automation script scene helper dashboard ha_list_resources ha_read_resource list_resources read_resource ha_get_skill_home_assistant_best_practices ha_get_skill_home_assistant home_assistant_best_practices

ParametersJSON Schema
NameRequiredDescriptionDefault
fileNoReference file path within the skill, relative to the skill directory (e.g., 'SKILL.md' or 'references/automation-patterns.md'). Requires skill to be set.
skillNoSkill name from the no-args listing (e.g., 'home-assistant-best-practices').

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=true and idempotentHint=true. The description adds behavioral context: 'No skill bundles are currently available... Calls return an empty listing; ask the operator to verify the skills-vendor submodule is initialized.' This provides transparency about current state and failure modes beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is relatively long but well-structured: a brief purpose, status note, usage guidance, and replacement info. Every sentence serves a purpose, though it could be slightly more compact. Still concise for the amount of useful information provided.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's simplicity (2 optional parameters, no enums, output schema present), the description covers all necessary context: current state, usage timing, replacement info, and parameter hints. It is complete for an agent to decide when and how to use it.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents both parameters. The description does not add significant meaning beyond what is in the schema (e.g., 'Skill name from the no-args listing' is already in schema). Baseline of 3 is appropriate as schema carries the burden.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Get bundled Home Assistant best-practice skill guides.' It specifies the resource (skill guides) and action (get), and distinguishes from siblings by focusing on skill guides, not other config entities. It also notes the current unavailability, which sets expectations.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states when to use: 'Use BEFORE: creating or editing automations, scripts, scenes, helpers, or dashboards; ...' and lists specific tool calls. It also clarifies that it supersedes earlier tools (ha_list_resources, etc.), providing clear alternatives and exclusion guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_get_stateGet Entity StateA
Read-onlyIdempotent

Get current status, state, and attributes of one or more entities (lights, switches, sensors, climate, covers, locks, fans, etc.).

SINGLE ENTITY: Pass a string entity_id. Returns the entity's full state and attributes.

MULTIPLE ENTITIES: Pass a list of entity IDs (max 100). Efficiently retrieves states using parallel requests. Duplicates are automatically deduplicated. Returns success=True if at least one entity state was retrieved. Check 'error_count' for any failed lookups in partial-success scenarios.

FIELDS PROJECTION: fields= projects the per-entity record keys (see the fields= parameter description for the full key list), NOT the outer bulk response wrapper. In single-entity mode it filters keys of the returned record directly. In bulk mode it filters keys of each record inside states[entity_id]; outer keys (success, count, states, errors, ...) are always preserved. attribute_keys= further narrows the attributes sub-dict and is only applied when "attributes" is in fields= (or fields=None); otherwise it is a no-op.

When attribute_keys= is set but has no effect (because attributes was excluded by fields=), a warnings list is emitted outside the projected entity record(s): in bulk mode at the response wrapper level (sibling of success/count/states); in single-entity mode at the top-level result (sibling of data/metadata, since the projected record IS data). The warnings list is never a record key, so fields=["state"] returns a record with only state regardless of whether the no-effect warning fires.

EXAMPLES:

  • Single: ha_get_state("light.kitchen")

  • Multiple: ha_get_state(["light.kitchen", "light.living_room", "sensor.temperature"])

  • State only: ha_get_state("light.kitchen", fields=["state"])

  • Slim bulk: ha_get_state(["light.kitchen", "sensor.temperature"], fields=["state", "attributes"], attribute_keys=["brightness"])

get current state value single entity check status bulk multiple states

ParametersJSON Schema
NameRequiredDescriptionDefault
fieldsNoReturn only the specified top-level entity record keys to reduce response size (e.g. ["state", "attributes"]). None = full entity record (default). Available keys: entity_id, state, attributes, last_changed, last_reported, last_updated, context.
entity_idYesEntity ID or list of entity IDs to retrieve state for (e.g., 'light.kitchen' or ['light.kitchen', 'sensor.temperature'])
attribute_keysNoReturn only the specified keys from each entity's attributes dict (e.g. ["brightness", "color_temp_kelvin"] for lights). None = full attributes (default). Unknown keys are silently dropped. Requires "attributes" to be present in fields= (or fields=None).

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and idempotentHint. The description adds significant behavioral context: bulk mode with parallel requests, deduplication, partial-success handling, fields projection behavior, and warnings for attribute_keys no-effect. No contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with sections and examples, but slightly verbose. It front-loads the core purpose and uses clear formatting, earning its length.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers all modes, edge cases (partial success, no-effect warnings), and provides examples. With an output schema existing, return values are covered. Complete for a complex tool with 3 parameters.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, and the description adds meaning beyond the schema by explaining fields projection behavior in detail, attribute_keys dependency, and warnings. It clarifies the interaction between parameters.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Get current status, state, and attributes of one or more entities'. It specifies the verb 'Get' and the resource 'state of entities', and distinguishes it from siblings by being a read-only state retrieval tool, unlike other tools like ha_get_entity or ha_get_history.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides detailed guidance on single vs multiple entities, fields projection, and attribute_keys, with examples. It does not explicitly mention when not to use or alternatives, but the context is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_get_system_healthGet System Health (incl. ZHA/Z-Wave/integration diagnostics)A
Read-onlyIdempotent

Get Home Assistant system health, including Zigbee (ZHA), Z-Wave JS, and per-integration diagnostics dumps.

Returns health check results from integrations, system resources, and connectivity. Available information varies by installation type and loaded integrations.

The result also carries an ha_mcp_update object โ€” {current, latest, update_available} โ€” reporting whether a newer ha-mcp release is available (from PyPI for pip/Docker, or the Supervisor add-on store for the add-on), so you can proactively tell the user to upgrade. Present on every install type including the HA add-on (so a user who missed the Supervisor's update prompt still hears about it); omitted only for the unknown version and when HA_MCP_DISABLE_UPDATE_CHECK is set.

Parameters:

  • include: Optional comma-separated list of additional data to include.

    • "repairs": Repair items from Settings > System > Repairs (active only by default; pass include_dismissed_repairs=True for all). To dismiss/ignore a repair, call ha_call_service(ws_command="repairs/ignore_issue", data={"domain": <domain>, "issue_id": <issue_id>, "ignore": true}).

    • "zha_network": ZHA Zigbee devices with radio signal summary (name, LQI, RSSI)

    • "zha_network_full": ZHA Zigbee devices with all device details (can be large on 100+ device networks; prefer "zha_network" for summary)

    • "zwave_network": Z-Wave JS network status and node summary (status, security, routing)

    • "thread_network": Thread/OpenThread Border Router (OTBR) summary โ€” per border-router channel, extended_pan_id, and border_agent_id (integration-presence + radio-network view, not per-node Thread health)

    • "matter_network": Matter integration presence summary โ€” config_entry_id, state, and title (per-node health is exposed separately via Matter node diagnostics, not here)

    • "themes": Installed theme names and defaults (sorted list of theme names, count, default_theme, default_dark_theme)

    • "diagnostics": Per-integration diagnostics dump โ€” integration-defined JSON (commonly includes redacted config, device list, state snapshots; exact top-level keys vary by integration). REQUIRES config_entry_id. The canonical artifact users grab via Settings โ†’ Devices & Services โ†’ [integration] โ†’ โ‹ฏ โ†’ Download diagnostics. Use this when triaging integration bugs or filing ha_report_issue for a specific integration. Payloads can be large (Hue ~290 KB, ZHA/MQTT/ESPHome several MB) โ€” pair with diagnostics_fields or diagnostics_truncate_at_bytes to fit the LLM context budget.

    • "config_check": Validate HA configuration via POST /config/core/check_config (the pre-restart safety check; ha_restart runs it automatically). Returns {result: valid|invalid, is_valid, errors}; read-only/idempotent, takes no args.

    • "dead_entities": Surface orphaned/stale entity-registry entries by diffing the registry against the state machine and the live config-entries set. Returns confidence-tiered buckets โ€” config_entry_orphans (owning integration instance gone; definitively dead) and stale_restored (HA restored the entity from the registry on startup but the loaded integration no longer provides it). Each item carries entity_id + platform so a client can propose cleanup with ha_remove_entity. Deliberately excludes unknown-state entities and merely-offline devices to keep false positives low. Read-only; takes no args.

    • Example: include="repairs,zha_network,zwave_network,config_check"

    • Example: include="diagnostics", config_entry_id="abc123..."

  • include_dismissed_repairs: Include user-dismissed/ignored repairs (default: False). Only meaningful when "repairs" is in include.

  • config_entry_id: Required when include contains diagnostics. The config entry ID of the integration (find via ha_get_integration).

  • device_id: Optional. When set with include=diagnostics, returns the device-scoped diagnostics dump for that specific device under the integration (rather than the full integration dump). Some integrations only expose config-entry-level dumps; others expose both.

  • diagnostics_fields: Optional list of top-level keys to keep from the diagnostics data payload (e.g. ["home_assistant", "issues"]). Accepts a JSON list or comma-separated string. Only applies with include=diagnostics.

  • diagnostics_truncate_at_bytes: Optional byte cap on the serialized diagnostics payload (post-projection / post-data_path). On hit, drops data and emits truncated=true, bytes_total, byte_cap, plus available_fields (when the capped value is a dict). Only applies when include contains diagnostics. Recommended starting point: 20000 bytes.

  • diagnostics_data_path: Optional dotted path into the diagnostics data sub-tree (e.g. "data.devices" for ZHA per-device records). Walks into the post-fields payload. Resolution failures replace data with null and surface data_path_error. Only applies when include contains diagnostics.

  • diagnostics_data_offset / diagnostics_data_limit: Pagination on list-valued diagnostics_data_path results. When data_limit is set and the resolved path is a list, data becomes {"path", "items", "offset", "limit", "total", "has_more"}. Only applies when include contains diagnostics.

    Example workflow (walk a list-valued sub-tree one page at a time; the exact data_path varies by integration version): ha_get_system_health(include="diagnostics", config_entry_id="abc", diagnostics_data_path="<list-valued path>", diagnostics_data_limit=10) โ†’ inspect the page envelope's total / has_more โ†’ repeat with diagnostics_data_offset=10 for the next slice.

ParametersJSON Schema
NameRequiredDescriptionDefault
includeNo
device_idNo
config_entry_idNo
diagnostics_fieldsNo
diagnostics_data_pathNo
diagnostics_data_limitNo
diagnostics_data_offsetNo
include_dismissed_repairsNo
diagnostics_truncate_at_bytesNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already indicate readOnlyHint, openWorldHint, and idempotentHint=true. The description adds significant behavioral context, including the return of the ha_mcp_update object, caveats about payload sizes for diagnostics, and that operations like config_check are read-only and idempotent. No contradictions with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is lengthy due to the tool's complexity, but it is well-structured with a clear lead sentence, a separate paragraph for the ha_mcp_update object, and bullet-point-like explanations for include options. While every sentence earns its place, some redundancy exists (e.g., repeating 'Only applies when include contains diagnostics'). Minor trimming could improve conciseness.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (9 parameters, no schema coverage, no enums), the description is exceptionally complete. It covers all parameters, explains return values (including the ha_mcp_update object), provides workflow examples, and addresses edge cases (e.g., omission when version is unknown or HA_MCP_DISABLE_UPDATE_CHECK set). The presence of an output schema does not reduce the need for this detail, and the description delivers.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema coverage, the description fully explains all 9 parameters. It lists every possible value for include, describes the behavior of each parameter (e.g., diagnostics_data_path, diagnostics_truncate_at_bytes), provides examples, and clarifies dependencies (e.g., config_entry_id required for diagnostics). This exceeds the minimum required and compensates for the lack of schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Get Home Assistant system health, including Zigbee (ZHA), Z-Wave JS, and per-integration diagnostics dumps.' It specifies the resource (system health) and the specific integrations covered, effectively distinguishing it from sibling tools that focus on individual integrations or other aspects.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit usage guidance for specific include options, such as 'Use this when triaging integration bugs or filing ha_report_issue for a specific integration' for diagnostics. It also hints at appropriate contexts for other options like dead_entities. However, it lacks a general statement on when to use this tool versus alternatives, which would improve clarity.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_get_todoGet TodoA
Read-onlyIdempotent

Get todo lists or items - list all todo lists or get items from a specific list.

Without an entity_id: Lists all todo list entities in Home Assistant. With an entity_id: Gets items from that specific todo list, optionally filtered by status.

LISTING TODO LISTS (entity_id omitted): Returns all entities in the 'todo' domain, including shopping lists and any other todo-type integrations.

Each todo list includes:

  • entity_id: The unique identifier (e.g., 'todo.shopping_list')

  • friendly_name: Human-readable name

  • state: Number of incomplete items or current status

GETTING TODO ITEMS (entity_id provided): Retrieves items from the specified todo list.

Status filter values:

  • needs_action: Items that still need to be done

  • completed: Items that have been marked as done

  • None (default): Returns all items regardless of status

Item properties:

  • uid: Unique identifier for the item

  • summary: The item text/description

  • status: Current status (needs_action or completed)

  • description: Optional detailed description

  • due: Optional due date (if supported)

EXAMPLES:

  • List all todo lists: ha_get_todo()

  • Get all items: ha_get_todo("todo.shopping_list")

  • Get incomplete items: ha_get_todo("todo.shopping_list", status="needs_action")

  • Get completed items: ha_get_todo("todo.shopping_list", status="completed")

USE CASES:

  • "What todo lists do I have?"

  • "Show me my shopping list"

  • "What's on my todo list?"

  • "Show completed items"

ParametersJSON Schema
NameRequiredDescriptionDefault
statusNoFilter items by status: 'needs_action' for incomplete, 'completed' for done. Only applies when entity_id is provided.
entity_idNoTodo list entity ID (e.g., 'todo.shopping_list'). If omitted, lists all todo list entities.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already provide readOnlyHint=true and idempotentHint=true. The description adds behavioral details: the two modes, return structures (entity_id, friendly_name, state for lists; uid, summary, status, description, due for items), and how the status filter works. No contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with headings, bullet points, and examples. It is front-loaded with a clear summary. While somewhat lengthy, every section adds value, and the structure aids readability.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool complexity (two modes) and high schema coverage, the description covers the tool's behavior, return structure, and common use cases. It does not rely on an output schema (though one exists) but explains return values explicitly. No critical gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description adds value by explaining the effect of each parameter (e.g., 'entity_id' lists all lists when omitted, 'status' filter values with defaults) and provides examples that clarify usage beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool gets todo lists or items, with two distinct modes: listing all lists (no entity_id) and getting items from a specific list (with entity_id). It is specific, uses a verb+resource structure, and distinguishes from sibling tools like ha_remove_todo_item or ha_set_todo_item.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly explains when to omit vs. provide entity_id, and optionally filter by status. It includes examples and use cases. It does not explicitly mention when not to use this tool vs. mutation siblings, but annotations (readOnlyHint=true) and the read-only nature make it clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_get_zoneGet ZoneA
Read-onlyIdempotent

Get zone information - list all zones or get details for a specific one.

Without a zone_id: Lists all Home Assistant zones with their coordinates and radius. With a zone_id: Returns detailed configuration for a specific zone.

ZONE PROPERTIES:

  • ID, name, icon

  • Latitude, longitude, radius

  • Passive mode setting

EXAMPLES:

  • List all zones: ha_get_zone()

  • Get specific zone: ha_get_zone(zone_id="abc123")

NOTE: With the ha_mcp_tools custom component installed, YAML-defined zones โ€” including the auto-synthesized 'home' zone โ€” are included and marked editable=false / source="yaml" (storage zones created via UI/API are source="storage"). Without the component, only storage zones are listed and YAML-defined zones such as 'home' will not appear.

ParametersJSON Schema
NameRequiredDescriptionDefault
zone_idNoZone ID to get details for (from ha_get_zone() list). If omitted, lists all zones.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark the tool as readOnlyHint=true and idempotentHint=true. The description adds valuable context beyond that, such as listing zone properties, the behavior difference between with/without zone_id, and a detailed note about YAML-defined vs storage zones depending on component installation. No contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured: clear main statement, bulleted list of properties, examples, and a note. Every sentence serves a purpose without redundancy. It is concise yet comprehensive.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the presence of an output schema, the description does not need to detail return values. It covers input behavior, properties, and special considerations. For a read-only tool with one optional parameter, this is complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% for the single parameter. The description reinforces the parameter's role: 'Zone ID to get details for... If omitted, lists all zones.' This adds clarity beyond the schema's description, and examples illustrate usage. A score of 4 reflects the added value while acknowledging the schema already does heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Get zone information - list all zones or get details for a specific one.' It distinguishes two modes based on the presence of a zone_id, and the title 'Get Zone' directly maps to reading operations, differentiating it from siblings like ha_remove_zone or ha_set_zone.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly explains when to use each mode: 'Without a zone_id: Lists all Home Assistant zones... With a zone_id: Returns detailed configuration for a specific zone.' It also provides examples. However, it does not explicitly mention when not to use this tool or suggest alternatives among siblings, which would improve the score.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_import_blueprintImport BlueprintA
Destructive

Import a blueprint from a URL.

Imports a blueprint from GitHub, Home Assistant Community forums, or any direct URL to a blueprint YAML file. Set overwrite=true to re-import a blueprint that is already installed (equivalent to the UI's "Re-import blueprint" action) - Home Assistant then reloads all automations/scripts that use it.

EXAMPLES:

SUPPORTED SOURCES:

  • GitHub repository URLs (will be converted to raw URLs)

  • Home Assistant Community forum posts with blueprint code

  • Direct URLs to YAML blueprint files

RETURNS:

  • Import result with the blueprint path where it was saved

  • Blueprint metadata (name, domain, description)

  • overrides_existing: true when an installed blueprint was overwritten

  • Error details if import fails

ParametersJSON Schema
NameRequiredDescriptionDefault
urlYesURL to import blueprint from (GitHub, Home Assistant Community, or direct YAML URL)
overwriteNoOverwrite the blueprint if it is already installed (re-import). Home Assistant reloads all automations/scripts using the blueprint.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations include openWorldHint and destructiveHint, and the description adds valuable context: overwrite=true triggers reload of automations/scripts, conversion of URLs to raw, and return of error details. No contradiction. The description supplements the annotations effectively.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with clear sections (overview, examples, supported sources, returns). Every sentence serves a purpose, and the length is appropriate for the tool's complexity. No extraneous text.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the existence of an output schema, the description still explains return values (import result, metadata, overrides_existing, error details). It covers input, behavior, output, and examples comprehensively for a moderately complex tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Input schema covers 100% of parameters with descriptions. The description adds examples of URL formats, explains the overwrite flag's effect, and lists supported sources. Despite high schema coverage, the description provides substantial additional meaning beyond the schema itself.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Import a blueprint from a URL', specifying the verb (import), resource (blueprint), and source (URL). It distinguishes from sibling tools like ha_get_blueprint (which retrievs existing blueprints) and ha_manage_hacs. No tautology; the purpose is unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains when to use the tool (importing blueprints from various sources) and provides examples and supported sources. It also describes the overwrite behavior and re-import action. However, it lacks explicit when-not scenarios or direct comparisons to alternatives, which would earn a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_list_floors_areasList Floors and AreasA
Read-onlyIdempotent

List floors sorted by level ascending, each with their assigned areas nested, plus areas without a floor.

Use for location-based reasoning where floor-to-area relationships matter, such as "which rooms are on the ground floor" or operations scoped to a level. Optionally project the response with fields= (top-level keys) or area_fields= (per-area-record keys, applied uniformly across nested, unassigned, and orphaned buckets).

Floors with level=None sort alongside level 0 (ground floor). Areas without a floor assignment appear in unassigned_areas; areas whose floor_id points to a non-existent floor appear in orphaned_areas. When the ha_mcp_tools component's registries capability is available, both registries come from a single in-process snapshot, so this classification is always consistent. Without it (legacy path), the two registries are fetched via independent WebSocket calls and a registry change between reads may transiently misclassify an area.

ParametersJSON Schema
NameRequiredDescriptionDefault
fieldsNoReturn only the specified top-level response keys to reduce response size (e.g. ["floors"]). None = full response (default). Available keys: success, floor_count, area_count, unassigned_count, orphaned_count, floors, unassigned_areas, orphaned_areas, message.
area_fieldsNoProject each area record (in floors[].areas, unassigned_areas, and orphaned_areas) to only the specified keys. E.g. ["area_id", "name"] returns slim area records. None = full records (default). Unknown keys yield empty records. Available keys: area_id, name, icon, floor_id, aliases, picture, labels.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and idempotentHint=true. The description goes far beyond by detailing sorting order, handling of level=None, unassigned and orphaned areas, consistency guarantees with registries, and a legacy path caveat. This provides extensive behavioral context that annotations alone do not cover.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured and front-loaded with the core purpose. It is somewhat lengthy (5 sentences plus a paragraph on consistency), but each part contributes necessary behavioral detail. Could be slightly more concise, but it remains clear and informative.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity (floors, nested areas, unassigned, orphaned) and the presence of an output schema, the description covers all essential aspects: sorting, level handling, edge cases (None floors, orphaned areas), consistency guarantees, and response projection. No gaps are apparent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% with detailed descriptions for both parameters. The description adds value by explaining how to project responses with fields= and area_fields=, giving examples (e.g., ['area_id', 'name']), and listing available keys. It enhances understanding beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description explicitly states 'List floors sorted by level ascending, each with their assigned areas nested, plus areas without a floor.' It uses a specific verb ('list') and resource ('floors and areas'), and the unique scope (nested areas, unassigned, orphaned) clearly distinguishes it from sibling tools that handle individual entities or different domain objects.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit usage context: 'Use for location-based reasoning where floor-to-area relationships matter, such as 'which rooms are on the ground floor' or operations scoped to a level.' It gives concrete use cases but does not explicitly state when not to use it or offer alternatives, though the sibling tool list implies other tools for other purposes.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_list_servicesList Available ServicesA
Read-onlyIdempotent

List available Home Assistant services with optional pagination and detail control.

Discovers services/actions that can be called via ha_call_service. Use domain or query filters to narrow results. Defaults to summary mode (name + description only) to keep responses compact.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMax services to return per page (default: 50)
queryNoSearch in service names and descriptions.
domainNoFilter by domain (e.g., 'light', 'switch', 'climate').
fieldsNoReturn only the specified top-level response keys to reduce response size (e.g. ["services"]). None = full response (default). Available keys: success, domains, services, total_count, count, offset, limit, has_more, next_offset, detail_level, filters_applied.
offsetNoNumber of services to skip for pagination (default: 0)
detail_levelNo'summary': service name + description only (default). 'full': include parameter field schemas.summary
service_fieldsNoProject each service record to only the specified keys. E.g. ["name", "description"] returns slim service records. None = full records (default). Unknown keys yield empty records. Available keys: name, description, domain, service, fields (full mode only), target (full mode only).

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations provide readOnlyHint and idempotentHint, so the safety profile is clear. The description adds context about pagination, response control, and the relationship to ha_call_service, which goes beyond the annotations without contradicting them.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is three sentences with no fluff. The first sentence defines action and options, the second links to another tool, and the third gives usage defaultsโ€”efficient and front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (7 parameters, pagination, filtering, and an output schema), the description covers all essential aspects: what the tool does, how to narrow results, detail control, and its role in the service call workflow. No important context is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description summarizes key parameters (domain and query filters, detail level) but doesn't add significant new meaning beyond what the schema already provides for each parameter.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool lists available Home Assistant services with optional pagination and detail control. It distinguishes itself from sibling tools like ha_call_service by noting that it discovers services that can be called, making the purpose unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description advises using domain or query filters to narrow results and defaults to summary mode for compact responses. It implicitly guides usage before calling services but does not explicitly state when not to use it or list alternatives, though no direct alternative exists among siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_manage_appManage App (add-on)A
Destructive

Manage Home Assistant apps (add-ons) or proxy an app API.

For app inventory, status, and Supervisor metadata, call ha_get_app first; use proxy mode here for documented app-specific read APIs. Do not infer private app API schemas; consult version-matched app docs, and use ha_get_skill_guide for complex Home Assistant workflows.

Use exactly one mode: lifecycle/store action, configuration fields, path proxy, or path with array_patch.

Requires Home Assistant OS or Supervised. options merges top-level keys and one nested mapping level; supply complete values for deeper nested mappings because they are replaced. A non-empty network replaces the full port override map. Prefer Ingress: direct-port access requires a shared container network and may require weakening the target app authentication. If a Supervisor lifecycle, configuration, or repository write has an unknown outcome, verify durable state with ha_get_app before retrying. That cannot prove whether restart or rebuild ran; inspect Supervisor jobs and logs and do not automatically replay them. For a proxy or array-patch write, query the target app's own read API before retrying.

manage app apps addon add-on configure settings options port network boot watchdog auto_update supervisor ingress proxy websocket api rest esphome nodered node-red frigate mosquitto mqtt zigbee2mqtt zigbee z-wave zwave appdaemon hacs studio code server file editor terminal ssh samba grafana influxdb deconz motioneye compile validate upload deploy firmware ota flash yaml device logs flows events stats

ParametersJSON Schema
NameRequiredDescriptionDefault
bodyNoProxy mode only. Request body for POST/PUT/PATCH โ€” or, with websocket=True, the initial WebSocket message. Pass a JSON object or JSON string.
bootNoConfig mode: Boot strategy โ€” 'auto' (start with HA) or 'manual'.
pathNoProxy mode: API path relative to the app (add-on) root (e.g., '/flows', '/api/events', '/api/stats'). Required for proxy mode; mutually exclusive with config parameters.
portNoProxy mode only. Connect to this port instead of the Ingress port. Use ha_get_app(slug='...') to find available ports. Some apps, including Node-RED, reject direct access unless their leave_front_door_open option is enabled and the app is restarted; related errors include an actionable, security-qualified ha_manage_app options command.
slugNoApp (add-on) slug (e.g., '<prefix>_nodered', '<prefix>_frigate'). Slug prefixes vary by app repository โ€” call ha_get_app() to discover the actual installed slug. Required for every mode except the store-repository actions (action='add_repository'/'remove_repository'), which use 'repository' instead and take no slug.
debugNoProxy mode only. Include diagnostic info (request URL, headers sent, response headers). Default: false.
limitNoProxy mode only. HTTP: return at most this many items from a JSON array response.
actionNoLifecycle mode: run a Supervisor app (add-on) action. One of 'install', 'uninstall', 'start', 'stop', 'restart', 'rebuild', 'update'. 'install'/'update' require the app's repository to be registered (it appears in ha_get_app(source='available')). Store-repository mode: 'add_repository' / 'remove_repository' register or unregister a custom app store repository โ€” these use the 'repository' param instead of 'slug'. When ha-mcp runs as an app, it can update other apps but cannot update its own running slug; update ha-mcp from the Home Assistant Apps UI. Mutually exclusive with path / config parameters / array_patch. HA OS / Supervised only.
methodNoProxy mode only. HTTP method: GET, POST, PUT, DELETE, PATCH. Defaults to GET.GET
offsetNoProxy mode only. HTTP: skip this many items in a JSON array response. Default: 0.
networkNoConfig mode: Complete desired host-port override map (e.g., {'5800/tcp': 8081}). A non-empty map replaces current overrides, so omitted entries are cleared. Omit 'network' to leave mappings unchanged. An empty map is ignored and does not by itself select config mode.
optionsNoConfig mode: App (add-on) configuration values (the 'Configuration' tab in the UI).
watchdogNoConfig mode: Enable or disable Supervisor watchdog (auto-restart on crash).
summarizeNoProxy mode only. WebSocket: when True (default), collapse runs of non-signal messages (typically YAML config dumps) into short elision markers. Set to False to return the raw stream.
websocketNoProxy mode only. Use WebSocket instead of HTTP for an app (add-on) WebSocket API. Sends 'body' as the initial message and collects responses; command names and body schemas are app/version-specific. Default: false.
repositoryNoStore-repository mode only (action='add_repository' or 'remove_repository'). For add_repository: the repository URL (e.g., 'https://github.com/balloob/home-assistant-addons'). For remove_repository: the repository slug (e.g., '0f1cc410', as shown in ha_get_app(source='available')). Required for those actions; rejected otherwise.
array_patchNoArray-patch mode: atomically GET a JSON array endpoint, apply ordered ops, then POST the mutated array back. Requires 'path'; mutually exclusive with body / websocket / offset / limit and config params. Use ha_get_skill_guide for operation shapes.
auto_updateNoConfig mode: Enable or disable automatic updates for this app (add-on).
message_limitNoProxy mode only. WebSocket: cap on messages collected from the wire, bounded by an internal safety ceiling. None = collect up to the ceiling. Lower to save tokens on noisy streams (e.g., message_limit=50 for a quick health check).
message_offsetNoProxy mode only. WebSocket: drop this many messages from the start of the collected list before returning. Useful for paginating past known-noisy headers. Default: 0.
wait_for_closeNoProxy mode only. WebSocket: True waits for the server to close a run-to-completion stream. False returns after the first response batch; use for one-shot command/response or bounded capture on a channel that stays open. Default: true.
request_headersNoProxy/array-patch mode: extra HTTP headers for the app (add-on) API. Useful for app-specific requirements such as Node-RED's `Node-RED-Deployment-Type: full`. Ingress routing headers override caller values on Ingress routes; direct-port calls have no internal routing headers. `Content-Type` is derived from the body when supplied. Not valid in config or websocket mode.
python_transformNoProxy mode only. Sandboxed Python expression that post-processes the response. Variable `response` is exposed โ€” a list[dict | str] for WebSocket (parsed JSON or raw text), or dict/list/str for HTTP (parsed body). Supports in-place mutation (response.append(...)) or reassignment (response = [...]). Example: response = [m for m in response if 'ERROR' in str(m)]. Post-processing only โ€” does not provide optimistic-locking write semantics.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already signal destructive and non-idempotent behavior, and the description adds substantial behavioral context: options merge only shallowly, network replaces the full port map, unknown write outcomes should be verified with ha_get_app, restart/rebuild cannot be proven and should not be automatically replayed, and direct-port access may require weakening authentication. This goes well beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The prose is front-loaded with purpose and mode selection, and the length is justified by the tool's 23-parameter complexity. The only deduction is for the trailing keyword list ('manage app apps addon add-on ...'), which adds bulk without aiding an agent's selection or invocation decision.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool this complex, the description covers all major operational concerns: mode selection, prerequisites, discovery via ha_get_app, schema uncertainty, destructive-write verification, and fallback to ha_get_skill_guide. An output schema exists, so the absence of return-value detail is not a gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, but the description adds critical cross-parameter semantics: mode exclusivity, the difference between slug and repository, the shallow-merge behavior of options, the full-replacement behavior of network, and the array_patch GET-then-POST flow. These insights are not inferable from the parameter descriptions alone.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Manage Home Assistant apps (add-ons) or proxy an app API.' It clearly differentiates from the sibling ha_get_app by assigning inventory, status, and metadata reads to that tool, while this tool covers lifecycle, configuration, proxy, and store actions.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit when-to-use guidance: call ha_get_app first for inventory/status, use proxy mode only for documented app-specific read APIs, do not infer private schemas, and consult ha_get_skill_guide for complex workflows. It also names exclusions and prerequisites such as 'Requires Home Assistant OS or Supervised' and the 'exactly one mode' rule.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_manage_backupManage BackupsA
Destructive

Manage Home Assistant backups โ€” both full HA snapshots AND per-edit auto-backups.

Pick the scope first, then the action. Wrong scope routes through the wrong code path:

scope

action

What it does

snapshot

create

Create a full HA tarball (config + addons, no DB by default). Can take a while on a large instance; progress heartbeats are sent while waiting.

snapshot

list

List full HA tarball snapshots (id, name, date, size). Read-only โ€” use to discover a backup_id or confirm a backup landed.

snapshot

restore

Restore a full HA tarball. Restarts HA. Last-resort recovery.

snapshot

delete

Delete one full HA tarball by backup_id (confirm=True required). Disabled by default (enable_snapshot_delete setting) and layered with guards even when enabled โ€” see below.

edits

create

On-demand snapshot of one entity (domain + entity_id required). Use before the user manually edits in the HA UI. Same handler path the decorator takes on writes; bypasses the enable_auto_backup toggle.

edits

list

List per-entity auto-backups (lightweight). Filter by domain and/or entity_id.

edits

view

Read one auto-backup file by name; returns YAML and parsed config.

edits

diff

Compare one auto-backup against the entity's current config. RFC 6902 JSON-Patch + add/remove/replace counts; bounded output. Read-only โ€” fetches the live config, makes no changes.

edits

restore

Re-apply one auto-backup. Creates a fresh safety snapshot first. No HA restart.

edits

delete

Delete one auto-backup by backup_name, or bulk-delete by filter.

When to use which scope:

  • Use scope="edits" to undo a recent automation/script/scene/dashboard/helper edit by the agent. Lightweight, fast, no restart.

  • Use scope="snapshot" only for system-wide recovery (botched add-on update, mass config corruption, etc.).

scope="snapshot" backup-hint: Run before operations that CANNOT be undone (e.g., deleting devices). If the current definition was fetched or can be fetched, this tool is usually not needed.

(snapshot, delete) is off by default and layered even when enabled: a human must set enable_snapshot_delete=true (env var, web settings UI, or add-on Supervisor options) โ€” an agent cannot turn this on itself. When enabled, a delete call is still refused if: the target is a scheduled/automatic backup; it's younger than snapshot_delete_min_age_days (default 7, 0 disables the floor); or it's the single newest snapshot remaining. These guarantee at least one recovery point always survives an agent's own mistakes.

enable_auto_backup and scope="edits": the automatic-on-write capture (every wrapped tool call) is gated by enable_auto_backup=true โ€” if the listing is empty, check the toggle (web settings UI or ENABLE_AUTO_BACKUP=true env var). The explicit (edits, create) action bypasses the toggle since the request is explicit; list / view / restore / delete operate on whatever's already on disk regardless of the toggle's current state.

Examples:

  • Snapshot before risky op: ha_manage_backup(scope="snapshot", action="create", name="Before_Big_Change")

  • List snapshots (to discover a backup_id or confirm one landed): ha_manage_backup(scope="snapshot", action="list")

  • Restore full snapshot: ha_manage_backup(scope="snapshot", action="restore", backup_id="dd7550ed")

  • Delete an old snapshot (requires enable_snapshot_delete=true): ha_manage_backup(scope="snapshot", action="delete", backup_id="dd7550ed", confirm=True)

  • On-demand entity snapshot before a manual UI edit: ha_manage_backup(scope="edits", action="create", domain="helper_input_boolean", entity_id="kitchen_lights_active")

  • List recent auto-backups for one automation: ha_manage_backup(scope="edits", action="list", domain="automation", entity_id="kitchen_lights")

  • View an auto-backup: ha_manage_backup(scope="edits", action="view", backup_name="automation.kitchen_lights.20260521_153000.yaml")

  • Diff an auto-backup vs current state: ha_manage_backup(scope="edits", action="diff", backup_name="automation.kitchen_lights.20260521_153000.yaml")

  • Restore an auto-backup: ha_manage_backup(scope="edits", action="restore", backup_name="automation.kitchen_lights.20260521_153000.yaml")

  • Delete one auto-backup: ha_manage_backup(scope="edits", action="delete", backup_name="...")

  • Bulk-delete old auto-backups: ha_manage_backup(scope="edits", action="delete", older_than_days=30)

ParametersJSON Schema
NameRequiredDescriptionDefault
nameNo(snapshot.create) Tarball name. Auto-generated if not provided.
limitNo(edits.list / snapshot.list) Maximum number of entries to return.
scopeYes'snapshot' for full HA tarballs; 'edits' for per-entity auto-backups.
actionYesOperation to perform. Valid (scope, action) combinations are listed in the tool description.
domainNo(edits.create / edits.list / edits.delete) Filter auto-backups by domain (e.g. 'automation', 'helper_timer'). Required for edits.create.
confirmNo(snapshot.delete) Must be True to confirm deletion โ€” a safety measure against accidental calls.
backup_idNo(snapshot.restore / snapshot.delete) Tarball ID (e.g. 'dd7550ed').
entity_idNo(edits.create / edits.list / edits.delete) Filter auto-backups by entity ID. Required for edits.create.
backup_nameNo(edits.view / edits.restore / edits.delete) Auto-backup filename (format '<domain>.<entity_id>.<timestamp>.yaml'). Not a tarball ID.
older_than_daysNo(edits.delete) Bulk-delete auto-backups older than this many days.
restore_databaseNo(snapshot.restore) Include database in the restore. Default false (config-only).

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

This is exemplary transparency. It discloses that snapshot restore restarts HA, snapshot delete is disabled by default and layered with guards (age floor, not delete newest, no scheduled backups), edits restore creates a safety snapshot first and does not restart HA, list/diff are read-only, and create sends progress heartbeats. This goes far beyond the destructiveHint annotation and aligns with it.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long, but the tool is genuinely complex: two scopes ร— six actions with different parameter sets and safety guards. The table, section headers, and example list make the length navigable and front-loaded. No filler or redundant prose; each section earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with 11 parameters, two scopes, six actions, destructive operations, and configuration toggles, the description covers everything an agent needs: valid combinations, safety locks, operational side effects, when to use alternatives, and concrete invocation examples. The output schema exists, so return-value documentation is not required here.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Even though schema coverage is 100%, the description adds substantial semantic value: backup_name format, backup_id example, confirm requirement for snapshot.delete, older_than_days bulk deletion, restore_database default false, and domain/entity_id requirements for edits.create. The examples map parameter combinations to concrete calls, eliminating ambiguity about which params apply to which scope/action.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Manage Home Assistant backups โ€” both full HA snapshots AND per-edit auto-backups.' The scope/action table enumerates every supported combination, so an agent immediately understands what the tool does and how it differs from sibling tools like ha_manage_app or ha_manage_updates.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description has an explicit 'When to use which scope' section, telling the agent to use scope='edits' for undoing recent edits and scope='snapshot' only for system-wide recovery. It also warns when the tool is NOT needed ('If the current definition was fetched or can be fetched, this tool is usually not needed'), plus safety preconditions such as enable_snapshot_delete and confirm=True.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_manage_energy_prefsManage Energy Dashboard PreferencesA
Destructive

Manage the Home Assistant Energy Dashboard preferences.

The Energy Dashboard configuration (grid/solar/battery/gas/water energy sources, individual device consumption sensors for electricity and water, cost tariffs) is stored in .storage/energy and not otherwise reachable via REST, services, or helper flows โ€” this tool is the only way for agents to inspect or modify it.

WHEN TO USE:

  • mode='get' / 'set': inspect or replace the full Energy Dashboard config. Use 'set' for bulk edits or anything touching multiple top-level keys at once.

  • mode='add_device' / 'remove_device': add or remove a single device-consumption entry. The tool performs a fresh read-modify-write internally; the caller does NOT manage config_hash. Use water=True to target the water meter list instead of electricity.

  • mode='add_source': append a single entry to energy_sources (grid, solar, battery, gas, or water). Same atomic read-modify-write semantics.

WHEN NOT TO USE:

  • To create the underlying statistics themselves โ€” they must already exist as HA entities before being referenced here; create them via the relevant integration's config flow first.

CAVEATS:

  • energy/save_prefs has per-key FULL-REPLACE semantics. Passing {"device_consumption": [<one entry>]} deletes every other device the user had configured โ€” silently, with no error. mode='set' requires a fresh config_hash for optimistic locking; convenience modes hide this entirely.

  • config_hash accepts both a single str (full-blob lock) and a dict[_PrefsKey, str] keyed by top-level keys (per-key lock, taken from the config_hash_per_key field of the mode='get' response). The per-key form lets an agent submit only the top- level key it wants to change โ€” set-equality between config keys and dict keys is enforced, and any key outside the canonical set (typo, etc.) on either side is rejected with VALIDATION_FAILED rather than silently dropped (so an empty submission cannot succeed as a no-op). A per-key submission still fully replaces that key's value as the save endpoint requires. Mismatch on any locked key returns RESOURCE_LOCKED with the offending keys in the response's top-level mismatched_keys (create_error_response flattens the context dict onto the response root).

  • dry_run=True skips the hash check entirely for both forms; the per-key form is therefore silently accepted on dry runs even if its keys would mismatch the current state.

  • A local shape check runs before every write; malformed payloads are rejected with a shape_errors list.

  • After a successful write, the tool calls energy/validate and returns any residual issues as post_save_validation_errors in the response. These reflect semantic problems (missing stats, unit mismatches) that shape checks can't catch; the save persists regardless โ€” correct the config and write again if needed.

  • The underlying save endpoint is admin-only. Non-admin tokens will receive an authorization error from Home Assistant.

  • Convenience modes are NOT idempotent: 'add_device' on an existing stat_consumption returns RESOURCE_ALREADY_EXISTS; 'remove_device' on a missing entry returns RESOURCE_NOT_FOUND. 'add_source' rejects duplicates by (type, stat_energy_from) for solar/battery/gas/water (RESOURCE_ALREADY_EXISTS); grid entries are appended without a duplicate check (multiple grid variants are legitimate, and grid has no single canonical uniqueness key) โ€” the caller is responsible for de-duplicating grid sources.

  • Convenience modes do NOT bypass the local shape check on dry_run: dry_run=True still raises RESOURCE_ALREADY_EXISTS (duplicate add_device / add_source), RESOURCE_NOT_FOUND (missing remove_device), or VALIDATION_FAILED (post-mutator shape error) when the proposed mutation is not applicable. The mutator and shape check both run before the dry-run short-circuit.

read get inspect energy dashboard preferences prefs electricity price prices pricing tariff tariffs rate rates cost costs kwh peak off-peak offpeak contract utility bill grid solar battery gas water consumption number_energy_price entity_energy_price stat_energy_from

ParametersJSON Schema
NameRequiredDescriptionDefault
modeYesOperation mode. Primitives: 'get' reads the current prefs; 'set' writes a full prefs payload (per-top-level-key full-replace). Convenience modes: 'add_device' / 'remove_device' / 'add_source' perform a single read-modify-write atomically โ€” no config_hash from the caller, the tool fetches it fresh internally.
nameNoOptional display name for mode='add_device'. Only used when adding a new device entry; ignored otherwise.
waterNoIf True, mode='add_device' / 'remove_device' targets 'device_consumption_water' instead of 'device_consumption'. Default False.
configNoFull prefs payload for mode='set'. Must contain the top-level keys you intend to replace: 'energy_sources', 'device_consumption', 'device_consumption_water'. Any top-level key present in this payload REPLACES the existing list entirely; any omitted key is preserved. Call with mode='get' first, mutate the returned config, then pass the whole object back. Ignored by convenience modes.
sourceNoSingle energy_sources entry for mode='add_source'. Must contain 'type' (one of grid|solar|battery|gas|water) and the type-specific required fields (e.g. solar/battery/gas/water require 'stat_energy_from'). Every source type also accepts an optional 'name' (display label in the energy graphs); battery additionally accepts 'stat_soc' (state-of-charge statistic). Note: HA Core's voluptuous schema for grid sources requires the full field set (cost_adjustment_day, stat_energy_to, stat_cost, entity_energy_price, number_energy_price, entity_energy_price_export, number_energy_price_export, stat_compensation) โ€” the local shape check is narrower, so a minimal {'type': 'grid'} passes locally but surfaces in post_save_validation_errors after writing. Pass the unused fields as None to satisfy the server. Required for mode='add_source'; ignored otherwise.
dry_runNoIf True, no write is performed. For mode='set': runs a local shape check on the proposed config AND calls the server's energy/validate against the CURRENT persisted state (Home Assistant's validate endpoint cannot validate an unsubmitted payload). For convenience modes: simulates the mutation against a fresh read and reports what would change without writing โ€” but still raises RESOURCE_ALREADY_EXISTS (duplicate add_device, or duplicate add_source for solar/battery/gas/water), RESOURCE_NOT_FOUND (missing remove_device), or VALIDATION_FAILED (post-mutator shape error) when the proposed mutation is not applicable. Default False.
config_hashNoHash from a previous mode='get' call. REQUIRED for mode='set' unless dry_run=True. Two forms: str (full-blob lock) or dict (per-key lock, taken from the config_hash_per_key field of mode='get'). Pass the dict form as a native object, NOT a JSON-encoded string โ€” a stringified dict is treated as a full-blob token and will report RESOURCE_LOCKED; clients that can only send strings should use the str full-blob form. See the tool docstring for fail-closed semantics. Ignored by convenience modes.
included_in_statNoOptional 'parent' statistic for mode='add_device'. Set this to a statistic that already INCLUDES this device's consumption (e.g., a whole-home or circuit-level meter that this device feeds into). The Energy Dashboard will subtract this device's reading from the parent so the parent's contribution is not double-counted. Ignored otherwise.
stat_consumptionNoStatistic entity_id for mode='add_device' / 'remove_device' (e.g. 'sensor.fridge_energy'). Required for those modes; ignored otherwise.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Extremely rich disclosure beyond the annotations: per-key FULL-REPLACE semantics with silent deletion of other devices, config_hash locking forms and fail-closed behavior, dry_run skipping the hash check, non-idempotency of convenience modes (RESOURCE_ALREADY_EXISTS/RESOURCE_NOT_FOUND), local shape checks, post-save validation persisting regardless of errors, and admin-only auth. All of this aligns with destructiveHint=true and idempotentHint=false with no contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but earns its length given the tool's complexity (5 modes, locking, validation, dry-run edge cases). It is well-structured with clear headers and front-loaded purpose. The trailing keyword list adds noise for a human reader, though it likely serves retrieval indexing; a slightly stronger edit would trim it.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a highly complex tool, nothing an agent needs to call it correctly is missing: mode selection, locking semantics, error conditions, prerequisites (statistics must pre-exist), auth requirements, and post-write validation behavior are all covered. Since an output schema exists, the description correctly avoids re-explaining return values and even references response fields like mismatched_keys where relevant.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Despite 100% schema coverage (baseline 3), the description adds substantial meaning beyond the schema: the stringified-dict config_hash gotcha ('a stringified dict is treated as a full-blob token and will report RESOURCE_LOCKED'), the HA Core voluptuous full-field requirement for grid sources, the double-counting semantics of included_in_stat, and dry_run's unusual behavior of still raising validation errors. The schema describes what parameters are; the description explains how they behave.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first line names a specific verb and resource ('Manage the Home Assistant Energy Dashboard preferences') and immediately enumerates what those preferences are: grid/solar/battery/gas/water sources, device consumption sensors, and cost tariffs. It further distinguishes the tool by stating it is 'the only way for agents to inspect or modify' this config, which is not reachable via REST, services, or helper flows.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit WHEN TO USE and WHEN NOT TO USE sections map each mode to its intended scenario ('Use 'set' for bulk edits...', 'mode='add_device' / 'remove_device': add or remove a single device-consumption entry'). The exclusion is concrete: the tool must not be used to create statistics, which should be created 'via the relevant integration's config flow first'. The claim that this is the only path to the energy config implicitly differentiates it from all dashboard-related siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_manage_hacsManage HACSA
Destructive

Manage HACS (Home Assistant Community Store) โ€” install/update, remove, add custom repositories, or refresh repository information.

Use action="download" to install or update a repository, action="remove" to uninstall a downloaded repository, or action="add_repository" to register a custom GitHub repository with HACS. This tool performs writes; to search the store or read repository details use ha_get_hacs_info. Use action="update_information" to run the HACS UI's "Update information" action โ€” a forced re-fetch of one repository's release data from GitHub, so a pending update becomes visible to HACS and its update entity immediately.

Examples:

  • Install latest: ha_manage_hacs(action="download", repository_id="441028036")

  • Install a version: ha_manage_hacs(action="download", repository_id="piitaya/lovelace-mushroom", version="v4.0.0")

  • Remove: ha_manage_hacs(action="remove", repository_id="owner/repo")

  • Add a custom repo: ha_manage_hacs(action="add_repository", repository="owner/repo", category="lovelace")

  • Refresh release data: ha_manage_hacs(action="update_information", repository_id="owner/repo")

Caveats: Installing an integration usually needs a Home Assistant restart to activate; new Lovelace cards need a browser cache clear. repository_id accepts a numeric HACS ID or an owner/repo path; add_repository requires owner/repo format plus a matching category. Removing an integration deletes its files but the loaded module persists until the next Home Assistant restart โ€” delete its config entries first (ha_remove_helpers_integrations). HACS refreshes custom repositories on its own only about every 48 hours, so update_information is the way to surface a just-published release.

ParametersJSON Schema
NameRequiredDescriptionDefault
actionYes'download' to install/update, 'add_repository' to register a custom repo, 'remove' to uninstall a downloaded repo, or 'update_information' to refresh a repository's release data from GitHub
versionNoSpecific version to install (action='download')
categoryNoRepository category (action='add_repository')
repositoryNoGitHub repo 'owner/repo' to add (action='add_repository')
repository_idNoNumeric HACS ID or 'owner/repo' path (action='download' / 'remove' / 'update_information')

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the destructiveHint and openWorldHint annotations, the description adds crucial caveats: the need for restart after installing integrations, browser cache clearing for Lovelace cards, the fact that removing an integration leaves the module loaded until restart, and the 48-hour refresh interval. This context is not inferred from annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but well-structured with a summary, examples, and caveats. Every sentence adds value, though it could be slightly tightened without losing critical information. It is not needlessly verbose for the tool's complexity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

All actions, parameter combinations, and edge cases are covered. The caveats address real-world operational concerns, and the presence of an output schema means return values need not be explained. The description is self-sufficient for an agent to select and invoke the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

While the schema documents each parameter, the description adds meaningful semantics: it maps actions to parameters, clarifies that repository_id accepts numeric or owner/repo, and explains that add_repository requires owner/repo plus a matching category. Concrete examples illustrate correct usage beyond the schema's field descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool manages HACS with specific actions: install/update, remove, add repositories, and refresh. It also distinguishes itself from the read-only sibling tool ha_get_hacs_info, making its purpose unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit when-to-use guidance: it names ha_get_hacs_info as the alternative for search/read, and explains when to use each action (e.g., update_information to surface a recent release because HACS refreshes every ~48 hours). This goes beyond mere function listing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_manage_pipelineManage Assist PipelineA
Destructive

Manage Home Assistant Assist pipelines.

Use action='list' to discover pipeline IDs, action='get' to inspect one pipeline, action='create' or action='update' to write pipeline settings, action='set_preferred' to choose the preferred pipeline, and action='process' to run a sentence through Assist.

action='process' sends the sentence straight to Assist's conversation agent, so a matched intent executes: it turns on the light rather than reporting that it would. Its result carries response_type ('action_done', 'query_answer' or 'error') and, on an error, error_code such as 'no_intent_match' โ€” Assist declining a sentence is an answer, not a tool failure, so inspect those fields rather than expecting a raised error. Use ha_call_service to act on an entity directly; use this to test what Assist itself understands. When the built-in agent answers, a matching conversation trigger runs its automation: that agent checks its sentence triggers before it matches intents, so this is not limited to intents. pipeline_id borrows a pipeline's conversation agent and language, but the sentence still goes to the agent directly. So with an agent other than the built-in one, neither sentence triggers nor prefer_local_intents apply โ€” a full pipeline run is what adds those for other agents.

EXAMPLES:

  • List pipelines: ha_manage_pipeline(action="list")

  • Get one pipeline: ha_manage_pipeline(action="get", pipeline_id="preferred")

  • Create by cloning preferred: ha_manage_pipeline( action="create", name="Local Assist", conversation_engine="conversation.local_llm", )

  • Create by cloning a specific pipeline: ha_manage_pipeline( action="create", base_pipeline_id="preferred", name="Local Assist", conversation_engine="conversation.local_llm", )

  • Update conversation agent and clear TTS voice: ha_manage_pipeline( action="update", pipeline_id="preferred", conversation_engine="conversation.local_llm", tts_voice="", )

  • Set preferred: ha_manage_pipeline( action="set_preferred", pipeline_id="preferred", )

  • Run a sentence: ha_manage_pipeline( action="process", sentence="turn on the kitchen light", )

  • Run it through one pipeline's agent: ha_manage_pipeline( action="process", sentence="turn on the kitchen light", pipeline_id="preferred", )

  • Continue a conversation: ha_manage_pipeline( action="process", sentence="and the hallway?", conversation_id="", )

Empty string clears nullable STT/TTS/wake-word fields. Non-nullable fields such as name, language, conversation_language, and conversation_engine must be omitted or non-empty.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameNoPipeline display name. Required when action='create'.
actionYesPipeline operation: list, get, create, update, set_preferred, or process.
agent_idNoFor process only, the conversation agent entity ID to answer, e.g. 'conversation.home_assistant'. Overrides the agent taken from pipeline_id; omit both for the default agent.
languageNoPipeline language, e.g. 'en'. For process, the language to recognise the sentence in.
sentenceNoNatural-language command to run through Assist. Required when action='process'. A matched intent executes, and with the built-in agent a sentence matching a conversation trigger runs that automation.
tts_voiceNoText-to-speech voice. Pass empty string to clear.
stt_engineNoSpeech-to-text engine. Pass empty string to clear.
tts_engineNoText-to-speech engine. Pass empty string to clear.
pipeline_idNoAssist pipeline ID. Required for get, update, and set_preferred. Optional for process, where it selects the conversation agent and language that pipeline is configured with.
stt_languageNoSpeech-to-text language. Pass empty string to clear.
tts_languageNoText-to-speech language. Pass empty string to clear.
wake_word_idNoWake-word ID. Pass empty string to clear.
make_preferredNoFor create/update only, also set the resulting pipeline as preferred with an extra websocket call. Ignored for other actions.
conversation_idNoFor process only, the conversation to continue. Returned in the response so follow-up sentences keep their context.
base_pipeline_idNoPipeline ID to clone when creating. Omit to clone the preferred pipeline. Ignored for non-create actions.
wake_word_entityNoWake-word entity ID. Pass empty string to clear.
conversation_engineNoConversation agent entity ID or engine ID. Required when action='create'.
prefer_local_intentsNoWhether Home Assistant local intents should be preferred before the conversation engine.
conversation_languageNoConversation language, usually '*'.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations (readOnlyHint=false, destructiveHint=true), the description adds rich behavioral context: it explains that action='process' executes intents ('it turns on the light rather than reporting that it would'), that errors are returned as fields ('does not raise an error'), and that conversation triggers only apply to the built-in agent. It also discloses the empty-string-clearing convention and the extra websocket call for make_preferred. This is far beyond annotation expectations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the action list, then dives into important behavioral nuances and examples. While long, it earns its place by covering six distinct actions and complex edge cases (e.g., agent-specific behavior). The examples are well-organized and labeled. It loses a point for densityโ€”the process paragraph is a wall of text that could be broken up for easier scanningโ€”but overall remains efficient for a complex tool.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with 19 parameters and six actions, the description is remarkably complete. It covers error handling ('Assist declining a sentence is an answer, not a tool failure'), agent behavior ('conversation triggers... are not limited to intents'), multiple examples, and the empty-string-clearing convention. The output schema is also present, and the description complements it without redundancy. No gaps identified.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema already has 100% coverage, so baseline is 3. The description adds value beyond the schema by explaining interaction semantics, e.g., that conversation_id is used for follow-ups, base_pipeline_id cloning behavior, and that pipeline_id is required for certain actions. The extensive examples further clarify parameter usage. It doesn't repeat schema descriptions verbatim but adds contextual meaning (e.g., the process action's side effects), so a 4 is warranted.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Manage Home Assistant Assist pipelines' and then enumerates the six actions (list, get, create, update, set_preferred, process). It distinguishes this tool from its sibling by specifying 'Use ha_call_service to act on an entity directly; use this to test what Assist itself understands.' This is a specific verb+resource with clear scope and sibling differentiation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly provides usage guidelines with a direct alternative: 'Use ha_call_service to act on an entity directly; use this to test what Assist itself understands.' It also differentiates when to use each action (e.g., 'action="list" to discover pipeline IDs', 'action="process" to run a sentence through Assist'). It further clarifies behavior with the built-in agent versus other agents, giving concrete when-to-use and when-not-to-use guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_manage_radioManage Radios (Z-Wave / Zigbee / Matter / Thread)A
Destructive

Manage Home Assistant radios โ€” Z-Wave, Zigbee, Matter, and Thread.

For read-only inspection prefer ha_get_device / ha_get_system_health, which mirror the 'diagnostics' and 'network_status' actions; use this tool for writes and the active 'ping' probe (unique to this tool). Write actions perform inclusion/commissioning, removal, healing, reconfiguration, firmware updates and credential provisioning.

Caveats: destructive actions (e.g. remove_device, network restore, change_channel, hard_reset, remove_fabric) require confirm=True. Long-running actions (inclusion, rebuild routes, firmware) start the operation and return immediately with long_running=true; completion happens out-of-band. Interactive Z-Wave S2 secure inclusion (read-the- PIN pairing) is not scriptable โ€” use SmartStart/QR provisioning here or the HA UI.

ParametersJSON Schema
NameRequiredDescriptionDefault
radioYesWhich radio to manage.
actionYesOperation to perform. Actions vary per radio; an unknown action returns the supported list for that radio. Common: 'diagnostics', 'network_status', 'ping', 'add'/'commission', 'remove_device', 'reinterview'/'reconfigure', 'firmware_update'.
paramsNoAction-specific parameters (e.g. code, pin, channel, property, value). An unknown action returns that radio's supported action list with one-line summaries.
confirmNoRequired (True) to run destructive actions.
device_idNoTarget device (node) for node-scoped actions.
entity_idNoResolve the device from this entity for node-scoped actions.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark destructiveHint=true. Description adds: destructive actions need confirm=True, long-running actions start and return with long_running=true, and S2 secure inclusion is not scriptable. These details go beyond the annotation signal.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Description is appropriately sized โ€” three paragraphs with front-loaded purpose and distinction. Every sentence adds meaningful information; no redundancy or fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (multiple radios, many actions, destructive/long-running behaviors, and output schema existing), the description covers when to use, behavioral caveats, error handling (unknown action returns list), and non-scriptable cases. No gaps remain.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3. Description adds value by explaining that an unknown action returns the supported list for that radio, and that params are action-specific (e.g., code, pin). This extra context justifies above baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Manage Home Assistant radios โ€” Z-Wave, Zigbee, Matter, and Thread' and distinguishes read-only inspection (prefer other tools) from write actions. It uses specific verb+resource and differentiates from sibling tools like ha_get_device and ha_get_system_health.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states when to use this tool (writes and ping probe) versus alternatives (read-only inspection via ha_get_device/h_get_system_health). Also provides caveats: destructive actions require confirm=True, long-running actions return immediately, and interactive S2 inclusion is not scriptable.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_manage_themeManage Frontend ThemesA
DestructiveIdempotent

Manage Home Assistant frontend themes.

When NOT to use: themes are YAML files - Home Assistant has no API to create or edit them. Installing community themes goes through HACS (ha_manage_hacs); editing custom theme files goes through ha_config_set_yaml (beta, edits themes/.yaml keyed by theme name and attempts an automatic theme reload).

When to use: action='list' discovers installed theme names and the current defaults; action='set' selects the backend default theme (optionally per light/dark mode).

SCREENSHOT-ENGINE ACTIONS (per-user, not the backend default): Taking a dashboard screenshot makes the Puppet engine write the saved theme of the Home Assistant user its token belongs to, which also flips that user's live web and mobile sessions. The screenshot tools are read-only and only report this; use action='set_engine_theme' with the value quoted in their warning to put it back, and action='get_engine_theme' to inspect it. These act on that engine account's per-user profile via frontend/set_user_data, which is a different layer from the backend default that action='set' changes. Giving the engine its own dedicated user and token avoids the issue entirely.

Caveats: action='set' changes the backend-selected default only - users who explicitly picked a theme in their profile keep their choice. Theme names are validated by Home Assistant at call time.

EXAMPLES:

  • List themes: ha_manage_theme(action="list")

  • Set default theme: ha_manage_theme(action="set", theme_name="nord")

  • Set dark-mode theme: ha_manage_theme( action="set", theme_name="nord", mode="dark")

  • Restore built-in default: ha_manage_theme( action="set", theme_name="default")

  • Inspect the engine account's theme: ha_manage_theme( action="get_engine_theme")

  • Undo a screenshot's theme change (pass BOTH values from the warning, so a theme changed since then is not overwritten): ha_manage_theme(action="set_engine_theme", value={"theme": "", "dark": False}, expected_current={"theme": "default", "dark": True})

ParametersJSON Schema
NameRequiredDescriptionDefault
modeNoWhich mode the theme applies to when action='set'. Defaults to light.
forceNoaction='set_engine_theme' only: skip the expected_current guard and overwrite unconditionally. Leave false unless you intend to discard whatever is stored.
valueNoFrontend user-data theme object when action='set_engine_theme', e.g. {'theme': '', 'dark': False}. An empty dict restores default/auto behavior. Take this verbatim from the warning a screenshot tool emitted.
actionYesTheme operation: 'list' installed themes, 'set' the backend default theme, or read/restore the screenshot engine account's own per-user theme with 'get_engine_theme' / 'set_engine_theme' (a different layer from the backend default).
theme_nameNoTheme name when action='set'. Must be an installed theme; 'default' restores the built-in theme, 'none' resets the chosen mode to the built-in default.
expected_currentNoGuard for action='set_engine_theme': the stored theme is read immediately before the write and the write is skipped if it no longer equals this. Omitting this value or passing null both mean 'expect no stored theme', enforced like any other value; the guard is always applied unless force is set. Best-effort, not atomic -- Home Assistant exposes no conditional write, so a change landing between that read and the write is not caught. Pass the expected_current value quoted in the screenshot tool's warning.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description goes well beyond the annotations, explaining that action='set' affects only the backend default and that users with explicit theme choices keep theirs. It also discloses that screenshot-engine theme changes flip live user sessions, that the expected_current guard is best-effort and non-atomic, and that force skips the guard. This is rich, honest behavioral context that does not contradict the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but well-structured with clear sections and examples. It front-loads the core purpose and usage guidance. Some details are repeated from the schema, and the screenshot-engine section is verbose, but the complexity of the tool justifies much of the length.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with four distinct actions, multiple parameter guards, and a screenshot-engine interaction, the description covers all necessary context: when to use, caveats, examples, and behavioral warnings. An output schema exists, so return values do not need to be explained. Nothing essential is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description adds value with concrete examples, guidance to pass value verbatim from screenshot warnings, and clarification of the expected_current guard semantics. It largely reinforces the schema rather than introducing entirely new meaning, so a 4 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly identifies the resource (Home Assistant frontend themes) and the specific operations: listing installed themes, setting the backend default, and managing the screenshot engine account's per-user theme. It also distinguishes itself from related tools like ha_manage_hacs and ha_config_set_yaml by explicitly stating what it is not for.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit 'When NOT to use' and 'When to use' guidance, naming alternatives for editing theme files and installing community themes. It also gives detailed context for when to use each action, including the screenshot-engine scenario.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_manage_updatesManage UpdatesA
Destructive

Manage Home Assistant updates -- list, read details, batch install, skip, or un-skip.

Covers Core, OS, supervisor, apps (add-ons), device firmware, and HACS update entities. In Read Only Mode the read actions ('list', 'get') stay available; write actions are blocked.

Installs run asynchronously in Home Assistant and can take minutes: 'install' returns once the service calls are accepted, with per-entity results. Poll action='list' to watch in_progress until installed_version reaches latest_version.

EXAMPLES:

  • List all updates: ha_manage_updates()

  • Pre-update analysis: ha_manage_updates(action="get", entity_ids=["update.home_assistant_core_update"], include_release_notes=True)

  • Update everything pending in a category: ha_manage_updates(action="install", categories=["addons", "hacs"])

RETURNS (action='list'): updates_available, updates, categories, and ha_mcp_update -- this MCP server's own update status {current, latest, update_available}, so a newer ha-mcp release can be flagged.

RETURNS (action='get'): update details, release notes; with include_release_notes=True on Core also breaking_changes.entries[], multi_version_release_notes[], and installed_integrations.

ParametersJSON Schema
NameRequiredDescriptionDefault
actionNo'list' (all pending updates, default), 'get' (details/release notes for one update), 'install' (apply pending updates), 'skip' (hide the offered version), or 'clear_skipped' (re-offer a skipped version).list
backupNoFor install: create a backup before installing where the update entity supports it (apps/add-ons). Default: False.
categoriesNoFor install: apply every pending update in these categories ('addons', 'hacs', 'devices', 'other'). Mirrors the HA 2026.7 'Update all' button: core/os/supervisor are excluded by design (target those individually via entity_ids) and skipped updates are never included.
entity_idsNoUpdate entity_id(s) to act on. 'get' takes exactly one; skip/clear_skipped require at least one; for install, mutually exclusive with categories.
include_skippedNoFor list: include updates that have been skipped (default: False).
include_release_notesNoFor get on a Core update entity: fetch multi-version release notes and breaking changes for all versions between installed and latest (default: False). Adds breaking_changes, multi_version_release_notes, and installed_integrations to the response.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the destructiveHint annotation, the description details that installs run asynchronously, take minutes, and require polling to monitor progress. It also clarifies read-only mode behavior. No contradictions with annotations; this adds significant value.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with clear sections: overview, scope, behavioral notes, examples, and return documentation. Every sentence adds value, and the key information is front-loaded. No unnecessary verbiage.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (multiple actions, async execution, categories, return types), the description thoroughly covers all aspects. It explains return formats, mentions the ha_mcp_update status, and provides practical examples. No gaps remain for effective use.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3. The description adds behavioral context beyond the schema, such as mutual exclusivity of entity_ids and categories for install, and the effect of include_release_notes on the response. It enhances understanding of parameter interactions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Manage Home Assistant updates -- list, read details, batch install, skip, or un-skip.' It lists the covered update domains (Core, OS, supervisor, apps, device firmware, HACS), making the scope explicit. This distinguishes it from sibling tools that handle different aspects of Home Assistant.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains when to use each action (list, get, install, skip, clear_skipped) and provides examples. It notes read-only mode behavior and asynchronous installs with polling instructions. However, it does not explicitly exclude scenarios or compare to specific sibling tools, which would elevate to a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_reload_coreReload Core ComponentsA
Destructive

Reload Home Assistant configuration without full restart.

This tool reloads specific configuration components, allowing changes to take effect without restarting the entire Home Assistant instance. This is much faster than a full restart.

Parameters:

  • target: What to reload. Options:

    • "all": Reload all reloadable components

    • "automations": Reload automation configurations

    • "scripts": Reload script configurations

    • "scenes": Reload scene configurations

    • "groups": Reload group configurations

    • "input_booleans": Reload input_boolean helpers

    • "input_numbers": Reload input_number helpers

    • "input_texts": Reload input_text helpers

    • "input_selects": Reload input_select helpers

    • "input_datetimes": Reload input_datetime helpers

    • "input_buttons": Reload input_button helpers

    • "timers": Reload timer helpers

    • "templates": Reload template sensors/entities

    • "persons": Reload person configurations

    • "zones": Reload zone configurations

    • "core": Reload core configuration (customize, packages)

    • "themes": Reload frontend themes

  • entry_id: Reload a SINGLE config entry (one integration instance) instead of sweeping subsystems โ€” the fast path after editing a custom component on disk. Pass it alone (leave target at its "all" default); combining it with an explicit target is a validation error. Find the id via ha_get_integration.

Example Usage:

# Reload just automations after editing
ha_reload_core(target="automations")

# Reload all configurations
ha_reload_core(target="all")

# Reload input helpers after adding new ones
ha_reload_core(target="input_booleans")

When to Use:

  • After editing automation/script YAML files

  • After adding new input helpers via YAML

  • After modifying customize.yaml

  • After theme changes

ParametersJSON Schema
NameRequiredDescriptionDefault
targetNoall
entry_idNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate destructiveHint=true, so the description adds value by detailing what reload actions are available (target options) and the special behavior of entry_id (fast path for single integration). It does not repeat annotation info, but provides behavioral context beyond it.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is structured with sections, bullet points, and code examples, making it easy to scan. While somewhat lengthy due to the many target options, every sentence earns its place. Could be slightly more concise, but the structure aids comprehension.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has only 2 parameters (both optional), an output schema exists (so return values are covered), and no nested objects, the description is fully complete. It covers all possible parameter values, usage patterns, and links to sibling tool ha_get_integration for finding entry_id.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has no descriptions (0% coverage), but the description compensates fully by enumerating all 17 valid target options with explanations, and thoroughly explains entry_id usage including how to find the id and that combining with target is a validation error. This adds critical meaning beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description explicitly states the tool reloads Home Assistant configuration without a full restart, using a specific verb ('reload') and resource ('core components'). It distinguishes from sibling ha_restart by emphasizing speed and avoiding full restart. The extensive target list further clarifies scope.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description includes a dedicated 'When to Use' section listing specific scenarios (e.g., after editing automation YAML, modifying customize.yaml). It also explains entry_id usage and warns against combining it with an explicit target, providing clear guidance on proper invocation.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_remove_area_or_floorRemove Area or FloorA
DestructiveIdempotent

Remove a Home Assistant area or floor.

Removing an area unassigns its entities and devices (the entities and devices themselves are not removed). Removing a floor unassigns its areas. May break automations referencing the removed area/floor.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesArea ID or floor ID to delete (use ha_list_floors_areas to find IDs)
kindYesWhich registry to delete from: 'area' or 'floor'

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate destructiveHint=true. The description adds valuable context: entities/devices are unassigned (not removed), floors unassign areas, and automations may break. This goes beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Description is concise with no wasted words. Main purpose is front-loaded, followed by necessary details. Every sentence is informative.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's simplicity, presence of output schema, and annotations, the description is complete. It explains side effects, risks, and how to find IDs, meeting all needs for an agent to use correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so parameters are well-documented. The description adds a helpful hint for the id parameter: 'use ha_list_floors_areas to find IDs', which adds value beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it removes a Home Assistant area or floor, with specific verbs and resource. It distinguishes from sibling tools like ha_set_area_or_floor (create/update) and ha_list_floors_areas (list).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It says what the tool does but does not explicitly tell when not to use or recommend alternatives. It is clear for its intended use but lacks exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_remove_deviceRemove DeviceA
DestructiveIdempotent

Remove an orphaned device from the Home Assistant device registry.

WARNING: This removes the device entry from the registry.

  • Use only for orphaned devices that are no longer connected

  • Active devices will typically be re-added by their integration

  • Associated entities may also be removed

This uses the config entry removal which is the safe way to remove devices. If the device has multiple config entries, they must all be removed.

EXAMPLES:

  • Remove orphaned device: ha_remove_device("abc123def456")

NOTE: For most use cases, consider disabling the device instead: ha_set_device(device_id="abc123", disabled_by="user")

ParametersJSON Schema
NameRequiredDescriptionDefault
device_idYesDevice ID to remove from the registry

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Describes side effects (removes device entry, may remove associated entities), safe method (config entry removal), and multiple config entry requirement. Adds context beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Concise, well-structured with warning, bullet points, example, and alternative. Every sentence adds value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers purpose, usage, consequences, and alternatives. Output schema exists, so return values need not be described.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description includes an example usage, but the input schema already fully describes the device_id parameter. No additional semantic value beyond schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Explicitly states it removes an orphaned device from the registry. Distinguishes from siblings like ha_set_device and ha_remove_entity by specifying orphaned condition.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides clear when-to-use (only for orphaned devices), when-not-to (active devices may be re-added), and an alternative (disable via ha_set_device).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_remove_entityRemove EntityA
DestructiveIdempotent

Remove one or more entities from the Home Assistant entity registry.

Permanently removes the entity registration from Home Assistant. The entity will no longer appear in the UI or be available to automations.

WARNING: This permanently removes the entity registration.

  • Use only for orphaned or stale entity entries

  • If the underlying device or integration is still active, the entity may be re-added automatically on the next HA restart or reload

  • This action cannot be undone without restoring from backup

BULK MODE: Pass a list of entity IDs to remove up to 100 at once โ€” handy for clearing the restored=true orphans an integration leaves behind after its filters change. Removals run sequentially and return: {removed: [...], skipped: [...], errors: [{entity_id, code, message}]} where skipped = ids already absent (not-found is idempotent, not an error). Bulk mode is NOT auto-backed-up (the snapshot is single-entity); single-id removal still is.

EXAMPLES:

  • Remove orphaned sensor: ha_remove_entity("sensor.old_temperature")

  • Remove stale helper entry: ha_remove_entity("input_boolean.deleted_helper")

  • Bulk cleanup: ha_remove_entity(["sensor.orphan_1", "sensor.orphan_2"])

NOTE: For most use cases, consider disabling instead: ha_set_entity(entity_id="sensor.old", enabled=False)

RELATED TOOLS:

  • ha_search: Find entities to verify the entity_id before removing

  • ha_get_entity: Check entity details before removal

ParametersJSON Schema
NameRequiredDescriptionDefault
entity_idYesEntity ID, or a list of entity IDs, to remove from the entity registry (e.g., 'sensor.old_temperature'). Permanently removes the registration(s).

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes beyond annotations by detailing permanent deletion, bulk mode sequential behavior, return format ({removed, skipped, errors}), idempotency of not-found, and backup implications. Though annotations already mark it destructive/idempotent, the description adds valuable operational context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with headings (WARNING, BULK MODE, EXAMPLES, NOTE, RELATED TOOLS) and front-loads the primary purpose. It is somewhat lengthy but each section earns its place given the tool's destructive nature and bulk mode details.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers all necessary aspects: purpose, warnings, bulk mode behavior, return format, idempotency, backup implications, and relationship to other tools. With an output schema present, the return format description in bulk mode is sufficient.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema provides 100% coverage with a clear description for entity_id. The description adds bulk mode semantics (up to 100 items, sequential removal, return format) and examples, enhancing understanding beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Remove one or more entities from the Home Assistant entity registry' with specific verb and resource. It distinguishes from related tools like ha_set_entity (disabling) and ha_search (finding entities), and provides examples for different use cases.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly recommends using only for orphaned or stale entries, warns about automatic re-addition, and suggests disabling as an alternative. It also lists related tools (ha_search, ha_get_entity) for verifying before removal.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_remove_helpers_integrationsRemove Helper or IntegrationA
DestructiveIdempotent

Remove a Home Assistant helper or integration config entry.

Unifies three backend removal mechanisms โ€” simple-helper websocket delete, config-entry delete, and config-subentry delete โ€” behind one entry point with four routing paths driven by helper_type.

WHEN NOT TO USE:

  • Removing only an entity (without deleting its underlying helper or config entry) โ€” use ha_remove_entity instead.

  • YAML-configured helpers โ€” they have no storage backend. Edit the YAML file and reload the relevant integration.

SUPPORTED HELPER TYPES:

  • SIMPLE (12, websocket-delete): input_button, input_boolean, input_select, input_number, input_text, input_datetime, counter, timer, schedule, zone, person, tag.

  • FLOW (17, config-entry-delete via entity lookup): template, group, utility_meter, derivative, min_max, threshold, integration, statistics, trend, random, filter, tod, generic_thermostat, switch_as_x, generic_hygrostat, history_stats, mold_indicator.

ROUTING:

  • SIMPLE helper_type + bare helper_id or entity_id โ†’ websocket delete.

  • FLOW helper_type + entity_id โ†’ resolve entity_id to config_entry_id via entity_registry, then delete the config entry. All sub-entities (e.g. utility_meter tariffs) are removed together.

  • helper_type=None + entry_id โ†’ direct config entry delete (any integration).

  • helper_type="config_subentry" + parent entry_id + subentry_id โ†’ delete one config subentry.

MISSING-TARGET CONTRACT: A target that is confirmed absent raises a structured error rather than returning silent success, so a typo'd or stale identifier surfaces immediately at the caller layer (the success boolean is what agent wrappers branch on). The error code per-path follows the target shape:

  • SIMPLE (bare helper_id or entity_id): state-machine empty AND entity registry empty โ†’ raises ENTITY_NOT_FOUND.

  • FLOW (entity_id): not in entity registry โ†’ raises ENTITY_NOT_FOUND. YAML-configured helpers (no config entry backing) raise RESOURCE_NOT_FOUND. A bare helper_id (no .) on a FLOW target raises ENTITY_NOT_FOUND โ€” FLOW resolution needs a full entity_id. TOCTOU 404 on the resolved entry_id raises RESOURCE_NOT_FOUND.

  • Direct config entry (helper_type=None): backend returns HTTP 404 โ†’ raises RESOURCE_NOT_FOUND.

  • Config subentry: backend returns a "not_found" error โ†’ raises RESOURCE_NOT_FOUND.

Idempotency at the contract level still holds (call N times = same response). Transient connectivity failures (WebSocket disconnected, network timeouts) raise their own codes (WEBSOCKET_DISCONNECTED, CONNECTION_FAILED) so retry logic can branch separately.

EXAMPLES:

  • Remove SIMPLE button: ha_remove_helpers_integrations( target="my_button", helper_type="input_button", confirm=True )

  • Remove FLOW utility_meter (any sub-entity works): ha_remove_helpers_integrations( target="sensor.energy_peak", helper_type="utility_meter", confirm=True, )

  • Remove any integration by entry_id: ha_remove_helpers_integrations( target="01HXYZ...", confirm=True )

  • Remove a config subentry: ha_remove_helpers_integrations( target="01HXYZ...", helper_type="config_subentry", subentry_id="subentry-123", confirm=True )

WARNING: Removing a helper or integration that is referenced by automations, scripts, or other integrations may cause those to fail. Use ha_search() / ha_get_integration() to verify before removal. Cannot be undone.

ParametersJSON Schema
NameRequiredDescriptionDefault
waitNoWait for entity removal. Default: True. Ignored when helper_type=None or helper_type='config_subentry' (no entity poll, require_restart returned).
targetYesWhat to remove. One of: (a) bare helper_id for SIMPLE helpers (requires helper_type), e.g. 'my_button'; (b) full entity_id (requires helper_type), e.g. 'input_button.my_button' or 'sensor.my_meter'; (c) config entry_id for any integration (helper_type=None), e.g. value from ha_get_integration(); (d) parent config entry_id for config_subentry (requires helper_type='config_subentry' and subentry_id).
confirmNoMust be True to confirm removal.
helper_typeNoHelper type. Required when target is a helper_id (bare) or entity_id. Set to None when target is a config entry_id to remove any integration. Use 'config_subentry' to remove a config subentry under target.
subentry_idNoConfig subentry ID to remove when helper_type='config_subentry'.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations provide destructiveHint=true and idempotentHint=true, but the description goes far beyond: it details three backend mechanisms, routing paths, missing-target error codes, idempotency behavior, transient failure codes, and a warning about dependencies. This adds critical context beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but every section earns its place: WHEN NOT TO USE, SUPPORTED HELPER TYPES, ROUTING, MISSING-TARGET CONTRACT, EXAMPLES, and WARNING. It is well-structured, front-loaded with a summary, and uses clear headings, making it easy to navigate despite its length.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (5 parameters, multiple routing paths, error handling) and the presence of an output schema, the description is exceptionally complete. It covers all use cases, error codes, examples, and risk warnings, leaving no gaps for an agent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Although schema coverage is 100%, the description adds substantial meaning: it explains the four target shapes, the helper_type routing, the difference between helper_id and entity_id, and the config_subentry case. This goes well beyond the schema's property descriptions, enriching agent understanding.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Remove a Home Assistant helper or integration config entry.' It specifies the verb (remove) and resource (helper/integration config entry) and distinguishes from sibling tools like ha_remove_entity, which is explicitly mentioned in the WHEN NOT TO USE section.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit WHEN NOT TO USE guidance naming alternatives (ha_remove_entity) and covers YAML-configured helpers. It also explains routing paths based on helper_type, giving clear criteria for when to use this tool vs others.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_remove_todo_itemRemove Todo ItemA
DestructiveIdempotent

Remove an item from a Home Assistant todo list.

Permanently deletes an item from the specified todo list.

IDENTIFYING ITEMS:

  • Use the item's UID (from ha_get_todo)

  • Or use the exact item summary/name text

EXAMPLES:

  • Remove by name: ha_remove_todo_item("todo.shopping_list", "Buy milk")

  • Remove by UID: ha_remove_todo_item("todo.shopping_list", "abc123-uid")

USE CASES:

  • "Remove milk from my shopping list"

  • "Delete the eggs item"

  • "Clear 'call mom' from my todo"

WARNING: This permanently removes the item. To mark as completed instead, use ha_set_todo_item() with status="completed".

ParametersJSON Schema
NameRequiredDescriptionDefault
itemYesItem to remove - can be the item UID or the exact item summary/name
entity_idYesTodo list entity ID (e.g., 'todo.shopping_list')

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate destructiveHint=true and idempotentHint=true. The description reinforces the permanent deletion with a warning. However, it does not explain the idempotent behavior (e.g., removing a non-existent item may not error), though the annotation covers it.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with clear headings (IDENTIFYING ITEMS, EXAMPLES, USE CASES, WARNING), is front-loaded with the core purpose, and every sentence adds meaningful information without redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (simple removal operation with two parameters), the description covers identification methods, examples, use cases, and a warning about permanence. Since an output schema exists, there's no need to detail return values.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents both parameters. The description adds value by providing examples of how to use the 'item' parameter with UID or exact name, and 'entity_id' with a concrete example.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('Remove an item'), the resource ('Home Assistant todo list'), and specifies it is a permanent deletion. It distinguishes from the sibling 'ha_set_todo_item' by mentioning the alternative for marking as completed.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit usage guidance, including how to identify items (by UID or exact name) and specific use cases. It clearly directs users to use 'ha_set_todo_item' for marking items as completed instead of deleting.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_remove_zoneRemove ZoneA
DestructiveIdempotent

Remove a Home Assistant zone.

EXAMPLES:

  • Remove zone: ha_remove_zone("abc123")

WARNING: Removing a zone used in automations may cause those automations to fail. Use ha_get_zone() to find the zone_id for the zone you want to remove.

NOTE: The 'home' zone cannot be removed as it is typically defined in configuration.yaml.

ParametersJSON Schema
NameRequiredDescriptionDefault
zone_idYesZone ID to remove (use ha_get_zone to find IDs)

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Adds context beyond annotations: warns about automations, home zone restriction, and references ha_get_zone for ID lookup.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Concise 5 sentences with example, warning, note. Well-organized and front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers purpose, prerequisites, limitations, side effects. Output schema exists, so return values not needed.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Only one parameter with schema coverage 100%. Description adds value by explaining how to find zone_id via ha_get_zone.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Clearly states 'Remove a Home Assistant zone.' Distinguishes from siblings like ha_set_zone and ha_get_zone.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides example, warning about automations, note that 'home' zone cannot be removed, and suggests using ha_get_zone to find IDs.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_report_issueReport Issue or FeedbackA
Read-onlyIdempotent

Get diagnostic information and templates for filing issue reports or feedback.

This tool generates templates for TWO types of reports:

  1. Runtime Bug Report - For ha-mcp errors, failures, unexpected behavior

  2. Agent Behavior Feedback - For AI agent inefficiency, wrong tool usage

IMPORTANT FOR AI AGENTS: You MUST analyze the conversation context to determine which template to present:

๐Ÿ› Present RUNTIME BUG template if:

  • User reports an error, failure, or unexpected behavior

  • A tool returned an error or incorrect result

  • Something is broken or not working in ha-mcp

๐Ÿค– Present AGENT BEHAVIOR template if:

  • User mentions YOU (the agent) used the wrong tool

  • User suggests a more efficient workflow

  • User reports YOUR inefficiency or mistakes

  • User says you should have done something differently

If unclear which type, ASK the user: "Are you reporting a bug in ha-mcp, or providing feedback on how I used the tools?"

WHEN TO USE THIS TOOL:

  • "I want to file a bug/issue/report"

  • "This isn't working"

  • "You should have used [other tool]"

  • "That was inefficient"

OUTPUT: Returns both templates plus diagnostic data. The full response is LARGE (the captured logs appear in the raw log keys AND inside each template) โ€” pass fields=... to fetch only the keys you need once you know which template applies. Key fields:

  • runtime_bug_template, agent_behavior_template โ€” pick based on context

  • recent_logs, startup_logs โ€” captured ha-mcp tool/server log entries

  • addon_logs โ€” addon container stdout/stderr (HA add-on installs only; empty string otherwise)

  • core_error_log โ€” Home Assistant error log (home-assistant.log) over REST; carries auth / integration errors that don't show in addon_logs

  • missing_tool_hint โ€” check this FIRST when the report is about a missing/unavailable tool; a stale client tool list (not a bug) is the usual cause, and refreshing the MCP connection is the fix

  • suggested_title, duplicate_check_urls, anonymization_guide

ParametersJSON Schema
NameRequiredDescriptionDefault
fieldsNoReturn only the specified top-level response keys โ€” the full response (both templates + logs + diagnostics, with log content repeated across the raw keys and templates) is very large. None = full response. Typical for a runtime bug: 'runtime_bug_template,suggested_title,runtime_bug_submit_url,duplicate_check_urls,anonymization_guide,instructions'; for agent feedback swap in agent_behavior_template and agent_behavior_submit_url. The templates already embed the relevant logs, so the raw log keys are only needed for your own analysis. Available keys: diagnostic_info, recent_logs, startup_logs, addon_logs, core_error_log, log_count, startup_log_count, formatted_report, runtime_bug_template, agent_behavior_template, anonymization_guide, suggested_title, runtime_bug_submit_url, agent_behavior_submit_url, duplicate_check_urls, missing_tool_hint, instructions.
tool_call_countNoNumber of tool calls made since the issue started. This determines how many log entries to include. Count how many ha_* tools were called from when the issue began. Default: 10. Max: 16 (limited by 200-entry log buffer: 16*4*3=192)

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=true and idempotentHint=true, so the agent knows it's safe. The description adds significant behavioral context: it returns large diagnostic data, includes log entries, and explains the `fields` parameter to manage response size. This goes well beyond what annotations provide.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-organized with headings, bullet points, and clear sections, front-loading critical information. However, it is quite long; while every sentence is useful, some details could be trimmed without losing clarity. Still, it is structured effectively for an AI agent.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite the tool's complexity and the presence of an output schema, the description covers all necessary context: how to choose the appropriate template, when to use the `fields` parameter, what diagnostic fields are available, and even hints about missing tools. It is fully complete for an agent to use correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% for the two parameters. The description adds substantial meaning: for `fields`, it lists all available keys and provides usage examples; for `tool_call_count`, it explains the default and maximum and the reasoning behind them. This greatly enhances understanding beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool generates diagnostic information and templates for filing issue reports or feedback, and it distinguishes between two specific report types (Runtime Bug Report and Agent Behavior Feedback). This sets it apart from all sibling tools, none of which are for reporting issues.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit conditions for when to use the tool with concrete examples (e.g., 'I want to file a bug', 'This isn't working', 'You should have used [other tool]'). It also instructs the agent to ask the user for clarification if the report type is unclear, effectively guiding the agent's decision-making.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_restartRestart Home AssistantA
Destructive

Restart Home Assistant.

WARNING: This will restart the entire Home Assistant instance! All automations will be temporarily unavailable during restart. The restart typically takes 1-5 minutes depending on your setup.

Parameters:

  • confirm: Must be set to True to confirm the restart. This is a safety measure to prevent accidental restarts.

Best Practices:

  1. Config is validated automatically before the restart proceeds; to pre-check, call ha_get_system_health(include="config_check")

  2. Notify users before restarting (if applicable)

  3. Schedule restarts during low-activity periods

Example Usage:

# Optional pre-check (ha_restart also validates config automatically)
health = ha_get_system_health(include="config_check")
if health["config_check"]["is_valid"]:
    # Restart with confirmation
    result = ha_restart(confirm=True)

Alternative: For configuration changes, consider using ha_reload_core() instead, which reloads specific components without a full restart.

ParametersJSON Schema
NameRequiredDescriptionDefault
confirmNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate destructiveness (destructiveHint=true). Description adds context: restart duration (1-5 minutes), temporary unavailability of automations, and automatic config validation. No contradictions with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well-structured with clear sections (warning, parameters, best practices, example, alternative). Every sentence provides value, no redundancy. Efficient yet comprehensive.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers all essential aspects: purpose, impact, parameter meaning, pre-check option, usage example, alternative. Additionally, output schema exists (though not shown), so description needn't explain returns.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, but description fully explains the 'confirm' parameter: must be True, serves as safety measure. This adds critical meaning beyond schema's type/default.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description clearly states 'Restart Home Assistant' as the purpose, uses a specific verb and resource, and distinguishes from siblings by mentioning ha_reload_core as an alternative for config changes.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly provides when to use (restart instance) and when not (for config changes, use ha_reload_core). Includes best practices like notifying users and scheduling during low activity.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_set_area_or_floorCreate or Update Area or FloorA
Destructive

Create or update a Home Assistant area or floor.

Pass kind='area' (with optional floor_id, picture) or kind='floor' (with optional level). Provide name only to create a new entry; provide id to update an existing one. Cross-kind parameters (e.g., picture under kind='floor') are rejected with VALIDATION_INVALID_PARAMETER.

EXAMPLES: ha_set_area_or_floor(kind="area", name="Kitchen") ha_set_area_or_floor(kind="area", id="kitchen", floor_id="ground_floor") ha_set_area_or_floor(kind="floor", name="Basement", level=-1) ha_set_area_or_floor(kind="floor", id="ground_floor", level=0)

ParametersJSON Schema
NameRequiredDescriptionDefault
idNoExisting area_id or floor_id to update (omit to create a new entry; use ha_list_floors_areas to find IDs)
iconNoMaterial Design Icon (e.g., 'mdi:sofa', 'mdi:home-floor-1', empty string to remove)
kindYesWhich registry to operate on: 'area' for rooms, 'floor' for building levels
nameNoName (required when creating; optional when updating, e.g., 'Living Room', 'Ground Floor')
levelNoNumeric level when kind='floor' (0=ground, 1=first, -1=basement). Only valid when kind='floor'.
aliasesNoAlternative names for voice assistant recognition (e.g., ['lounge'], empty list to clear)
pictureNoPicture URL when kind='area' (empty string to remove). Only valid when kind='area'.
floor_idNoFloor assignment when kind='area' (use empty string to clear). Only valid when kind='area'.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations include destructiveHint=true, and the description discloses that the tool creates or updates records, implying overwriting. It also details validation behavior (cross-kind params rejected). However, it does not explicitly mention that updates replace existing data or any side effects.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise yet complete, with a clear structure: purpose statement, parameter rules, and examples. Every sentence provides necessary information with no redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers creation and update for both area and floor, includes cross-kind validation, and provides examples. Since an output schema exists, return values are not required. The description fully addresses the tool's complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so baseline is 3. The description adds value by showing how parameters combine in examples (e.g., floor_id with kind='area'), which clarifies usage beyond individual parameter descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The title and description clearly state the tool creates or updates Home Assistant areas or floors. It distinguishes between the two kinds ('area' vs 'floor') and between create vs update operations, providing a specific verb and resource.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit guidelines for when to use kind='area' vs kind='floor', when to create (provide name) vs update (provide id), and warns that cross-kind parameters are rejected. Examples illustrate common use cases, making usage clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_set_deviceSet DeviceA
Destructive

Update device properties such as name, area, disabled state, or labels.

IMPORTANT: Renaming a device does NOT rename its entities! Device and entity names are independent. To rename entities, use ha_set_entity(new_entity_id=...).

Common workflow for full rename:

  1. ha_set_device(device_id="abc", name="Living Room Sensor") # Rename device

  2. ha_set_entity("sensor.old", new_entity_id="sensor.living_room") # Rename entities separately

PARAMETERS:

  • name: Sets the user-defined display name (name_by_user)

  • area_id: Assigns device to an area/room. Use '' to remove from area.

  • disabled_by: Set to 'user' to disable, or empty to enable

  • labels: List of labels (replaces existing labels)

EXAMPLES:

  • Rename device: ha_set_device("abc123", name="Living Room Hub")

  • Move to area: ha_set_device("abc123", area_id="living_room")

  • Disable device: ha_set_device("abc123", disabled_by="user")

  • Enable device: ha_set_device("abc123", disabled_by="")

  • Add labels: ha_set_device("abc123", labels=["important", "sensor"])

ParametersJSON Schema
NameRequiredDescriptionDefault
nameNoNew display name for the device (sets name_by_user)
labelsNoLabels to assign to the device (replaces existing labels)
area_idNoArea/room ID to assign the device to. Use empty string '' to unassign.
device_idYesDevice ID to update
disabled_byNoSet to 'user' to disable, or None/empty string to enable

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses critical behavioral traits not in annotations: renaming device does not rename entities, labels replace existing ones, and how to disable/enable. Annotations only note destructiveHint=true, but the description adds rich context about the mutation behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is somewhat long but well-structured: purpose statement, important note, workflow, parameter list, examples. It is front-loaded with critical info. Every section is valuable, though could be slightly more concise.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the moderate complexity, annotations (destructiveHint), and presence of output schema, the description covers all necessary aspects: parameters, important caveats, workflow, and examples. It is comprehensive enough for an agent to use correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and each parameter has a description. The narrative description adds value by explaining semantics like 'replaces existing labels' and 'empty string to unassign', and provides examples. This goes beyond the schema but slightly redundant.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description explicitly states 'Update device properties such as name, area, disabled state, or labels.' It clearly distinguishes from sibling tools like ha_get_device (read) and ha_set_entity (entity operations) by noting that renaming a device does not rename entities.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit guidance: it describes a common workflow for full rename combining with ha_set_entity, and explains when to use each parameter (e.g., area_id with '' to unassign). It does not explicitly state when not to use, but the important note serves as a clear alternative.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_set_entitySet EntityA
DestructiveIdempotent

Update entity properties in the entity registry.

Allows modifying entity metadata such as area assignment, display name, icon, "Show As" device class override, per-domain registry options, enabled/disabled state, visibility, aliases, labels, voice assistant exposure, and entity_id rename in a single call.

BULK OPERATIONS: When entity_id is a list, only labels, expose_to, and categories parameters are supported. Other parameters (area_id, name, icon, device_class, options, enabled, hidden, aliases, new_entity_id, new_device_name) require single entity.

LABEL OPERATIONS:

  • label_operation="set" (default): Replace all labels with the provided list. Use [] to clear.

  • label_operation="add": Add labels to existing ones without removing any.

  • label_operation="remove": Remove specified labels from the entity.

SHOW AS / DEVICE CLASS: device_class overrides the entity's display device class โ€” equivalent to the HA UI's "Show As" dropdown. Use empty string '' to clear. Applies instantly, no reload needed.

REGISTRY OPTIONS: options carries per-domain registry options (sensor display_precision, weather forecast_type, etc). Pass {domain: {key: value}}; multi-domain dicts are sent as separate registry updates because HA's WS schema requires options_domain + options to be paired one domain at a time.

ENTITY ID RENAME: Use new_entity_id to change an entity's ID (e.g., sensor.old -> sensor.new). Domain must match. Voice exposure settings are preserved automatically.

WARNING: Renaming an entity_id does NOT update references in automations, scripts, templates, or dashboards. All consumers of the old entity_id must be updated manually โ€” HA does not propagate the rename automatically.

Rename limitations:

  • Entity history is preserved (HA 2022.4+)

  • Entities without unique IDs cannot be renamed

  • Entities disabled by their integration cannot be renamed

DEVICE RENAME: Use new_device_name to rename the associated device. Can be combined with new_entity_id to rename both in one call. The device is looked up automatically.

Use ha_search() or ha_get_device() to find entity IDs. Use ha_config_get_label() to find available label IDs.

EXAMPLES: Single entity:

  • Assign to area: ha_set_entity("sensor.temp", area_id="living_room")

  • Rename display name: ha_set_entity("sensor.temp", name="Living Room Temperature")

  • Set Show As: ha_set_entity("binary_sensor.zone_10", device_class="window")

  • Clear Show As: ha_set_entity("binary_sensor.zone_10", device_class="")

  • Set sensor precision: ha_set_entity("sensor.power", options={"sensor": {"display_precision": 2}})

  • Rename entity_id: ha_set_entity("light.old_name", new_entity_id="light.new_name")

  • Rename entity and device: ha_set_entity("light.old", new_entity_id="light.new", new_device_name="New Lamp")

  • Rename entity_id with friendly name: ha_set_entity("sensor.old", new_entity_id="sensor.new", name="New Name")

  • Set labels: ha_set_entity("light.lamp", labels=["outdoor", "smart"])

  • Add labels: ha_set_entity("light.lamp", labels=["new_label"], label_operation="add")

  • Remove labels: ha_set_entity("light.lamp", labels=["old_label"], label_operation="remove")

  • Clear labels: ha_set_entity("light.lamp", labels=[])

  • Expose to Alexa: ha_set_entity("light.lamp", expose_to={"cloud.alexa": True})

Bulk operations:

  • Set labels on multiple: ha_set_entity(["light.a", "light.b"], labels=["outdoor"])

  • Add labels to multiple: ha_set_entity(["light.a", "light.b"], labels=["new"], label_operation="add")

  • Expose multiple to Alexa: ha_set_entity(["light.a", "light.b"], expose_to={"cloud.alexa": True})

ENABLED/DISABLED WARNING: Setting enabled=False performs a registry-level disable โ€” the entity is completely removed from the Home Assistant state machine and hidden from the UI. It will NOT appear in state queries, dashboards, or automations until re-enabled AND the integration is reloaded. This is NOT the same as "turning off" an entity.

For automations and scripts, enabled=False is blocked. Use these instead:

  • ha_call_service("automation", "turn_off", entity_id="automation.xxx")

  • ha_call_service("script", "turn_off", entity_id="script.xxx")

ParametersJSON Schema
NameRequiredDescriptionDefault
iconNoIcon for the entity (e.g., 'mdi:thermometer'). Use empty string '' to remove custom icon. Single entity only.
nameNoDisplay name for the entity. Use empty string '' to remove custom name and revert to default. Single entity only.
hiddenNoTrue to hide the entity from UI, False to show it. Single entity only.
labelsNoList of label IDs for the entity. Behavior depends on label_operation parameter. Supports bulk operations.
aliasesNoList of voice assistant aliases for the entity (replaces existing aliases). Single entity only.
area_idNoArea/room ID to assign the entity to. Use empty string '' to unassign from current area. Single entity only.
enabledNoTrue to enable the entity, False to disable it. Single entity only. WARNING: Setting enabled=False is a registry-level disable โ€” it completely removes the entity from the state machine and hides it from the UI. A reload or restart is required to restore it after re-enabling. NOT allowed for automation or script entities โ€” use automation.turn_off / script.turn_off via ha_call_service() instead.
optionsNoPer-domain entity registry options (e.g. sensor 'display_precision', weather 'forecast_type'). Pass a dict mapping domain to a sub-dict, e.g. {"sensor": {"display_precision": 2}}. Multiple domains are sent as separate registry updates. For 'Show As' use the dedicated `device_class` parameter โ€” that is what the HA UI Show As dropdown writes. Voice-assistant exposure is stored under `options.<assistant>.should_expose` but must be managed via the dedicated `expose_to` parameter, not this options dict. Single entity only.
entity_idYesEntity ID or list of entity IDs to update. Bulk operations (list) only support labels, expose_to, and categories parameters.
expose_toNoControl voice assistant exposure. Pass a dict mapping assistant IDs to booleans. Valid assistants: 'conversation' (Assist), 'cloud.alexa', 'cloud.google_assistant'. Example: {"conversation": true, "cloud.alexa": false}. Supports bulk operations.
categoriesNoCategory assignment as a dict mapping scope to category_id. Example: {"automation": "category_id_here"}. Use null value to clear: {"automation": null}. Single entity only.
device_classNoOverride the entity's display device class โ€” what the HA UI's 'Show As' dropdown writes. Use empty string '' to clear the override and fall back to the integration default. None (the default) means 'no change' โ€” pass an explicit '' to clear. Single entity only. Examples: 'window', 'door', 'motion' for binary_sensor; 'temperature', 'humidity' for sensor.
new_entity_idNoNew entity ID to rename to (e.g., 'light.new_name'). Domain must match the original. Single entity only.
label_operationNoHow to apply labels: 'set' replaces all labels, 'add' adds to existing, 'remove' removes specified labels.set
new_device_nameNoNew display name for the associated device. If provided, both entity and device are updated in one operation. Single entity only.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations indicate idempotent and destructive hints; the description adds critical behavioral details: enabling/disabling is registry-level (requires reload), rename doesn't update references, label operations semantics, and multi-domain options handling. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well-structured with sections, bullet points, and examples. Front-loaded with a clear summary. Slightly verbose due to many examples, but every section serves a purpose. Could be trimmed slightly, but still very effective.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers all 15 parameters, bulk restrictions, warnings (enabled=False, rename propagation), and cross-references sibling tools. With output schema present, it provides comprehensive context for complex entity registry operations.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 100% schema coverage, the description still adds significant value: explains label_operation enum, device_class 'Show As' usage, options multi-domain handling, expose_to valid assistants, rename limitations, and device rename combination. Goes far beyond schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Update entity properties in the entity registry' and lists specific modifiable aspects (area, name, icon, etc.). It distinguishes from siblings like ha_get_entity (read), ha_remove_entity (delete), and ha_set_device (device-level) by focusing on entity registry properties.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly covers when to use (single vs bulk), when not to use (e.g., enabled=False for automations/scripts, alternatives provided via ha_call_service()), and includes examples for each operation. Clearly differentiates single entity and bulk operations.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_set_integrationSet IntegrationA
Destructive

Manage an integration (config entry): enable/disable, add, update options, or reconfigure.

Modes (pick one):

  • Enable/disable: entry_id + enabled.

  • Add integration: domain (+ config) โ€” drives the domain's config flow, including menus and multi-step forms.

  • Update options: entry_id + config โ€” drives the entry's options flow (what the "Configure" button does in the HA UI). Like that dialog it is a patch: omitted fields keep their current values, and a field set to null is cleared where the integration's schema allows that field to be empty.

  • Reconfigure: entry_id + reconfigure=True + config โ€” drives the existing entry's official reconfigure flow (host, port, credentials). Call it without confirm_token for a read-only preflight; repeat with the token it returns to apply.

WHEN NOT TO USE:

  • Helpers (template, group, utility_meter, ...): use ha_config_set_helper. The exception is otp, which is a helper in the HA UI but is created HERE via domain="otp" โ€” its flow needs a live TOTP code, so ha_config_set_helper deliberately omits it.

  • Config subentries: use ha_config_set_helper(helper_type='config_subentry').

  • Removing an entry: use ha_remove_helpers_integrations.

Use ha_get_integration() to find entry IDs, and ha_get_integration(entry_id=..., include_schema=True) to inspect the options fields before an update. Its supports_reconfigure field tells you whether an entry qualifies for reconfigure=True; only integrations implementing async_step_reconfigure do.

Caveats: adding an integration runs its config flow exactly as the HA UI would (may pair devices, scan the network, create entities). Flows requiring a browser step (OAuth) or an asynchronous provider step error out at that step with a structured error instead of completing. Reconfigure edits the settings a live integration connects with: a wrong host or credential takes it offline, and there is no automatic rollback โ€” the returned rollback metadata describes repeating the official flow by hand with the previous values, which this tool cannot read back. The preflight does not validate config keys against the integration's form; wrong field names surface on the confirm call.

EXAMPLES:

  • Disable: ha_set_integration(entry_id="abc123", enabled=False)

  • Add: ha_set_integration(domain="workday", config={"name": "Workday"})

  • Update options: ha_set_integration(entry_id="abc123", config={"scan_interval": 30})

  • Reconfigure preflight: ha_set_integration(entry_id="abc123", reconfigure=True, config={"host": "10.0.0.5"})

  • Reconfigure apply: repeat that call adding confirm_token="sha256:..."

ParametersJSON Schema
NameRequiredDescriptionDefault
configNoFlow form data. With 'domain': input for the new integration's config flow. With 'entry_id' alone: input for the entry's options flow (updates its options). Updating an existing entry โ€” options or reconfigure โ€” is a patch: a field you omit keeps its current value, and a field set to null is cleared where the integration's schema allows that field to be empty. Multi-step flows consume keys per step. A field two steps declare gets your one value both times; pass step_values={'<step_id>': {'<field>': <value>}} to give a step its own value, or to leave the field out of that step; a LIST of those objects supplies one per encounter when the flow presents a step more than once. Menu steps take 'next_step_id' โ€” a string, or a list of successive selections for flows that present more than one menu (e.g. a menu revisited after each branch, ending in a finish option). The step's data_schema is returned on validation errors so field names can be corrected.
domainNoIntegration domain to add (e.g. 'workday', 'local_calendar') โ€” starts and drives that domain's config flow. Pass the flow's form fields in 'config'.
enabledNoTrue to enable, False to disable the entry. Requires entry_id; mutually exclusive with 'domain' and 'config'.
entry_idNoConfig entry ID of an existing integration (enable/disable and options-update modes). Omit when adding via 'domain'.
reconfigureNoUse the existing config entry's official reconfigure flow (its connection settings) instead of its options flow. Without confirm_token this is a read-only preflight that returns one.
expected_macNoRequires reconfigure=True. MAC or IEEE the entry's device must still report.
confirm_tokenNoRequires reconfigure=True. A token from a reconfigure preflight; applies the change. Any token still matching the entry's current state and the same requested config is accepted, so a token stays valid while nothing moves.
expected_device_idNoRequires reconfigure=True. Device registry ID the entry must still own, before and after the change.
expected_unique_idNoRequires reconfigure=True, AND the ha_mcp_tools custom component: Home Assistant does not expose a config entry's unique_id over its API. Without the component this is rejected โ€” anchor on expected_device_id, expected_mac or expected_entity_ids instead.
expected_entity_idsNoRequires reconfigure=True. Exact entity IDs that must remain associated with the entry.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond destructiveHint=true, the description discloses concrete side effects: adding runs the config flow as the UI would (pairing devices, scanning, creating entities), OAuth/async provider steps fail at that step, and reconfigure can take a live integration offline with no automatic rollback. It also explains the preflight/confirm_token two-call contract, giving the agent accurate behavioral expectations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is structured with clear labeled sections (modes, when not to use, caveats, examples) and front-loads the core action and mode selection before detailed caveats. Despite its length, every section adds operational value rather than repeating schema content.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex 10-parameter tool, the description covers mode selection, scheduling of preflight vs apply, constraints on expected_* fields, failure behavior, and rollback limits. The output schema exists, so return values need not be described; nothing essential to correct invocation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is already 100%, and the description additionally maps parameters to operational modes (entries vs domain vs reconfigure) and patch semantics ('omitted fields keep current values, null clears'). The worked examples clarify how config, entry_id, enabled, reconfigure, and confirm_token combine in real calls.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb-resource pairing ('Manage an integration (config entry)') and immediately enumerates the four distinct modes: enable/disable, add, update options, reconfigure. It also differentiates from sibling tools in 'WHEN NOT TO USE' (ha_config_set_helper, ha_remove_helpers_integrations), so an agent can select it unambiguously.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The 'WHEN NOT TO USE' section explicitly names alternatives for helpers, subentries, and removal, including the otp exception. It gives positive routing guidance ('Use ha_get_integration() to find entry IDs...') and clarifies when reconfigure is available via supports_reconfigure / async_step_reconfigure.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_set_todo_itemSet Todo ItemA
Destructive

Create or update a todo item in Home Assistant.

WITHOUT item parameter (create mode): Creates a new item. summary is required.

WITH item parameter (update mode): Updates an existing item identified by UID or exact name. At least one update field (rename, status, description, due_date, due_datetime) is required.

EXAMPLES:

  • Add item: ha_set_todo_item("todo.shopping_list", summary="Buy milk")

  • Add with description: ha_set_todo_item("todo.shopping_list", summary="Buy milk", description="2% organic")

  • Add with due date: ha_set_todo_item("todo.tasks", summary="Pay bills", due_date="2024-12-31")

  • Complete item: ha_set_todo_item("todo.shopping_list", item="Buy milk", status="completed")

  • Rename item: ha_set_todo_item("todo.tasks", item="Old task", rename="New task name")

  • Update due date: ha_set_todo_item("todo.tasks", item="Pay bills", due_date="2024-12-31")

  • Reopen item: ha_set_todo_item("todo.tasks", item="Task to redo", status="needs_action")

NOTE: Not all todo integrations support all features (description, due dates). The Shopping List integration only supports summary.

ParametersJSON Schema
NameRequiredDescriptionDefault
itemNoExisting item to update - can be the item UID or the exact item summary/name. When provided, operates in update mode. When omitted, creates a new item.
renameNoNew name/summary for an existing item. Only used in update mode.
statusNoItem status: 'completed' to mark done, 'needs_action' to mark incomplete. Only used in update mode.
summaryNoItem text/name. Required when creating a new item. Ignored in update mode โ€” use 'rename' to change the item name.
due_dateNoDue date in YYYY-MM-DD format (e.g., '2024-12-25')
entity_idYesTodo list entity ID (e.g., 'todo.shopping_list')
descriptionNoDetailed description for the item
due_datetimeNoDue datetime in ISO format (e.g., '2024-12-25T14:00:00'). Overrides due_date if both provided.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations include destructiveHint: true, confirming mutation. The description adds details about create/update modes and parameter behaviors but does not disclose potential side effects, permissions required, or reversibility. It provides adequate context beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with clear sections (create mode, update mode, examples, note) and front-loads the main action. While somewhat lengthy due to multiple examples, every sentence adds value and the structure aids readability.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (8 params, two modes), the description covers all key aspects: mode behavior, required/optional params, integration limitations, and examples. With full schema coverage and an output schema present, no return value explanation is needed.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, but the description adds significant value by explaining param relationships (summary vs rename, due_datetime override), mode-switching via 'item', and providing concrete examples that clarify parameter usage beyond the schema definitions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Create or update a todo item in Home Assistant' and distinguishes two modes (create vs update) based on the 'item' parameter, which differentiates it from sibling tools like ha_remove_todo_item and ha_get_todo.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly explains when to use create mode (no item) vs update mode (with item), provides detailed examples for each scenario, and notes limitations across integrations. However, it does not explicitly state when to avoid this tool (e.g., for deletion or listing).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ha_set_zoneSet ZoneA
Destructive

Create or update a Home Assistant zone.

Omit zone_id to create a new zone (name, latitude, longitude required). Provide zone_id to update an existing zone (only specified fields change).

EXAMPLES:

  • Create: ha_set_zone(name="Office", latitude=40.7128, longitude=-74.0060, radius=150, icon="mdi:briefcase")

  • Update name: ha_set_zone(zone_id="abc123", name="New Office")

  • Update radius: ha_set_zone(zone_id="abc123", radius=200)

  • Update location: ha_set_zone(zone_id="abc123", latitude=40.7128, longitude=-74.0060)

Note: The 'home' zone is typically defined in YAML and cannot be modified via this API.

ParametersJSON Schema
NameRequiredDescriptionDefault
iconNoMaterial Design Icon (e.g., 'mdi:briefcase', 'mdi:school')
nameNoDisplay name for the zone (required for create)
radiusNoRadius of the zone in meters (must be > 0, defaults to 100 on create)
passiveNoPassive mode - if True, zone will not trigger enter/exit automations (defaults to False on create)
zone_idNoZone ID to update (omit to create new zone, use ha_get_zone to find IDs)
latitudeNoLatitude coordinate of the zone center (required for create)
longitudeNoLongitude coordinate of the zone center (required for create)

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare destructiveHint: true, and the description confirms modification behavior. It adds specific constraints: only specified fields change on update, defaults for radius and passive on create, and the home zone restriction. This goes beyond the annotation's general destructiveness hint.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise and well-structured: a clear first sentence, followed by bullet-like paragraphs summarizing create vs update, then examples, and a final note. Every sentence adds value, with no redundant information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (create/update, 7 params) and the presence of an output schema, the description is fairly complete. It covers key behavioral aspects, required fields, defaults, and a notable restriction. Lacks details on error handling or edge cases like invalid coordinates, but schema validation likely covers that.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Input schema covers all 7 parameters with descriptions (100% coverage). The description adds semantic value by clarifying which parameters are required for create (name, latitude, longitude) and showing usage via examples. It also states default values (radius 100, passive False) that are not explicitly in the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose as 'Create or update a Home Assistant zone', which is a specific verb+resource. It distinguishes itself from sibling tools like ha_get_zone (read) and ha_remove_zone (delete) by explicitly covering both creation and update operations.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit guidance on when to use each mode: omit zone_id for create, provide for update. It also notes the limitation that the 'home' zone cannot be modified. Examples illustrate typical usage, and it references sibling tool ha_get_zone for finding zone IDs. However, it does not explicitly compare to alternatives like ha_remove_zone for deletion, though that is implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 1 tool updatev8.4.3
    • Changedha_search1 field changed
      • changedInput schema / properties / config_time_budget / anyOf
        Previous value: -[
        -  {
        -    "exclusiveMinimum": 0,
        -    "maximum": 300,
        -    "type": "number"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "maximum": 300,
        +    "minimum": 0.001,
        +    "type": "number"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
  2. 14 tool updatesv8.4.1
    • Changedha_bulk_control13 fields changed
      • addedInput schema / properties / action
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "One device action applied to every resolved leaf."
        +}
      • addedInput schema / properties / dry_run
        Added value: +{
        +  "default": false,
        +  "type": "boolean"
        +}
      • addedInput schema / properties / operations / default
        Added value: +null
      • addedInput schema / properties / operations / description
        Added value: +"Explicit entity operations. Use this or selector, never both. Each item requires exact entity_id and action. Use action='off', not service='turn_off'."
      • changedInput schema / properties / operations / items / additionalProperties
        Previous value: -trueNew value: +false
      • addedInput schema / properties / operations / items / description
        Added value: +"One entity action in a ha_bulk_control request."
      • addedInput schema / properties / operations / items / properties
        Added value: +{
        +  "action": {
        +    "description": "Device action such as 'on', 'off', or 'toggle'. For lights, use 'off' instead of the ha_call_service form 'turn_off'.",
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "entity_id": {
        +    "description": "Exact Home Assistant entity ID, e.g. 'light.kitchen'.",
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "parameters": {
        +    "additionalProperties": true,
        +    "description": "Optional action parameters, e.g. {'brightness_pct': 30} when action='on'. Each domain has a fixed allowlist of supported keys; keys outside it are ignored rather than rejected. Use ha_call_service for parameters this tool does not carry.",
        +    "type": "object"
        +  },
        +  "timeout_seconds": {
        +    "description": "Optional confirmation timeout. On the component path, all operations share the maximum requested wait (default 10s, capped at 60s); 0 disables confirmation waiting.",
        +    "minimum": 0,
        +    "type": "number"
        +  },
        +  "validate_first": {
        +    "description": "Report an ENTITY_NOT_FOUND failure when the target entity does not exist; default true. On the component batch path this is detected from the captured pre-state rather than by preventing dispatch. The action is always validated.",
        +    "type": "boolean"
        +  }
        +}
      • addedInput schema / properties / operations / items / required
        Added value: +[
        +  "entity_id",
        +  "action"
        +]
      • addedInput schema / properties / parameters
        Added value: +{
        +  "anyOf": [
        +    {
        +      "additionalProperties": true,
        +      "type": "object"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Optional action parameters for selector mode."
        +}
      • addedInput schema / properties / selector
        Added value: +{
        +  "anyOf": [
        +    {
        +      "additionalProperties": false,
        +      "description": "Exact structural scope for one deterministic bulk action.\n\nLives here (not in ``tools_service.py``) so ``_SELECTOR_KEYS`` below can\nderive from this single field set instead of duplicating it as an\nindependent literal -- the import direction (``tools_service`` already\nimports from this module) makes that safe without a cycle.",
        +      "properties": {
        +        "area_ids": {
        +          "description": "Exact Home Assistant area IDs to include.",
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        },
        +        "domain": {
        +          "description": "Exact Home Assistant domain, e.g. 'light'.",
        +          "type": "string"
        +        },
        +        "exclude_entity_ids": {
        +          "description": "Exact entity or aggregate IDs to exclude after recursive membership expansion.",
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        },
        +        "floor_ids": {
        +          "description": "Exact Home Assistant floor IDs to include.",
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        }
        +      },
        +      "required": [
        +        "domain"
        +      ],
        +      "type": "object"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Optional exact structural scope using domain plus area_ids and/or floor_ids, with optional exclude_entity_ids."
        +}
      • addedInput schema / properties / timeout_seconds
        Added value: +{
        +  "anyOf": [
        +    {
        +      "maximum": 60,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null
        +}
      • addedInput schema / properties / validate_first
        Added value: +{
        +  "default": true,
        +  "type": "boolean"
        +}
      • removedInput schema / required
        Removed value: -[
        -  "operations"
        -]
    • Changedha_call_service6 fields changed
      • addedInput schema / properties / data / description
        Added value: +"Extra service-call parameters beyond entity_id (e.g. {'temperature': 22} for climate.set_temperature). Also carries the raw command payload when ws_command is set. If entity_id is also present in data, the entity_id parameter wins."
      • addedInput schema / properties / domain / description
        Added value: +"Service domain (e.g. 'light', 'climate', 'automation'). Required for a service call; must be omitted when ws_command is set."
      • addedInput schema / properties / entity_id / description
        Added value: +"Entity ID(s) the service call targets โ€” one ID ('light.living_room') or several comma-separated ('light.a,light.b'). Optional for services that don't target a specific entity. Must be omitted when ws_command is set."
      • addedInput schema / properties / return_response / description
        Added value: +"If True, the service's response data is returned once, as the top-level 'service_response' key โ€” never nested inside 'result' (default: False). Must stay False when ws_command is set."
      • addedInput schema / properties / service / description
        Added value: +"Service name within domain (e.g. 'turn_on', 'set_temperature', 'trigger'). Required for a service call; must be omitted when ws_command is set."
      • addedInput schema / properties / wait / description
        Added value: +"If True (default), wait for the entity state to change before returning. Applies only to state-changing services called with a single entity_id. A comma-separated multi-target does not get confirmed by this: it falls through to a legacy path that polls for the literal composite entity_id and times out after 10s. Set wait=False for multi-target calls."
    • Changedha_config_get_dashboard1 field changed
      • changedInput schema / properties / include_screenshot / description
        Previous value: -"Get mode only: also return rendered image(s) of the dashboard for visual verification. Requires the 'dashboard screenshot' beta feature + engine add-on/sidecar. If the feature is disabled the config is returned with a warning; if the engine is configured but the render fails, the call errors (the screenshot is the requested payload). Ignored in list/search mode."New value: +"Get mode only: also return rendered image(s) of the dashboard for visual verification. Requires the 'dashboard screenshot' beta feature + engine add-on/sidecar. If the feature is disabled the config is returned with a warning; if the engine is configured but the render fails, the call errors (the screenshot is the requested payload). Ignored in list/search mode. When you already have the config and only need the render, use the dedicated ha_get_dashboard_screenshot tool (registered when the same beta feature is on) โ€” it returns images without echoing the config."
    • Changedha_config_set_dashboard1 field changed
      • changedInput schema / properties / return_screenshot / description
        Previous value: -"After writing, also return rendered image(s) of the dashboard so you can see what it looks like in a single call (the dashboard creation/iteration loop). Requires the 'dashboard screenshot' beta feature + engine add-on/sidecar; if unavailable, the write result is returned with a warning."New value: +"After writing, also return rendered image(s) of the dashboard so you can see what it looks like in a single call (the dashboard creation/iteration loop). Requires the 'dashboard screenshot' beta feature + engine add-on/sidecar; if unavailable, the write result is returned with a warning. For visual re-checks after the write (no config round-trip), use the dedicated ha_get_dashboard_screenshot tool instead."
    • Changedha_config_set_helper1 field changed
      • changedInput schema / properties / config / description
        Previous value: -"Config dict for flow-based helper types and helper_type='config_subentry' (template, group, utility_meter, derivative, min_max, threshold, integration, statistics, trend, random, filter, tod, generic_thermostat, switch_as_x, generic_hygrostat, history_stats, mold_indicator). Ignored for simple helper types. Field set is delivered as data_schema on the first validation error."New value: +"Config dict for flow-based helper types and helper_type='config_subentry' (template, group, utility_meter, derivative, min_max, threshold, integration, statistics, trend, random, filter, tod, generic_thermostat, switch_as_x, generic_hygrostat, history_stats, mold_indicator). Ignored for simple helper types. On update it is a patch: a field you omit keeps its current value, and a field set to null is cleared where the schema allows that field to be empty. A field two steps declare gets your one value both times; pass step_values={'<step_id>': {'<field>': <value>}} to give a step its own value, or to leave it out of that step; a LIST of those objects supplies one per encounter when the flow presents a step more than once. Field set is delivered as data_schema on the first validation error."
    • Changedha_get_app3 fields changed
      • changedInput schema / properties / query / description
        Previous value: -"Search filter for add-on names/descriptions (only for source='available')"New value: +"App (add-on) name/description filter (only for source='available')"
      • changedInput schema / properties / slug / description
        Previous value: -"Add-on slug for detailed info (e.g., '<prefix>_nodered'). Slug prefixes vary by add-on repository โ€” omit to list all add-ons and discover the actual installed slug."New value: +"App (add-on) slug for detailed info (e.g., '<prefix>_nodered'). Slug prefixes vary by app repository โ€” omit to list all apps and discover the actual installed slug."
      • changedInput schema / properties / source / description
        Previous value: -"Add-on source: 'installed' (default) for currently installed add-ons, 'available' for add-ons in the store that can be installed."New value: +"App (add-on) source: 'installed' (default) for currently installed apps, 'available' for apps in the store that can be installed."
    • Changedha_get_logs1 field changed
      • addedInput schema / properties / offset / description
        Added value: +"Page deeper into source='logbook' and source='error_log' (ignored for other sources). On error_log it counts raw log lines back from the newest entry; pass the response's 'next_offset' to continue while 'has_more' is true."
    • Changedha_get_operation_status2 fields changed
      • addedInput schema / properties / timeout_seconds / minimum
        Added value: +0
      • changedInput schema / properties / timeout_seconds / type
        Previous value: -"integer"New value: +"number"
    • Changedha_get_overview1 field changed
      • changedInput schema / properties / fields / description
        Previous value: -"Return only the specified top-level response keys to reduce response size (e.g. [\"system_info\", \"domains\"]). None = full response (default). Available keys: success, system_summary, domain_stats, area_analysis, ai_insights, pagination, partial, warnings, device_types, service_availability, system_info, notification_count, notifications, repair_count, dismissed_repair_count, repairs, repairs_error, tool_discovery, settings_url, settings_url_hint, read_only_mode, read_only_mode_hint, ha_mcp_update. Note: ``settings_url`` (stdio mode), ``settings_url_hint`` (HTTP/Docker/OAuth mode), the ``read_only_mode`` / ``read_only_mode_hint`` pair (only while Read Only Mode is on), and ``ha_mcp_update`` (when an update check applies) are emitted regardless of ``fields=`` projection so the settings page, the active mode, and a newer ha-mcp release stay discoverable; see the tool description."New value: +"Return only the specified top-level response keys to reduce response size (e.g. [\"system_info\", \"domains\"]). None = full response (default). Available keys: success, system_summary, domain_stats, area_analysis, ai_insights, pagination, partial, warnings, device_types, service_availability, system_info, notification_count, notifications, repair_count, dismissed_repair_count, repairs, repairs_error, tool_discovery, settings_url, settings_url_hint, read_only_mode, read_only_mode_hint, ha_mcp_update. Note: ``settings_url`` (stdio mode), ``settings_url_hint`` (standalone HTTP/Docker mode), the ``read_only_mode`` / ``read_only_mode_hint`` pair (only while Read Only Mode is on), and ``ha_mcp_update`` (when an update check applies) are emitted regardless of ``fields=`` projection so the settings page, the active mode, and a newer ha-mcp release stay discoverable; see the tool description."
    • Changedha_manage_app12 fields changed
      • changedInput schema / properties / action / description
        Previous value: -"Lifecycle mode: run a Supervisor add-on action. One of 'install', 'uninstall', 'start', 'stop', 'restart', 'rebuild', 'update'. 'install'/'update' require the add-on's repository to be registered (it appears in ha_get_app(source='available')). Store-repository mode: 'add_repository' / 'remove_repository' register or unregister a custom add-on store repository โ€” these use the 'repository' param instead of 'slug'. Mutually exclusive with path / config parameters / array_patch. HA OS / Supervised only."New value: +"Lifecycle mode: run a Supervisor app (add-on) action. One of 'install', 'uninstall', 'start', 'stop', 'restart', 'rebuild', 'update'. 'install'/'update' require the app's repository to be registered (it appears in ha_get_app(source='available')). Store-repository mode: 'add_repository' / 'remove_repository' register or unregister a custom app store repository โ€” these use the 'repository' param instead of 'slug'. When ha-mcp runs as an app, it can update other apps but cannot update its own running slug; update ha-mcp from the Home Assistant Apps UI. Mutually exclusive with path / config parameters / array_patch. HA OS / Supervised only."
      • changedInput schema / properties / array_patch / description
        Previous value: -"Array-patch mode: atomically GET a JSON array endpoint, apply ordered ops, then POST the mutated array back. Requires 'path'; mutually exclusive with body / websocket / offset / limit and config params. See the docstring Examples and ha_get_skill_guide for op shapes."New value: +"Array-patch mode: atomically GET a JSON array endpoint, apply ordered ops, then POST the mutated array back. Requires 'path'; mutually exclusive with body / websocket / offset / limit and config params. Use ha_get_skill_guide for operation shapes."
      • changedInput schema / properties / auto_update / description
        Previous value: -"Config mode: Enable or disable automatic updates for this add-on."New value: +"Config mode: Enable or disable automatic updates for this app (add-on)."
      • changedInput schema / properties / network / description
        Previous value: -"Config mode: Host port mappings (e.g., {'5800/tcp': 8081})."New value: +"Config mode: Complete desired host-port override map (e.g., {'5800/tcp': 8081}). A non-empty map replaces current overrides, so omitted entries are cleared. Omit 'network' to leave mappings unchanged. An empty map is ignored and does not by itself select config mode."
      • changedInput schema / properties / options / description
        Previous value: -"Config mode: Add-on configuration values (the 'Configuration' tab in the UI)."New value: +"Config mode: App (add-on) configuration values (the 'Configuration' tab in the UI)."
      • changedInput schema / properties / path / description
        Previous value: -"Proxy mode: API path relative to the add-on root (e.g., '/flows', '/api/events', '/api/stats'). Required for proxy mode; mutually exclusive with config parameters."New value: +"Proxy mode: API path relative to the app (add-on) root (e.g., '/flows', '/api/events', '/api/stats'). Required for proxy mode; mutually exclusive with config parameters."
      • changedInput schema / properties / port / description
        Previous value: -"Proxy mode only. Connect to this port instead of the Ingress port. Use ha_get_app(slug='...') to find available ports."New value: +"Proxy mode only. Connect to this port instead of the Ingress port. Use ha_get_app(slug='...') to find available ports. Some apps, including Node-RED, reject direct access unless their leave_front_door_open option is enabled and the app is restarted; related errors include an actionable, security-qualified ha_manage_app options command."
      • changedInput schema / properties / repository / description
        Previous value: -"Store-repository mode only (action='add_repository' or 'remove_repository'). For add_repository: the repository URL (e.g., 'https://github.com/balloob/home-assistant-addons'). For remove_repository: the repository slug (e.g., '0f1cc410', as shown in ha_get_app(source='available')). Required for those actions; ignored otherwise."New value: +"Store-repository mode only (action='add_repository' or 'remove_repository'). For add_repository: the repository URL (e.g., 'https://github.com/balloob/home-assistant-addons'). For remove_repository: the repository slug (e.g., '0f1cc410', as shown in ha_get_app(source='available')). Required for those actions; rejected otherwise."
      • changedInput schema / properties / request_headers / description
        Previous value: -"Proxy/array-patch mode: extra HTTP headers to send to the addon API. Useful for addon-specific requirements such as Node-RED's `Node-RED-Deployment-Type: full`. The proxy's internal framing (`X-Ingress-Path`, `X-Hass-Source`, `Cookie`, `Content-Type`) is layered on top, so caller-supplied values for those keys are overridden. Not valid in config or websocket mode."New value: +"Proxy/array-patch mode: extra HTTP headers for the app (add-on) API. Useful for app-specific requirements such as Node-RED's `Node-RED-Deployment-Type: full`. Ingress routing headers override caller values on Ingress routes; direct-port calls have no internal routing headers. `Content-Type` is derived from the body when supplied. Not valid in config or websocket mode."
      • changedInput schema / properties / slug / description
        Previous value: -"Add-on slug (e.g., '<prefix>_nodered', '<prefix>_frigate'). Slug prefixes vary by add-on repository โ€” call ha_get_app() to discover the actual installed slug. Required for every mode except the store-repository actions (action='add_repository'/'remove_repository'), which use 'repository' instead and take no slug."New value: +"App (add-on) slug (e.g., '<prefix>_nodered', '<prefix>_frigate'). Slug prefixes vary by app repository โ€” call ha_get_app() to discover the actual installed slug. Required for every mode except the store-repository actions (action='add_repository'/'remove_repository'), which use 'repository' instead and take no slug."
      • changedInput schema / properties / wait_for_close / description
        Previous value: -"Proxy mode only. WebSocket: True: wait for the server to close the stream (run-to-completion ops like an ESPHome compile/validate). False: return after the first response batch โ€” use for a one-shot command/response or a bounded log capture on a channel that stays open (e.g. ESPHome '/ws'). Default: true."New value: +"Proxy mode only. WebSocket: True waits for the server to close a run-to-completion stream. False returns after the first response batch; use for one-shot command/response or bounded capture on a channel that stays open. Default: true."
      • changedInput schema / properties / websocket / description
        Previous value: -"Proxy mode only. Use WebSocket instead of HTTP โ€” for an add-on's WebSocket API (e.g. the ESPHome dashboard's '/ws' command channel; see the docstring's ESPHome section). Sends 'body' as the initial message, collects responses. Default: false."New value: +"Proxy mode only. Use WebSocket instead of HTTP for an app (add-on) WebSocket API. Sends 'body' as the initial message and collects responses; command names and body schemas are app/version-specific. Default: false."
    • Changedha_manage_backup2 fields changed
      • changedInput schema / properties / domain / description
        Previous value: -"(edits.list / edits.delete) Filter auto-backups by domain (e.g. 'automation', 'helper_timer')."New value: +"(edits.create / edits.list / edits.delete) Filter auto-backups by domain (e.g. 'automation', 'helper_timer'). Required for edits.create."
      • changedInput schema / properties / entity_id / description
        Previous value: -"(edits.list / edits.delete) Filter auto-backups by entity ID."New value: +"(edits.create / edits.list / edits.delete) Filter auto-backups by entity ID. Required for edits.create."
    • Changedha_manage_theme5 fields changed
      • changedInput schema / properties / action / description
        Previous value: -"Theme operation: list installed themes or set the default theme."New value: +"Theme operation: 'list' installed themes, 'set' the backend default theme, or read/restore the screenshot engine account's own per-user theme with 'get_engine_theme' / 'set_engine_theme' (a different layer from the backend default)."
      • changedInput schema / properties / action / enum
        Previous value: -[
        -  "list",
        -  "set"
        -]New value: +[
        +  "list",
        +  "set",
        +  "get_engine_theme",
        +  "set_engine_theme"
        +]
      • addedInput schema / properties / expected_current
        Added value: +{
        +  "anyOf": [
        +    {
        +      "additionalProperties": true,
        +      "type": "object"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Guard for action='set_engine_theme': the stored theme is read immediately before the write and the write is skipped if it no longer equals this. Omitting this value or passing null both mean 'expect no stored theme', enforced like any other value; the guard is always applied unless force is set. Best-effort, not atomic -- Home Assistant exposes no conditional write, so a change landing between that read and the write is not caught. Pass the expected_current value quoted in the screenshot tool's warning."
        +}
      • addedInput schema / properties / force
        Added value: +{
        +  "default": false,
        +  "description": "action='set_engine_theme' only: skip the expected_current guard and overwrite unconditionally. Leave false unless you intend to discard whatever is stored.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / value
        Added value: +{
        +  "anyOf": [
        +    {
        +      "additionalProperties": true,
        +      "type": "object"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Frontend user-data theme object when action='set_engine_theme', e.g. {'theme': '', 'dark': False}. An empty dict restores default/auto behavior. Take this verbatim from the warning a screenshot tool emitted."
        +}
    • Changedha_search4 fields changed
      • changedInput schema / properties / area_filter / description
        Previous value: -"Narrow entity-registry results to an area (id or name). Does not affect configuration search."New value: +"Narrow entity-registry results to an area (id, name, or alias), an exact floor (id, name, or alias), or an unambiguous close-spelling floor match; a floor match expands to all areas on that floor. Does not affect configuration search."
      • changedInput schema / properties / config_time_budget / description
        Previous value: -"Per-call override for the per-id config-fetch wall-clock budget (seconds). Replaces the per-type HAMCP_*_CONFIG_TIME_BUDGET defaults for the automation, script, AND scene branches when their bulk-fetch falls through to per-id Attempt-C. Use when a `partial: True` response names time-budget skipping. Stateless per-call: one caller raising the budget doesn't affect others. None = use the per-type env defaults."New value: +"Per-call override for the per-id config-fetch wall-clock budget (seconds). Replaces the per-type HAMCP_*_CONFIG_TIME_BUDGET defaults for the automation, script, AND scene branches. Use when a `partial: True` response names time-budget skipping. Stateless per-call: one caller raising the budget doesn't affect others. None = use the per-type env defaults."
      • changedInput schema / properties / query / description
        Previous value: -"What to search for (entity name fragment, free-text config term, entity_id). Searches BOTH the entity registry (entity_ids, friendly names, areas) AND configuration bodies (automation triggers/actions, script sequences, scene contents, helper bodies, dashboard cards) in one call. Use this for any find-something-in-HA question โ€” entity OR config. Omit `query` to enumerate by `domain_filter`, `area_filter`, and/or `state_filter` alone (registry-listing mode); configuration-body search is skipped in that mode because there is no term to match against."New value: +"What to search for (entity name fragment, free-text config term, entity_id). Searches BOTH the entity registry (entity_ids, friendly names, areas) AND configuration bodies (automation triggers/actions, script sequences, scene contents, helper bodies, dashboard cards) in one call. Use this for any find-something-in-HA question โ€” entity OR config. Pass the exact entity_id, not a name fragment, when checking what a rename or delete would break: that form reports automations, scripts and scenes referencing it even when their configuration could not be read. Omit `query` to enumerate by `domain_filter`, `area_filter`, and/or `state_filter` alone (registry-listing mode); configuration-body search is skipped in that mode because there is no term to match against."
      • changedInput schema / properties / result_fields / description
        Previous value: -"Project each entity-registry record to only the specified keys (e.g. [\"entity_id\", \"state\"]). None = full records. Base keys: entity_id, friendly_name, domain, state, score, match_type. Opt-in enrichment keys (joined on request): area, floor, labels, aliases. An unknown key is rejected."New value: +"Project each entity-registry record to only the specified keys (e.g. [\"entity_id\", \"state\"]). None = full records. Base keys: entity_id, friendly_name, domain, state, score, match_type. Opt-in enrichment/membership keys (computed on request): area, floor, labels, aliases, is_group, member_entity_ids. Membership is recognized only when HA explicitly exposes a valid group_entities or legacy entity_id collection; member IDs are sorted, direct (not recursively expanded), and omitted if visibility/include_hidden excludes a member. is_group remains true when member IDs are withheld; requesting member_entity_ids also retains is_group. An unknown key is rejected."
    • Changedha_set_integration1 field changed
      • changedInput schema / properties / config / description
        Previous value: -"Flow form data. With 'domain': input for the new integration's config flow. With 'entry_id' alone: input for the entry's options flow (updates its options). Multi-step flows consume keys per step; menu steps take 'next_step_id' โ€” a string, or a list of successive selections for flows that present more than one menu (e.g. a menu revisited after each branch, ending in a finish option). The step's data_schema is returned on validation errors so field names can be corrected."New value: +"Flow form data. With 'domain': input for the new integration's config flow. With 'entry_id' alone: input for the entry's options flow (updates its options). Updating an existing entry โ€” options or reconfigure โ€” is a patch: a field you omit keeps its current value, and a field set to null is cleared where the integration's schema allows that field to be empty. Multi-step flows consume keys per step. A field two steps declare gets your one value both times; pass step_values={'<step_id>': {'<field>': <value>}} to give a step its own value, or to leave the field out of that step; a LIST of those objects supplies one per encounter when the flow presents a step more than once. Menu steps take 'next_step_id' โ€” a string, or a list of successive selections for flows that present more than one menu (e.g. a menu revisited after each branch, ending in a finish option). The step's data_schema is returned on validation errors so field names can be corrected."
  3. 10 tool updatesv8.3.0
    • Changedha_config_list_helpers1 field changed
      • changedInput schema / properties / helper_type / anyOf
        Previous value: -[
        -  {
        -    "enum": [
        -      "input_button",
        -      "input_boolean",
        -      "input_select",
        -      "input_number",
        -      "input_text",
        -      "input_datetime",
        -      "counter",
        -      "timer",
        -      "schedule",
        -      "zone",
        -      "person",
        -      "tag",
        -      "all"
        -    ],
        -    "type": "string"
        -  },
        -  {
        -    "enum": [
        -      "template",
        -      "group",
        -      "utility_meter",
        -      "derivative",
        -      "min_max",
        -      "threshold",
        -      "integration",
        -      "statistics",
        -      "trend",
        -      "random",
        -      "filter",
        -      "tod",
        -      "generic_thermostat",
        -      "switch_as_x",
        -      "generic_hygrostat"
        -    ],
        -    "type": "string"
        -  }
        -]New value: +[
        +  {
        +    "enum": [
        +      "input_button",
        +      "input_boolean",
        +      "input_select",
        +      "input_number",
        +      "input_text",
        +      "input_datetime",
        +      "counter",
        +      "timer",
        +      "schedule",
        +      "zone",
        +      "person",
        +      "tag",
        +      "all"
        +    ],
        +    "type": "string"
        +  },
        +  {
        +    "enum": [
        +      "template",
        +      "group",
        +      "utility_meter",
        +      "derivative",
        +      "min_max",
        +      "threshold",
        +      "integration",
        +      "statistics",
        +      "trend",
        +      "random",
        +      "filter",
        +      "tod",
        +      "generic_thermostat",
        +      "switch_as_x",
        +      "generic_hygrostat",
        +      "history_stats",
        +      "mold_indicator"
        +    ],
        +    "type": "string"
        +  }
        +]
    • Changedha_config_set_helper2 fields changed
      • changedInput schema / properties / config / description
        Previous value: -"Config dict for flow-based helper types and helper_type='config_subentry' (template, group, utility_meter, derivative, min_max, threshold, integration, statistics, trend, random, filter, tod, generic_thermostat, switch_as_x, generic_hygrostat). Ignored for simple helper types. Field set is delivered as data_schema on the first validation error."New value: +"Config dict for flow-based helper types and helper_type='config_subentry' (template, group, utility_meter, derivative, min_max, threshold, integration, statistics, trend, random, filter, tod, generic_thermostat, switch_as_x, generic_hygrostat, history_stats, mold_indicator). Ignored for simple helper types. Field set is delivered as data_schema on the first validation error."
      • changedInput schema / properties / helper_type / enum
        Previous value: -[
        -  "counter",
        -  "config_subentry",
        -  "derivative",
        -  "filter",
        -  "generic_hygrostat",
        -  "generic_thermostat",
        -  "group",
        -  "input_boolean",
        -  "input_button",
        -  "input_datetime",
        -  "input_number",
        -  "input_select",
        -  "input_text",
        -  "integration",
        -  "min_max",
        -  "person",
        -  "random",
        -  "schedule",
        -  "statistics",
        -  "switch_as_x",
        -  "tag",
        -  "template",
        -  "threshold",
        -  "timer",
        -  "tod",
        -  "trend",
        -  "utility_meter",
        -  "zone"
        -]New value: +[
        +  "counter",
        +  "config_subentry",
        +  "derivative",
        +  "filter",
        +  "generic_hygrostat",
        +  "generic_thermostat",
        +  "group",
        +  "history_stats",
        +  "input_boolean",
        +  "input_button",
        +  "input_datetime",
        +  "input_number",
        +  "input_select",
        +  "input_text",
        +  "integration",
        +  "min_max",
        +  "mold_indicator",
        +  "person",
        +  "random",
        +  "schedule",
        +  "statistics",
        +  "switch_as_x",
        +  "tag",
        +  "template",
        +  "threshold",
        +  "timer",
        +  "tod",
        +  "trend",
        +  "utility_meter",
        +  "zone"
        +]
    • Removedha_get_addon
    • Addedha_get_app
    • Changedha_get_logs3 fields changed
      • changedInput schema / properties / order / description
        Previous value: -"Sort order for time-ordered sources (logbook, system, error_log, supervisor, system_service): 'newest' (default) returns most-recent first; 'oldest' returns chronological-first. Ignored for source='logger'."New value: +"Sort order for time-ordered sources (logbook, system, error_log, supervisor, system_service): 'newest' (default) returns most-recent first; 'oldest' returns chronological-first. Ignored for source='logger', and for source='error_log' with structured=True (that summary is ranked by occurrence count, not by time)."
      • addedInput schema / properties / structured
        Added value: +{
        +  "default": false,
        +  "description": "source='error_log' only. When True, return a deduplicated, component-grouped summary of the log (counted issues sorted by frequency) instead of raw text. Use this on busy instances where the raw log is large enough to exhaust context. Ignored for other sources.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / top_n
        Added value: +{
        +  "anyOf": [
        +    {
        +      "minimum": 1,
        +      "type": "integer"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Max distinct issues to return when structured=True (default 20, capped at 500). Bounds the response regardless of log size."
        +}
    • Removedha_manage_addon
    • Addedha_manage_app
    • Changedha_manage_pipeline7 fields changed
      • changedInput schema / properties / action / description
        Previous value: -"Pipeline operation: list, get, create, update, or set_preferred."New value: +"Pipeline operation: list, get, create, update, set_preferred, or process."
      • changedInput schema / properties / action / enum
        Previous value: -[
        -  "list",
        -  "get",
        -  "create",
        -  "update",
        -  "set_preferred"
        -]New value: +[
        +  "list",
        +  "get",
        +  "create",
        +  "update",
        +  "set_preferred",
        +  "process"
        +]
      • addedInput schema / properties / agent_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "For process only, the conversation agent entity ID to answer, e.g. 'conversation.home_assistant'. Overrides the agent taken from pipeline_id; omit both for the default agent."
        +}
      • addedInput schema / properties / conversation_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "For process only, the conversation to continue. Returned in the response so follow-up sentences keep their context."
        +}
      • changedInput schema / properties / language / description
        Previous value: -"Pipeline language, e.g. 'en'."New value: +"Pipeline language, e.g. 'en'. For process, the language to recognise the sentence in."
      • changedInput schema / properties / pipeline_id / description
        Previous value: -"Assist pipeline ID. Required for get, update, and set_preferred."New value: +"Assist pipeline ID. Required for get, update, and set_preferred. Optional for process, where it selects the conversation agent and language that pipeline is configured with."
      • addedInput schema / properties / sentence
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Natural-language command to run through Assist. Required when action='process'. A matched intent executes, and with the built-in agent a sentence matching a conversation trigger runs that automation."
        +}
    • Changedha_remove_helpers_integrations1 field changed
      • changedInput schema / properties / helper_type / anyOf
        Previous value: -[
        -  {
        -    "enum": [
        -      "input_button",
        -      "input_boolean",
        -      "input_select",
        -      "input_number",
        -      "input_text",
        -      "input_datetime",
        -      "counter",
        -      "timer",
        -      "schedule",
        -      "zone",
        -      "person",
        -      "tag",
        -      "config_subentry",
        -      "template",
        -      "group",
        -      "utility_meter",
        -      "derivative",
        -      "min_max",
        -      "threshold",
        -      "integration",
        -      "statistics",
        -      "trend",
        -      "random",
        -      "filter",
        -      "tod",
        -      "generic_thermostat",
        -      "switch_as_x",
        -      "generic_hygrostat"
        -    ],
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "enum": [
        +      "input_button",
        +      "input_boolean",
        +      "input_select",
        +      "input_number",
        +      "input_text",
        +      "input_datetime",
        +      "counter",
        +      "timer",
        +      "schedule",
        +      "zone",
        +      "person",
        +      "tag",
        +      "config_subentry",
        +      "template",
        +      "group",
        +      "utility_meter",
        +      "derivative",
        +      "min_max",
        +      "threshold",
        +      "integration",
        +      "statistics",
        +      "trend",
        +      "random",
        +      "filter",
        +      "tod",
        +      "generic_thermostat",
        +      "switch_as_x",
        +      "generic_hygrostat",
        +      "history_stats",
        +      "mold_indicator"
        +    ],
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
    • Changedha_set_integration6 fields changed
      • addedInput schema / properties / confirm_token
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Requires reconfigure=True. A token from a reconfigure preflight; applies the change. Any token still matching the entry's current state and the same requested config is accepted, so a token stays valid while nothing moves."
        +}
      • addedInput schema / properties / expected_device_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Requires reconfigure=True. Device registry ID the entry must still own, before and after the change."
        +}
      • addedInput schema / properties / expected_entity_ids
        Added value: +{
        +  "anyOf": [
        +    {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Requires reconfigure=True. Exact entity IDs that must remain associated with the entry."
        +}
      • addedInput schema / properties / expected_mac
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Requires reconfigure=True. MAC or IEEE the entry's device must still report."
        +}
      • addedInput schema / properties / expected_unique_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Requires reconfigure=True, AND the ha_mcp_tools custom component: Home Assistant does not expose a config entry's unique_id over its API. Without the component this is rejected โ€” anchor on expected_device_id, expected_mac or expected_entity_ids instead."
        +}
      • addedInput schema / properties / reconfigure
        Added value: +{
        +  "default": false,
        +  "description": "Use the existing config entry's official reconfigure flow (its connection settings) instead of its options flow. Without confirm_token this is a read-only preflight that returns one.",
        +  "type": "boolean"
        +}
  4. 3 tool updatesv8.2.0
    • Changedha_call_service1 field changed
      • changedInput schema / properties / verbose / description
        Previous value: -"Return HA's raw service response unchanged (default: False). Use as an escape hatch when you need the full propagation chain or raw attribute payload (debug / inspection). WARNING: brings back token-bloat for nested-group targets โ€” prefer result_fields / result_attribute_keys for targeted control."New value: +"Return HA's raw changed-state records unchanged (default: False). Use as an escape hatch when you need the full propagation chain or raw attribute payload (debug / inspection). With return_response=True the response data still surfaces once as the top-level service_response key, never nested in result. WARNING: brings back token-bloat for nested-group targets โ€” prefer result_fields / result_attribute_keys for targeted control."
    • Changedha_manage_hacs3 fields changed
      • changedInput schema / properties / action / description
        Previous value: -"'download' to install/update, or 'add_repository'"New value: +"'download' to install/update, 'add_repository' to register a custom repo, 'remove' to uninstall a downloaded repo, or 'update_information' to refresh a repository's release data from GitHub"
      • changedInput schema / properties / action / enum
        Previous value: -[
        -  "download",
        -  "add_repository"
        -]New value: +[
        +  "download",
        +  "add_repository",
        +  "remove",
        +  "update_information"
        +]
      • changedInput schema / properties / repository_id / description
        Previous value: -"Numeric HACS ID or 'owner/repo' path (action='download')"New value: +"Numeric HACS ID or 'owner/repo' path (action='download' / 'remove' / 'update_information')"
    • Changedha_set_integration1 field changed
      • changedInput schema / properties / config / description
        Previous value: -"Flow form data. With 'domain': input for the new integration's config flow. With 'entry_id' alone: input for the entry's options flow (updates its options). Multi-step flows consume keys per step; menu steps take 'next_step_id'. The step's data_schema is returned on validation errors so field names can be corrected."New value: +"Flow form data. With 'domain': input for the new integration's config flow. With 'entry_id' alone: input for the entry's options flow (updates its options). Multi-step flows consume keys per step; menu steps take 'next_step_id' โ€” a string, or a list of successive selections for flows that present more than one menu (e.g. a menu revisited after each branch, ending in a finish option). The step's data_schema is returned on validation errors so field names can be corrected."
  5. 78 tool updatesv7.14.2
    • First observedha_bulk_control
    • First observedha_call_event
    • First observedha_call_service
    • First observedha_config_delete_dashboard
    • First observedha_config_delete_dashboard_resource
    • First observedha_config_get_automation
    • First observedha_config_get_calendar_events
    • First observedha_config_get_category
    • First observedha_config_get_dashboard
    • First observedha_config_get_label
    • First observedha_config_get_scene
    • First observedha_config_get_script
    • First observedha_config_list_dashboard_resources
    • First observedha_config_list_groups
    • First observedha_config_list_helpers
    • First observedha_config_remove_automation
    • First observedha_config_remove_calendar_event
    • First observedha_config_remove_category
    • First observedha_config_remove_group
    • First observedha_config_remove_label
    • First observedha_config_remove_scene
    • First observedha_config_remove_script
    • First observedha_config_set_automation
    • First observedha_config_set_calendar_event
    • First observedha_config_set_category
    • First observedha_config_set_dashboard
    • First observedha_config_set_dashboard_resource
    • First observedha_config_set_group
    • First observedha_config_set_helper
    • First observedha_config_set_label
    • First observedha_config_set_scene
    • First observedha_config_set_script
    • First observedha_eval_template
    • First observedha_get_addon
    • First observedha_get_automation_traces
    • First observedha_get_blueprint
    • First observedha_get_camera_image
    • First observedha_get_device
    • First observedha_get_entity
    • First observedha_get_entity_exposure
    • First observedha_get_hacs_info
    • First observedha_get_history
    • First observedha_get_integration
    • First observedha_get_logs
    • First observedha_get_operation_status
    • First observedha_get_overview
    • First observedha_get_skill_guide
    • First observedha_get_state
    • First observedha_get_system_health
    • First observedha_get_todo
    • First observedha_get_zone
    • First observedha_import_blueprint
    • First observedha_list_floors_areas
    • First observedha_list_services
    • First observedha_manage_addon
    • First observedha_manage_backup
    • First observedha_manage_energy_prefs
    • First observedha_manage_hacs
    • First observedha_manage_pipeline
    • First observedha_manage_radio
    • First observedha_manage_theme
    • First observedha_manage_updates
    • First observedha_reload_core
    • First observedha_remove_area_or_floor
    • First observedha_remove_device
    • First observedha_remove_entity
    • First observedha_remove_helpers_integrations
    • First observedha_remove_todo_item
    • First observedha_remove_zone
    • First observedha_report_issue
    • First observedha_restart
    • First observedha_search
    • First observedha_set_area_or_floor
    • First observedha_set_device
    • First observedha_set_entity
    • First observedha_set_integration
    • First observedha_set_todo_item
    • First observedha_set_zone

TDQS

A3.6/5.0
Disambiguation3/5

The tool set covers many distinct Home Assistant domains (automation, script, dashboard, entity, helper, integration, device, calendar, todo, etc.), but there is significant overlap between some tools, e.g. ha_config_set_automation vs ha_config_set_script vs ha_config_set_helper, and ha_set_entity vs ha_set_device vs ha_manage_* tools. Also ha_manage_app and ha_manage_updates have overlapping lifecycle actions. However, descriptions are detailed and often clarify when to use each, so an agent can usually disambiguate.

Naming Consistency4/5

Names mostly follow a consistent pattern: ha_config_get/set/remove_<resource> for configuration, ha_get_<resource> for read, ha_set_<resource> for write, ha_call_service, ha_manage_<resource> for management actions. There are some deviations like ha_bulk_control, ha_get_overview, and ha_config_list_helpers vs ha_config_get_dashboard, but overall the convention is predictable.

Tool Count2/5

78 tools is far beyond the typical well-scoped server size (3-15). The server attempts to cover an enormous range of Home Assistant functionality, which is ambitious but results in a heavy, bloated tool surface. Many tools are highly specialized (e.g. ha_config_list_dashboard_resources, ha_manage_energy_prefs, ha_get_entity_exposure) and could be merged or omitted, but the count is not extreme enough to warrant a 1.

Completeness4/5

The tool surface is remarkably extensive and covers almost every aspect of Home Assistant management: configuration CRUD for automations/scripts/scenes/dashboards/helpers, entity registry management, state/service calls, history/logs, system health, backups, updates, HACS, and integrations. Some gaps exist (e.g. no direct tool for managing YAML configuration files beyond ha_config_set_yaml, no dedicated tool for creating templates beyond ha_config_set_helper), but most workflows are covered.

Maintenance

ActivityActive
ResponsivenessResponsive

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    An MCP server and Home Assistant add-on that enables AI assistants to manage smart homes by creating automations, designing dashboards, and interacting with entities. It features native access to Home Assistant APIs, built-in Git versioning for safe rollbacks, and full management of HACS integrations.
    619
    MIT
  • A
    license
    A
    quality
    C
    maintenance
    MCP server for full Home Assistant control, enabling AI agents to manage dashboards, automations, files, apps, entities, and more via REST API, WebSocket, and SSH.
    66
    92
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    An MCP server that enables AI assistants to control Home Assistant via natural language, including device control, automation management, and system configuration.
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    A self-hosted MCP server for Home Assistant that exposes full control over entity states, service calls, history, templates, and areas via local stdio, enabling AI assistants to manage your smart home.
    9
    91
    MIT

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/homeassistant-ai/ha-mcp'

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