Skip to main content
Glama
Home Assistant MCP Server

Home Assistant MCP Server

Official

Call Event

ha_call_event
Destructive

Fire a custom event on the Home Assistant event bus to trigger event-driven automations, Node-RED flows, or custom integrations that subscribe to specific event types.

Instructions

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. To run an automation now, use ha_config_set_automation(entity_id=..., run_actions=True).

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; a successful dispatch reports the bus accepted the event and how many listeners were registered for it, not that any of them acted. A timeout means dispatch is unconfirmed. listener_count covers the exact event type; wildcard_listener_count covers match-all listeners (the recorder is one, and it only stores the event). The counts come from the component's dispatch reply when it serves the fire, otherwise from a GET /api/events lookup taken before dispatch; a route that cannot report them omits both fields.

The response carries the event's context_id (and context) when Home Assistant reports it. An automation triggered by this event records that id as the parent_id of its run's context, so looking up that automation trace proves whether a listener acted — which the counts cannot show, because an event trigger that filters on event_data still registers as a listener when the payload does not match.

Events fire in-process through the ha_mcp_tools component when it is installed, otherwise over Home Assistant's own WebSocket fire_event command; both carry the event type in the message body, so any type Core accepts fires as written and Core's rejection comes back as the error text (for example its 64-character event-type limit). state_changed alone keeps the REST route, because only that route rebuilds its old_state/new_state payloads into State objects; there event_type must be a plain name with no / \ ? # or % characters.

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.

Tool call template

Replace each placeholder with a value matching the input schema. Only required parameters are included; add optional parameters as needed.

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "arguments": {
      "event_type": "<event_type>"
    },
    "name": "ha_call_event"
  }
}

Input Schema

NameRequiredDescriptionDefault
dataNoOptional event payload, delivered to subscribers as the event's data (trigger.event.data in an automation).
event_typeYesEvent type to fire, e.g. 'my_custom_event'.

Output Schema

NameRequiredDescriptionDefault

No arguments

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed2 schema fields changedv8.6.0
    • addedInput schema / properties / data / description
      Added value: +"Optional event payload, delivered to subscribers as the event's data (trigger.event.data in an automation)."
    • addedInput schema / properties / event_type / description
      Added value: +"Event type to fire, e.g. 'my_custom_event'."
  2. First observedv7.14.2

TDQS

A3.9/5.0
Behavior3/5

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

Beyond the annotations (destructiveHint=true, non-idempotent) it discloses genuinely useful behavior: fire-and-forget semantics, what listener_count vs wildcard_listener_count mean, that a timeout means unconfirmed dispatch, and that context_id/parent_id is the only proof a listener acted. However, it spends most of its length on internal dispatch routing (in-process component vs WebSocket fire_event, REST exception for state_changed) and a Claude Desktop timeout workaround, which is operational trivia rather than behavior an agent needs to select or invoke the tool. The safety-relevant disclosure is diluted by this padding.

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?

Purpose and exclusions are correctly front-loaded, but the body sprawls across five dense paragraphs, most of it covering dispatch internals, error-text provenance, and a client-specific timeout workaround. Several sentences (the recorder being a wildcard listener, the fallback GET /api/events lookup) do not earn their place in a tool description an agent must parse at selection time.

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 two-parameter fire-and-forget tool with an output schema and full param documentation, this covers more than enough: exclusions, error surfacing, count semantics, and trace-based verification. It loses a point because the volume of low-value routing detail and the confusing 'read the target back before repeating it' instruction make it harder to extract the operative guidance, and the client-specific paragraph reads as extraneous.

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% for both parameters, so event_type and data are already fully documented, establishing a baseline of 3. The description adds a real constraint beyond the schema (for state_changed the type must be a plain name without / \ ? # or %, and Core enforces a 64-character event-type limit), but only for one narrow route; it offers nothing extra about the data payload.

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 and resource: 'Execute a custom event on the Home Assistant event bus.' It then names what the event is for (event-triggered automations, Node-RED flows, custom integrations), which lets an agent distinguish it from service calls and automation runs without opening the 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?

Gives an explicit 'When NOT to use' block with two named alternatives and their exact invocation (ha_call_service for entities, ha_config_set_automation(entity_id=..., run_actions=True) to run an automation), plus a positive use case. Both the exclusion and the routing condition are stated.

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