Skip to main content
Glama
homeassistant-ai

Home Assistant MCP Server

Official

Call Service

ha_call_service
Destructive

Run any Home Assistant service or WebSocket command not covered by a dedicated tool. Use for services like light.turn_on or climate.set_temperature, with domain, service, and data.

Instructions

Call any Home Assistant service or one-shot WebSocket command: the catch-all escape hatch.

When NOT to use: a dedicated tool that covers the job. It validates the request, reports the outcome in its own terms, and stays available where a security policy gates this tool. For example: turn an automation on or off or run it now with ha_config_set_automation (enabled / run_actions); start or stop a script with ha_config_set_script (run); activate a scene with ha_config_set_scene (activate); manage apps (add-ons) with ha_manage_app; handle updates and Repairs issues with ha_manage_updates; set an integration's log level with ha_set_integration (log_level).

When to use: a service no dedicated tool covers. Services follow the pattern domain.service (e.g., light.turn_on, climate.set_temperature); ha_list_services lists them with their fields.

EXAMPLES:

  • ha_call_service("light", "turn_on", entity_id="light.living_room")

  • ha_call_service("climate", "set_temperature", entity_id="climate.thermostat", data={"temperature": 22})

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

For detailed service documentation, use ha_get_skill_guide.

WebSocket command escape hatch (advanced): Some Home Assistant operations are WebSocket-only commands, not registered services. Pass ws_command (instead of domain/service) to send one no dedicated tool covers, with its parameters in data: ha_call_service(ws_command="", data={...}). Only one-shot request/response commands are supported, and the other service parameters (entity_id, return_response, etc.) don't apply.

Unavailable in Read Only Mode, including read-like services and WebSocket commands. Use dedicated read tools while that mode is enabled.

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
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.
serviceNoService name within domain (e.g. 'turn_on', 'set_temperature', 'trigger'). Required for a service call.
verboseNoReturn HA's raw changed-state records unchanged. With return_response=True the response data still surfaces once as the top-level service_response key, never nested in result. Large for nested-group targets — prefer result_fields / result_attribute_keys.
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.
ws_commandNoAdvanced escape hatch: send a raw one-shot Home Assistant WebSocket command that is NOT a registered service and that no dedicated tool covers. When set, omit domain/service and the other service params. 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']). 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'.
result_attribute_keysNoProject each record's 'attributes' dict to only these keys (e.g. ['brightness', 'rgb_color']). 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.

  1. Changed8 schema fields changedv8.6.0
    • changedInput schema / properties / domain / description
      Previous value: -"Service domain (e.g. 'light', 'climate', 'automation'). Required for a service call; must be omitted when ws_command is set."New value: +"Service domain (e.g. 'light', 'climate', 'automation'). Required for a service call."
    • changedInput schema / properties / entity_id / description
      Previous 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."New 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."
    • changedInput schema / properties / result_attribute_keys / description
      Previous value: -"Project 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)."New value: +"Project each record's 'attributes' dict to only these keys (e.g. ['brightness', 'rgb_color']). Setting this DISABLES default compaction. Requires 'attributes' to be present in result_fields (or result_fields=None)."
    • changedInput schema / properties / result_fields / description
      Previous value: -"Project 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."New value: +"Project each record in 'result' to only these top-level keys (e.g. ['entity_id', 'state']). Setting this DISABLES default compaction — no entity-id filter, no metadata strip — and applies the explicit projection instead."
    • changedInput schema / properties / return_response / description
      Previous 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."New value: +"If True, the service's response data is returned once, as the top-level 'service_response' key — never nested inside 'result'."
    • changedInput schema / properties / service / description
      Previous 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."New value: +"Service name within domain (e.g. 'turn_on', 'set_temperature', 'trigger'). Required for a service call."
    • changedInput schema / properties / verbose / description
      Previous 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."New value: +"Return HA's raw changed-state records unchanged. With return_response=True the response data still surfaces once as the top-level service_response key, never nested in result. Large for nested-group targets — prefer result_fields / result_attribute_keys."
    • changedInput schema / properties / ws_command / description
      Previous value: -"Advanced 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."New value: +"Advanced escape hatch: send a raw one-shot Home Assistant WebSocket command that is NOT a registered service and that no dedicated tool covers. When set, omit domain/service and the other service params. Streaming/two-phase and service-invoking commands (call_service, execute_script) are rejected."
  2. 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."
  3. 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."
  4. 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 already cover the safety profile (destructive=true, readOnly=false, idempotent=false), and the description layers on non-obvious behavior: default result compaction and exactly what it strips, the ws_command one-shot restriction with call_service/execute_script rejected, unavailability in Read Only Mode, and the multi-target/wait pitfall. The Claude Desktop timeout-before-retry workaround is unusual but operationally material.

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-loaded with purpose, then when-not/when-to, examples, compaction, the WebSocket escape hatch, and mode gating — every section is headed and information-dense. The single detractor is the trailing Claude Desktop timeout paragraph, which is client-specific and sits far from the call semantics it relates to.

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 10-parameter catch-all with an output schema present, the description covers the routing decision, the two invocation modes, the read-only gate, and the result-shaping behavior that the output schema cannot express. Nothing an agent needs in order to choose and invoke it 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 description coverage is 100%, so the baseline is 3 and the schema already carries the parameter contract. The description still adds meaning the schema does not: worked examples showing positional domain/service plus data, and the domain.service pattern that governs how these two strings must be supplied. That is a modest but real lift 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?

States a specific verb+resource ('call any Home Assistant service... the catch-all escape hatch') and immediately frames itself against dedicated siblings, naming them with the exact arguments that select them (ha_config_set_automation, ha_config_set_script, ha_config_set_scene, ha_manage_app, ha_manage_updates, ha_set_integration). An agent can place this tool correctly without opening any 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?

Explicit when-NOT-to-use (a dedicated tool covers the job) with a concrete routing table of alternatives, followed by an explicit when-to-use (a service no dedicated tool covers), the domain.service naming convention, and a pointer to ha_list_services for discovery. Both the positive and negative conditions are spelled out rather than inferred.

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