Skip to main content
Glama
homeassistant-ai

Home Assistant MCP Server

Official

Call Service

ha_call_service
Destructive

Execute any Home Assistant service to control smart home entities, trigger automations, and send advanced WebSocket commands.

Instructions

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.

Input Schema

TableJSON 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

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Schema Changelog

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

  1. Changed6 schema fields changedv8.4.1
    • 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."
  2. Changed1 schema field changedv8.2.0
    • 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."
  3. First observedv7.14.2

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.

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