Skip to main content
Glama
homeassistant-ai

Home Assistant MCP Server

Official

Search

ha_search
Read-onlyIdempotent

Search Home Assistant entities and config contents by name, domain, area, state, or text—automations, scripts, scenes, helpers, dashboards—in one call.

Instructions

Search for entities (lights, sensors, switches, climate, etc.) by name, domain, or area — AND inside automation/script/scene/helper/dashboard configurations — in one call.

Two surfaces run in parallel and return tagged results:

  • entities: entity-registry matches (entity_id, friendly name, area). Filter with domain_filter/area_filter/state_filter.

  • automations / scripts / scenes / helpers / dashboards: matches inside config definitions — triggers, actions, sequences, scene entity-sets, helper bodies, dashboard cards. Driven by query; narrow with search_types.

Use dedicated get/list tools first for a known resource type, including ha_config_get_scene for scene listing and content search. Use this for broader discovery or deep searches across resource types.

For control requests with exclusions such as "except", "excluding", or "but not", include is_group and member_entity_ids in result_fields. Do not control an aggregate whose members include an excluded entity; prefer leaf entities when the exception cannot be verified safely. A withheld member list still returns is_group=true; absence of member_entity_ids must not be interpreted as a leaf entity.

When NOT to use:

  • To read a known entity_id's state: use ha_get_state (cheaper).

  • To inspect one automation/script/scene config by id: use the matching ha_config_get_*.

  • To list installed Apps (add-ons): use ha_get_app.

Config-body search is skipped when domain_filter/area_filter/ state_filter signal entity-only intent (keeping name lookups off the expensive backend); a warnings[] entry names the skip. Repeat without entity filters to search configuration contents too.

Caveats:

  • partial: True means results are NOT exhaustive — a surface raised, or the config-body branch lost data (per-id time budget exhausted, an individual fetch failed, or a helper-type list fetch failed). Empty buckets with partial: True mean "search failed", not "no results". The cause is in partial_reason, also mirrored into warnings[] with an "incomplete results: " prefix. Do not treat a partial response as complete.

  • count is items in this response (post-pagination), not corpus totals — use entity_total_matches + config_total_matches.

  • limit/offset apply per-surface. Flat has_more/next_offset page the next call (iterate offset = next_offset); per-surface entity_*/config_* variants show which surface still has results.

Examples: - Find a light by name: ha_search("kitchen", domain_filter="light") - List sensors in an area: ha_search(domain_filter="sensor", area_filter="Living Room") - Find lights safely before an "all except one" control request: ha_search("living room", domain_filter="light", result_fields=["entity_id", "friendly_name", "is_group", "member_entity_ids"]) - Which automations use an entity: ha_search("light.bed_light") - All unavailable entities: ha_search(state_filter="unavailable")

find entities configs lookup discover search lights sensors switches covers climate fans media_player binary_sensor device_tracker person weather automation script helper input_boolean input_number automations scripts scenes helpers dashboards

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum results per surface (entities, configs).
queryNoWhat to search for (entity name fragment, free-text config term, entity_id). Pass the exact entity_id, not a name fragment, when checking what a rename or delete would break: that form reports automations, scripts and scenes referencing it even when their configuration could not be read. Omit `query` to enumerate by `domain_filter`, `area_filter`, and/or `state_filter` alone (registry-listing mode); configuration-body search is skipped in that mode because there is no term to match against.
fieldsNoProject the response to the named top-level keys (e.g. ["entities", "automations"]); None = full response. Diagnostic / pagination keys are always retained so projection cannot hide partial / error state. Distinct from `result_fields` (which projects each entity record's keys). Available keys: success, query, entities, automations, scripts, scenes, helpers, dashboards, search_types, search_type, entity_total_matches, config_total_matches, count, offset, limit, has_more, next_offset, entity_has_more, entity_next_offset, config_has_more, config_next_offset, by_domain, state_filter_note, area_names, domain_filter, area_filter, message, warnings, errors, partial, partial_reason.
offsetNoNumber of results to skip for pagination.
area_filterNoNarrow entity-registry results to an area (id, name, or alias), an exact floor (id, name, or alias), or an unambiguous close-spelling floor match; a floor match expands to all areas on that floor.
exact_matchNoExact substring matching. Set False for fuzzy matching when the query may have typos.
search_typesNoConfiguration types to include in body search: 'automation', 'script', 'scene', 'helper', 'dashboard'. Explicitly providing this selects configuration-only search and skips entities. Omit it for entity discovery. Default = automation+script+scene+helper.
state_filterNoFilter entity-registry results to a specific state (e.g. "on", "off", "unavailable"). Case-insensitive. Can be used standalone (no query/domain/area) to enumerate every entity in that state; entity_total_matches reflects the filtered count.
domain_filterNoNarrow entity-registry results to a single domain (e.g. 'light', 'sensor').
result_fieldsNoProject each entity-registry record to only the specified keys (e.g. ["entity_id", "state"]). None = full records. Base keys: entity_id, friendly_name, domain, state, score, match_type. Opt-in enrichment/membership keys (computed on request): area, floor, labels, aliases, is_group, member_entity_ids. Membership is recognized only when HA explicitly exposes a valid group_entities or legacy entity_id collection; member IDs are sorted, direct (not recursively expanded), and omitted if visibility/include_hidden excludes a member. Requesting member_entity_ids also retains is_group. An unknown key is rejected.
include_configNoInclude full configuration bodies in body-search results. Otherwise summaries only.
include_hiddenNoInclude hidden entities in registry results (with a score penalty so they sort below visible matches). Set False to exclude entirely.
group_by_domainNoGroup entity-registry results by domain (entity-side only). Adds a `by_domain` map to the response.
per_domain_limitNoWhen `group_by_domain=True`, cap entity-registry results per domain to this number. Ignored otherwise.
config_time_budgetNoPer-call override for the per-id config-fetch wall-clock budget (seconds). Replaces the per-type HAMCP_*_CONFIG_TIME_BUDGET defaults for the automation, script, AND scene branches. Use when a `partial: True` response names time-budget skipping. None = use the per-type env defaults.

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed9 schema fields changedv8.6.0
    • changedInput schema / properties / area_filter / description
      Previous value: -"Narrow entity-registry results to an area (id, name, or alias), an exact floor (id, name, or alias), or an unambiguous close-spelling floor match; a floor match expands to all areas on that floor. Does not affect configuration search."New value: +"Narrow entity-registry results to an area (id, name, or alias), an exact floor (id, name, or alias), or an unambiguous close-spelling floor match; a floor match expands to all areas on that floor."
    • changedInput schema / properties / config_time_budget / description
      Previous value: -"Per-call override for the per-id config-fetch wall-clock budget (seconds). Replaces the per-type HAMCP_*_CONFIG_TIME_BUDGET defaults for the automation, script, AND scene branches. Use when a `partial: True` response names time-budget skipping. Stateless per-call: one caller raising the budget doesn't affect others. None = use the per-type env defaults."New value: +"Per-call override for the per-id config-fetch wall-clock budget (seconds). Replaces the per-type HAMCP_*_CONFIG_TIME_BUDGET defaults for the automation, script, AND scene branches. Use when a `partial: True` response names time-budget skipping. None = use the per-type env defaults."
    • changedInput schema / properties / domain_filter / description
      Previous value: -"Narrow entity-registry results to a single domain (e.g. 'light', 'sensor'). Does not affect configuration search."New value: +"Narrow entity-registry results to a single domain (e.g. 'light', 'sensor')."
    • changedInput schema / properties / exact_match / description
      Previous value: -"Exact substring matching (default). Set False for fuzzy matching when the query may have typos."New value: +"Exact substring matching. Set False for fuzzy matching when the query may have typos."
    • changedInput schema / properties / include_config / description
      Previous value: -"Include full configuration bodies in body-search results. Default: False (summary only)."New value: +"Include full configuration bodies in body-search results. Otherwise summaries only."
    • changedInput schema / properties / limit / description
      Previous value: -"Maximum results per surface (entities, configs). Default: 10."New value: +"Maximum results per surface (entities, configs)."
    • changedInput schema / properties / query / description
      Previous value: -"What to search for (entity name fragment, free-text config term, entity_id). Searches BOTH the entity registry (entity_ids, friendly names, areas) AND configuration bodies (automation triggers/actions, script sequences, scene contents, helper bodies, dashboard cards) in one call. Use this for any find-something-in-HA question — entity OR config. Pass the exact entity_id, not a name fragment, when checking what a rename or delete would break: that form reports automations, scripts and scenes referencing it even when their configuration could not be read. Omit `query` to enumerate by `domain_filter`, `area_filter`, and/or `state_filter` alone (registry-listing mode); configuration-body search is skipped in that mode because there is no term to match against."New value: +"What to search for (entity name fragment, free-text config term, entity_id). Pass the exact entity_id, not a name fragment, when checking what a rename or delete would break: that form reports automations, scripts and scenes referencing it even when their configuration could not be read. Omit `query` to enumerate by `domain_filter`, `area_filter`, and/or `state_filter` alone (registry-listing mode); configuration-body search is skipped in that mode because there is no term to match against."
    • changedInput schema / properties / result_fields / description
      Previous value: -"Project each entity-registry record to only the specified keys (e.g. [\"entity_id\", \"state\"]). None = full records. Base keys: entity_id, friendly_name, domain, state, score, match_type. Opt-in enrichment/membership keys (computed on request): area, floor, labels, aliases, is_group, member_entity_ids. Membership is recognized only when HA explicitly exposes a valid group_entities or legacy entity_id collection; member IDs are sorted, direct (not recursively expanded), and omitted if visibility/include_hidden excludes a member. is_group remains true when member IDs are withheld; requesting member_entity_ids also retains is_group. An unknown key is rejected."New value: +"Project each entity-registry record to only the specified keys (e.g. [\"entity_id\", \"state\"]). None = full records. Base keys: entity_id, friendly_name, domain, state, score, match_type. Opt-in enrichment/membership keys (computed on request): area, floor, labels, aliases, is_group, member_entity_ids. Membership is recognized only when HA explicitly exposes a valid group_entities or legacy entity_id collection; member IDs are sorted, direct (not recursively expanded), and omitted if visibility/include_hidden excludes a member. Requesting member_entity_ids also retains is_group. An unknown key is rejected."
    • changedInput schema / properties / search_types / description
      Previous value: -"Configuration types to include in body search: 'automation', 'script', 'scene', 'helper', 'dashboard'. Default = automation+script+scene+helper. Pass as list or JSON-array string."New value: +"Configuration types to include in body search: 'automation', 'script', 'scene', 'helper', 'dashboard'. Explicitly providing this selects configuration-only search and skips entities. Omit it for entity discovery. Default = automation+script+scene+helper."
  2. Changed1 schema field changedv8.4.3
    • changedInput schema / properties / config_time_budget / anyOf
      Previous value: -[
      -  {
      -    "exclusiveMinimum": 0,
      -    "maximum": 300,
      -    "type": "number"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]New value: +[
      +  {
      +    "maximum": 300,
      +    "minimum": 0.001,
      +    "type": "number"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
  3. Changed4 schema fields changedv8.4.1
    • changedInput schema / properties / area_filter / description
      Previous value: -"Narrow entity-registry results to an area (id or name). Does not affect configuration search."New value: +"Narrow entity-registry results to an area (id, name, or alias), an exact floor (id, name, or alias), or an unambiguous close-spelling floor match; a floor match expands to all areas on that floor. Does not affect configuration search."
    • changedInput schema / properties / config_time_budget / description
      Previous value: -"Per-call override for the per-id config-fetch wall-clock budget (seconds). Replaces the per-type HAMCP_*_CONFIG_TIME_BUDGET defaults for the automation, script, AND scene branches when their bulk-fetch falls through to per-id Attempt-C. Use when a `partial: True` response names time-budget skipping. Stateless per-call: one caller raising the budget doesn't affect others. None = use the per-type env defaults."New value: +"Per-call override for the per-id config-fetch wall-clock budget (seconds). Replaces the per-type HAMCP_*_CONFIG_TIME_BUDGET defaults for the automation, script, AND scene branches. Use when a `partial: True` response names time-budget skipping. Stateless per-call: one caller raising the budget doesn't affect others. None = use the per-type env defaults."
    • changedInput schema / properties / query / description
      Previous value: -"What to search for (entity name fragment, free-text config term, entity_id). Searches BOTH the entity registry (entity_ids, friendly names, areas) AND configuration bodies (automation triggers/actions, script sequences, scene contents, helper bodies, dashboard cards) in one call. Use this for any find-something-in-HA question — entity OR config. Omit `query` to enumerate by `domain_filter`, `area_filter`, and/or `state_filter` alone (registry-listing mode); configuration-body search is skipped in that mode because there is no term to match against."New value: +"What to search for (entity name fragment, free-text config term, entity_id). Searches BOTH the entity registry (entity_ids, friendly names, areas) AND configuration bodies (automation triggers/actions, script sequences, scene contents, helper bodies, dashboard cards) in one call. Use this for any find-something-in-HA question — entity OR config. Pass the exact entity_id, not a name fragment, when checking what a rename or delete would break: that form reports automations, scripts and scenes referencing it even when their configuration could not be read. Omit `query` to enumerate by `domain_filter`, `area_filter`, and/or `state_filter` alone (registry-listing mode); configuration-body search is skipped in that mode because there is no term to match against."
    • changedInput schema / properties / result_fields / description
      Previous value: -"Project each entity-registry record to only the specified keys (e.g. [\"entity_id\", \"state\"]). None = full records. Base keys: entity_id, friendly_name, domain, state, score, match_type. Opt-in enrichment keys (joined on request): area, floor, labels, aliases. An unknown key is rejected."New value: +"Project each entity-registry record to only the specified keys (e.g. [\"entity_id\", \"state\"]). None = full records. Base keys: entity_id, friendly_name, domain, state, score, match_type. Opt-in enrichment/membership keys (computed on request): area, floor, labels, aliases, is_group, member_entity_ids. Membership is recognized only when HA explicitly exposes a valid group_entities or legacy entity_id collection; member IDs are sorted, direct (not recursively expanded), and omitted if visibility/include_hidden excludes a member. is_group remains true when member IDs are withheld; requesting member_entity_ids also retains is_group. An unknown key is rejected."
  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 only declare the safety profile (readOnly, idempotent, non-destructive, closed-world), yet the description discloses far more: partial-result semantics with partial_reason/warnings, that empty buckets under partial mean failure, count vs. corpus totals, per-surface limit/offset and has_more/next_offset iteration, and silent config-body skipping. This is unusually rich behavioral disclosure beyond structured data.

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 purpose, then surfaces, then exclusions, then caveats, then examples — good ordering. It is long and contains some overlap with the schema (e.g., the config-body-skip rule is stated in both), and the aggregate-control paragraph is tangential to searching, but the length is largely justified by 15 parameters and two surfaces.

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?

An output schema exists, so return shape need not be explained, and the description still covers pagination, partiality, filtering interactions, and alternatives. Nothing an agent needs to select or invoke this tool 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 coverage is 100%, so baseline is 3, but the description adds cross-parameter semantics the schema does not: result_fields must include is_group/member_entity_ids for exclusion control requests, an exact entity_id query reports referrers even when configs are unreadable, and entity filters signal entity-only intent that suppresses body search. These interactions are genuinely useful; it falls short of 5 only because per-parameter meanings largely restate the 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?

States a specific verb and resource ('Search for entities ... AND inside automation/script/scene/helper/dashboard configurations') and explicitly enumerates the two parallel surfaces. It distinguishes itself from siblings by naming ha_get_state, ha_config_get_*, ha_get_app, and ha_config_get_scene as the alternatives for known resources.

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?

Has an explicit 'When NOT to use' block routing each case to a specific sibling, plus a positive statement of when this tool is preferred ('broader discovery or deep searches across resource types'). The exclusion-control guidance and the entity-filter-skips-config-body note give concrete usage conditions.

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