Skip to main content
Glama

search_entities_tool

Find Home Assistant entities by searching IDs, names, and attributes using a query string to locate specific devices or sensors in your smart home system.

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

TableJSON Schema
NameRequiredDescriptionDefault
queryYes
limitNo

Implementation Reference

  • Implementation of the search_entities_tool handler. Decorated with @mcp.tool() for MCP registration and @async_handler for logging. Handles entity search queries, empty queries as all-entities listing, simplifies results with domain counts and key attributes per domain.
    @mcp.tool()
    @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
        }
  • Type hints and comprehensive docstring defining input schema (query: str, limit: int=20) and output schema (Dict[str, Any] with specific keys: count, results, domains, query or error).
    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
            
        """
  • app/server.py:360-361 (registration)
    MCP tool registration via @mcp.tool() decorator and named via @async_handler("search_entities_tool").
    @mcp.tool()
    @async_handler("search_entities_tool")
Behavior4/5

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

With no annotations provided, the description carries full burden for behavioral disclosure. It effectively describes key behaviors: search functionality with query matching against specific fields (IDs, names, attributes), lack of wildcard support, default limit behavior, and return format details. It doesn't mention error conditions, rate limits, or authentication needs, but provides substantial operational context.

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?

Well-structured with clear sections (Args, Returns, Examples) and front-loaded purpose statement. Every sentence adds value: the initial statement defines purpose, parameter explanations provide crucial constraints, return format details output structure, and examples demonstrate practical usage. Slightly verbose in return format details but justified given no output schema.

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?

Given 2 parameters with 0% schema coverage and no output schema, the description provides strong compensation: complete parameter semantics, return format details, and usage examples. It doesn't cover all possible edge cases or error conditions, but for a search tool with this complexity, it provides sufficient context for effective use.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must fully compensate. It provides comprehensive parameter semantics: explains what 'query' matches against (IDs, names, attributes), notes wildcard limitations, and explains blank query behavior. For 'limit', it specifies default value (20) and purpose. The examples further clarify parameter usage in different scenarios.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Search for entities matching a query string' with specific resources (entity IDs, names, attributes). It distinguishes from sibling 'list_entities' by noting this tool is for search, not listing all entities. However, it doesn't explicitly differentiate from other search-related siblings like 'get_entity' or 'domain_summary_tool'.

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?

The description provides explicit guidance on when to use this tool versus alternatives. It states: 'To get all entities, leave this blank or use list_entities tool' and gives examples showing different query scenarios. It also clarifies what the tool does not support ('Does not support wildcards'), providing clear boundaries.

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/voska/hass-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server