Skip to main content
Glama
homeassistant-ai

Home Assistant MCP Server

Official

Bulk Control

ha_bulk_control
Destructive

Control multiple Home Assistant entities in one call using explicit operations or a selector-based bulk action on areas, floors, and exclusions.

Instructions

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 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.

If a Claude Desktop user gets a 4-minute timeout with no result on this call, read the target back before repeating it, and tell them to wait a few seconds before clicking the manual-approve button, as clicking it too quickly is known to cause hangs in Claude Desktop. This workaround is specific to Claude Desktop.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
actionNoOne device action applied to every resolved leaf.
dry_runNoSelector mode only; True is rejected in operations mode.
parallelNoDispatch operations concurrently (default) or one at a time when False.
selectorNoOptional exact structural scope using domain plus area_ids and/or floor_ids, with optional exclude_entity_ids.
operationsNoExplicit entity operations. Each item requires exact entity_id and action. Use action='off', not service='turn_off'.
parametersNoOptional action parameters for selector mode.
validate_firstNoSelector mode only: report ENTITY_NOT_FOUND for a target that does not exist. In operations mode set validate_first on each operation instead; a top-level False is rejected in operations mode.
timeout_secondsNoSelector mode only: confirmation wait in seconds for every resolved entity. In operations mode set timeout_seconds on each operation instead; a top-level value is rejected in operations mode.

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed5 schema fields changedv8.6.0
    • addedInput schema / properties / dry_run / description
      Added value: +"Selector mode only; True is rejected in operations mode."
    • changedInput schema / properties / operations / description
      Previous 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'."New value: +"Explicit entity operations. Each item requires exact entity_id and action. Use action='off', not service='turn_off'."
    • addedInput schema / properties / parallel / description
      Added value: +"Dispatch operations concurrently (default) or one at a time when False."
    • addedInput schema / properties / timeout_seconds / description
      Added value: +"Selector mode only: confirmation wait in seconds for every resolved entity. In operations mode set timeout_seconds on each operation instead; a top-level value is rejected in operations mode."
    • addedInput schema / properties / validate_first / description
      Added value: +"Selector mode only: report ENTITY_NOT_FOUND for a target that does not exist. In operations mode set validate_first on each operation instead; a top-level False is rejected in operations mode."
  2. Changed13 schema fields changedv8.4.1
    • 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"
      -]
  3. First observedv7.14.2

TDQS

A4.8/5.0
Behavior5/5

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

Annotations declare destructive=true/idempotent=false, and the description goes substantially beyond them: fail-closed behavior when every item fails, the group-plus-own-member conflict that silently drops nothing (nothing dispatched), the non-transactional per-leaf failure model, the 100-entity selector cap, and dry_run preview semantics. This is exactly the extra context an agent needs before a destructive bulk call.

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?

Front-loads purpose and exclusions, then splits modes into labeled paragraphs, which is well structured. However, the trailing Claude Desktop timeout paragraph is long and anecdotal, and mode exclusivity rules are restated in both the description and the schema, so some text does not fully earn 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 an 8-parameter destructive tool, the definition covers both execution modes, failure/abort semantics, exclusion mechanics, batch-size limits, and preview. An output schema exists so return values need no explanation, and annotations carry the safety profile; no gap remains that would cause a misinvocation.

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, and the schema already documents mode exclusivity (top-level validate_first/timeout_seconds/dry_run rejected in operations mode). The description adds genuine cross-parameter semantics not in the schema: the group/aggregate targeting conflict and its required exclude_entity_ids remedy, plus the >100-entity tightening path — both directly constrain how selector parameters may be combined.

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?

States a specific verb and resource ('Manage explicit operations or one deterministic structural bulk action') and immediately disambiguates against named siblings ha_call_service and ha_search. An agent can distinguish this tool from every neighboring tool without opening a schema.

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?

Contains an explicit 'When NOT to use' clause naming the two alternatives and the conditions that select them, then explains when to prefer operations mode vs selector mode (exclusions after recursive expansion, group/aggregate conflicts). Nothing is left to inference.

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

Deploy Server

Other Tools