Skip to main content
Glama
homeassistant-ai

Home Assistant MCP Server

Official

Bulk Control

ha_bulk_control
Destructive

Apply one action to many Home Assistant entities via explicit lists or area/floor selectors. Exclude entities, preview with dry run, and keep invalid items from blocking valid operations.

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

Input Schema

TableJSON 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

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Schema Changelog

Changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 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"
      -]
  2. 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 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.

Install Server

Other Tools

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