list_entities
Retrieve Home Assistant entities filtered by domain, search term, or specific fields.
Instructions
Get a list of Home Assistant entities with optional filtering
Args: domain: Optional domain to filter by (e.g., 'light', 'switch', 'sensor') search_query: Optional search term to filter entities by name, id, or attributes (Note: Does not support wildcards. To get all entities, leave this empty) limit: Maximum number of entities to return (default: 100) fields: Optional list of specific fields to include in each entity detailed: If True, returns all entity fields without filtering
Returns: A list of entity dictionaries with lean formatting by default
Examples: domain="light" - get all lights search_query="kitchen", limit=20 - search entities domain="sensor", detailed=True - full sensor details
Best Practices: - Use lean format (default) for most operations - Prefer domain filtering over no filtering - For domain overviews, use domain_summary_tool instead of list_entities - Only request detailed=True when necessary for full attribute inspection - To get all entity types/domains, use list_entities without a domain filter, then extract domains from entity_ids
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| domain | No | ||
| search_query | No | ||
| limit | No | ||
| fields | No | ||
| detailed | No |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| result | Yes |
Implementation Reference
- app/server.py:246-310 (handler)The main handler function for the 'list_entities' tool. Decorated with @mcp.tool() and @async_handler(). Accepts optional domain, search_query, limit, fields, and detailed parameters. Logs the request, handles wildcard '*' search query, and delegates to get_entities() in app/hass.py.
@mcp.tool() @async_handler("list_entities") async def list_entities( domain: Optional[str] = None, search_query: Optional[str] = None, limit: int = 100, fields: Optional[List[str]] = None, detailed: bool = False ) -> List[Dict[str, Any]]: """ Get a list of Home Assistant entities with optional filtering Args: domain: Optional domain to filter by (e.g., 'light', 'switch', 'sensor') search_query: Optional search term to filter entities by name, id, or attributes (Note: Does not support wildcards. To get all entities, leave this empty) limit: Maximum number of entities to return (default: 100) fields: Optional list of specific fields to include in each entity detailed: If True, returns all entity fields without filtering Returns: A list of entity dictionaries with lean formatting by default Examples: domain="light" - get all lights search_query="kitchen", limit=20 - search entities domain="sensor", detailed=True - full sensor details Best Practices: - Use lean format (default) for most operations - Prefer domain filtering over no filtering - For domain overviews, use domain_summary_tool instead of list_entities - Only request detailed=True when necessary for full attribute inspection - To get all entity types/domains, use list_entities without a domain filter, then extract domains from entity_ids """ log_message = "Getting entities" if domain: log_message += f" for domain: {domain}" if search_query: log_message += f" matching: '{search_query}'" if limit != 100: log_message += f" (limit: {limit})" if detailed: log_message += " (detailed format)" elif fields: log_message += f" (custom fields: {fields})" else: log_message += " (lean format)" logger.info(log_message) # Handle special case where search_query is a wildcard/asterisk - just ignore it if search_query == "*": search_query = None logger.info("Converting '*' search query to None (retrieving all entities)") # Use the updated get_entities function with field filtering return await get_entities( domain=domain, search_query=search_query, limit=limit, fields=fields, lean=not detailed # Use lean format unless detailed is requested ) - app/server.py:246-247 (registration)The tool is registered via the @mcp.tool() decorator on line 246 in app/server.py, which registers 'list_entities' as an MCP tool with the FastMCP server.
@mcp.tool() @async_handler("list_entities") - app/hass.py:256-354 (helper)The get_entities() helper function in app/hass.py that performs the actual API call. It fetches all states from HA's /api/states endpoint, enriches with area data, filters by domain and search query, applies limits, and formats output with lean/field filtering.
async def get_entities( domain: Optional[str] = None, search_query: Optional[str] = None, limit: int = 100, fields: Optional[List[str]] = None, lean: bool = True ) -> List[Dict[str, Any]]: """ Get a list of all entities from Home Assistant with optional filtering and search Args: domain: Optional domain to filter entities by (e.g., 'light', 'switch') search_query: Optional case-insensitive search term to filter by entity_id, friendly_name or other attributes limit: Maximum number of entities to return (default: 100) fields: Optional list of specific fields to include in each entity lean: If True (default), returns token-efficient versions with minimal fields Returns: List of entity dictionaries, optionally filtered by domain and search terms, and optionally limited to specific fields """ # Get all entities directly client = await get_client() response = await client.get(f"{HA_URL}/api/states", headers=get_ha_headers()) response.raise_for_status() entities = response.json() # Enrich each entity with area data. One bulk template call covers # the whole list regardless of size. areas = await get_all_areas(client) for entity in entities: entity["area"] = areas.get(entity["entity_id"]) # Filter by domain if specified if domain: entities = [entity for entity in entities if entity["entity_id"].startswith(f"{domain}.")] # Search if query is provided if search_query and search_query.strip(): search_term = search_query.lower().strip() filtered_entities = [] for entity in entities: # Search in entity_id if search_term in entity["entity_id"].lower(): filtered_entities.append(entity) continue # Search in friendly_name friendly_name = entity.get("attributes", {}).get("friendly_name", "").lower() if friendly_name and search_term in friendly_name: filtered_entities.append(entity) continue # Search in other common attributes (state, area_id, etc.) if search_term in entity.get("state", "").lower(): filtered_entities.append(entity) continue # Search in other attributes for attr_name, attr_value in entity.get("attributes", {}).items(): # Check if attribute value can be converted to string if isinstance(attr_value, (str, int, float, bool)): if search_term in str(attr_value).lower(): filtered_entities.append(entity) break entities = filtered_entities # Apply the limit if limit > 0 and len(entities) > limit: entities = entities[:limit] # Apply field filtering if requested if fields: # Use explicit field list when provided return [filter_fields(entity, fields) for entity in entities] elif lean: # Apply domain-specific lean fields to each entity result = [] for entity in entities: # Get the entity's domain entity_domain = entity["entity_id"].split('.')[0] # Start with basic lean fields lean_fields = DEFAULT_LEAN_FIELDS.copy() # Add domain-specific important attributes if entity_domain in DOMAIN_IMPORTANT_ATTRIBUTES: for attr in DOMAIN_IMPORTANT_ATTRIBUTES[entity_domain]: lean_fields.append(f"attr.{attr}") # Filter and add to result result.append(filter_fields(entity, lean_fields)) return result else: # Return full entities return entities - app/server.py:248-254 (schema)Input schema/type annotations for the list_entities tool: domain (Optional[str]), search_query (Optional[str]), limit (int, default 100), fields (Optional[List[str]]), detailed (bool, default False). Return type is List[Dict[str, Any]].
async def list_entities( domain: Optional[str] = None, search_query: Optional[str] = None, limit: int = 100, fields: Optional[List[str]] = None, detailed: bool = False ) -> List[Dict[str, Any]]: