search_entities_tool
Search for Home Assistant entities by querying their IDs, names, or attributes. Returns matching results with count and domain breakdown.
Instructions
Search for entities matching a query string
Args: query: The search query to match against entity IDs, names, and attributes. (Note: Does not support wildcards. To get all entities, leave this blank or use list_entities tool) limit: Maximum number of results to return (default: 20)
Returns: A dictionary containing search results and metadata: - count: Total number of matching entities found - results: List of matching entities with essential information - domains: Map of domains with counts (e.g. {"light": 3, "sensor": 2})
Examples: query="temperature" - find temperature entities query="living room", limit=10 - find living room entities query="", limit=500 - list all entity types
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | ||
| limit | No |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| result | Yes |
Implementation Reference
- app/server.py:424-553 (handler)The main handler function for the search_entities_tool MCP tool. It is registered with @mcp.tool() decorator and @async_handler('search_entities_tool'). Accepts a query string and optional limit (default 20), searches entities via get_entities(), and returns structured results with count, results list, domain counts, and the query string. Handles special cases like empty query (returns all entities) and '*' wildcard conversion.
@async_handler("search_entities_tool") async def search_entities_tool(query: str, limit: int = 20) -> Dict[str, Any]: """ Search for entities matching a query string Args: query: The search query to match against entity IDs, names, and attributes. (Note: Does not support wildcards. To get all entities, leave this blank or use list_entities tool) limit: Maximum number of results to return (default: 20) Returns: A dictionary containing search results and metadata: - count: Total number of matching entities found - results: List of matching entities with essential information - domains: Map of domains with counts (e.g. {"light": 3, "sensor": 2}) Examples: query="temperature" - find temperature entities query="living room", limit=10 - find living room entities query="", limit=500 - list all entity types """ logger.info(f"Searching for entities matching: '{query}' with limit: {limit}") # Special case - treat "*" as empty query to just return entities without filtering if query == "*": query = "" logger.info("Converting '*' to empty query (retrieving all entities up to limit)") # Handle empty query as a special case to just return entities up to the limit if not query or not query.strip(): logger.info(f"Empty query - retrieving up to {limit} entities without filtering") entities = await get_entities(limit=limit, lean=True) # Check if there was an error if isinstance(entities, dict) and "error" in entities: return {"error": entities["error"], "count": 0, "results": [], "domains": {}} # No query, but we'll return a structured result anyway domains_count = {} simplified_entities = [] for entity in entities: domain = entity["entity_id"].split(".")[0] # Count domains if domain not in domains_count: domains_count[domain] = 0 domains_count[domain] += 1 # Create simplified entity representation simplified_entity = { "entity_id": entity["entity_id"], "state": entity["state"], "domain": domain, "friendly_name": entity.get("attributes", {}).get("friendly_name", entity["entity_id"]) } # Add key attributes based on domain attributes = entity.get("attributes", {}) # Include domain-specific important attributes if domain == "light" and "brightness" in attributes: simplified_entity["brightness"] = attributes["brightness"] elif domain == "sensor" and "unit_of_measurement" in attributes: simplified_entity["unit"] = attributes["unit_of_measurement"] elif domain == "climate" and "temperature" in attributes: simplified_entity["temperature"] = attributes["temperature"] elif domain == "media_player" and "media_title" in attributes: simplified_entity["media_title"] = attributes["media_title"] simplified_entities.append(simplified_entity) # Return structured response for empty query return { "count": len(simplified_entities), "results": simplified_entities, "domains": domains_count, "query": "all entities (no filtering)" } # Normal search with non-empty query entities = await get_entities(search_query=query, limit=limit, lean=True) # Check if there was an error if isinstance(entities, dict) and "error" in entities: return {"error": entities["error"], "count": 0, "results": [], "domains": {}} # Prepare the results domains_count = {} simplified_entities = [] for entity in entities: domain = entity["entity_id"].split(".")[0] # Count domains if domain not in domains_count: domains_count[domain] = 0 domains_count[domain] += 1 # Create simplified entity representation simplified_entity = { "entity_id": entity["entity_id"], "state": entity["state"], "domain": domain, "friendly_name": entity.get("attributes", {}).get("friendly_name", entity["entity_id"]) } # Add key attributes based on domain attributes = entity.get("attributes", {}) # Include domain-specific important attributes if domain == "light" and "brightness" in attributes: simplified_entity["brightness"] = attributes["brightness"] elif domain == "sensor" and "unit_of_measurement" in attributes: simplified_entity["unit"] = attributes["unit_of_measurement"] elif domain == "climate" and "temperature" in attributes: simplified_entity["temperature"] = attributes["temperature"] elif domain == "media_player" and "media_title" in attributes: simplified_entity["media_title"] = attributes["media_title"] simplified_entities.append(simplified_entity) # Return structured response return { "count": len(simplified_entities), "results": simplified_entities, "domains": domains_count, "query": query } - app/server.py:423-424 (registration)The tool is registered with MCP via the @mcp.tool() decorator on line 423, which registers it under the name 'search_entities_tool' in the FastMCP server instance.
@mcp.tool() @async_handler("search_entities_tool") - app/server.py:304-310 (helper)The search_entities_tool handler calls get_entities() imported from app.hass, passing search_query, limit, and lean=True parameters to perform the actual entity search.
return await get_entities( domain=domain, search_query=search_query, limit=limit, fields=fields, lean=not detailed # Use lean format unless detailed is requested )