Building an AI-Controllable Smart Home: MCP-HASS and the Model Context Protocol
Hook
Your AI assistant can now turn off your lights, but making that reliable required solving a problem most developers never think about: what happens when your smart home has 500 entities and your LLM only has a 200K token context window?
Context
The Model Context Protocol is Anthropic's answer to a growing problem in AI tooling: every AI assistant needs its own integration layer for external services. Instead of building a Claude integration, a ChatGPT integration, and separate connectors for every new LLM that launches, MCP provides a standardized protocol for connecting AI assistants to data sources and tools.
Home Assistant users face a parallel challenge. With 2,500+ integrations spanning everything from Philips Hue to Tesla vehicles, the platform has become the universal translator for smart home devices. But controlling it programmatically means wrestling with two separate APIs—REST for operational data, WebSocket for metadata—each with different authentication flows and reconnection semantics. MCP-HASS sits at this intersection, translating Home Assistant's dual-API complexity into a clean MCP interface that any protocol-compliant AI assistant can consume. Built by Max Rousseau on FastMCP, it's essentially a smart adapter that handles connection management, token budget awareness, and the ceremonial overhead of keeping both APIs happy simultaneously.
Technical Insight
The architectural elegance of MCP-HASS lies in how it handles Home Assistant's split personality. Home Assistant's REST API handles entity states and service calls—the operational "do things now" interface. Its WebSocket API manages the registry system: areas ("Living Room"), devices ("Hue Bridge"), and entity metadata. Most Home Assistant libraries pick one or force you to manage both separately. MCP-HASS maintains both connections through a single HomeAssistantClient class with self-healing logic.
Here's what that dual-connection setup looks like in practice:
# Simplified from the actual HomeAssistantClient implementation
class HomeAssistantClient:
def __init__(self, url: str, token: str):
self.rest_url = url
self.headers = {"Authorization": f"Bearer {token}"}
self.ws_client = None
self._ensure_ws_connection()
async def get_states(self) -> list[dict]:
# REST API for operational data
response = await self.session.get(
f"{self.rest_url}/api/states",
headers=self.headers
)
return await response.json()
async def get_areas(self) -> list[dict]:
# WebSocket for registry metadata
await self._ensure_ws_connection()
return await self.ws_client.send_json({
"type": "config/area_registry/list"
})
The token-aware response trimming is where things get interesting for production deployments. A typical Home Assistant installation with 200+ entities can generate response payloads exceeding 50K tokens when you request full state dumps. MCP-HASS implements configurable token limits that intelligently truncate responses:
# From the tool context implementation
class ToolContext:
def __init__(self, client: HomeAssistantClient, max_tokens: int = 100000):
self.client = client
self.max_tokens = max_tokens
def truncate_response(self, data: list[dict]) -> list[dict]:
"""Keep responses under token budget by removing items"""
estimated_tokens = len(json.dumps(data)) // 4 # Rough estimate
if estimated_tokens <= self.max_tokens:
return data
# Truncate and add metadata about what was removed
ratio = self.max_tokens / estimated_tokens
keep_count = int(len(data) * ratio)
return data[:keep_count] + [{
"_truncated": True,
"removed_count": len(data) - keep_count
}]
The deployment flexibility deserves attention. MCP servers can run in two modes: stdio (standard input/output) for local process communication, or HTTP for networked access. MCP-HASS supports both through FastMCP's transport abstraction. For Claude Desktop integration, you'd configure stdio transport in your Claude config:
{
"mcpServers": {
"home-assistant": {
"command": "uvx",
"args": ["mcp-hass"],
"env": {
"HASS_URL": "http://homeassistant.local:8123",
"HASS_TOKEN": "your-long-lived-access-token"
}
}
}
}
For containerized deployments serving multiple clients, switch to HTTP transport and the same server code works without modification—FastMCP handles the protocol translation.
The tool inventory reveals the breadth of Home Assistant operations exposed: list_entities and describe_entity for discovery, get_state and set_state for entity manipulation, call_service for arbitrary Home Assistant actions, list_areas and list_devices for topology mapping, even take_camera_snapshot with intelligent downsampling to keep image tokens manageable. The get_config_yaml tool is particularly clever—it exposes Home Assistant's YAML configuration through MCP, enabling AI assistants to understand your automation logic and suggest improvements.
The self-healing WebSocket connection management uses exponential backoff with jitter, essential for reliability in long-running deployments where network hiccups are inevitable. When the WebSocket connection drops, registry-dependent operations automatically trigger reconnection attempts before failing, transparent to the calling AI assistant.
Gotcha
The single-token authentication model is a significant limitation for multi-tenant deployments. When running MCP-HASS in HTTP mode to serve multiple AI clients, all requests use the same Home Assistant long-lived access token. There's no per-client authentication or authorization—everyone gets full access to your entire Home Assistant instance. For home use this is fine, but enterprise scenarios or home automation consultants serving multiple properties would need to deploy separate MCP-HASS instances per Home Assistant installation.
Camera snapshot handling, while token-aware, lacks fine-grained control over image quality and format. The intelligent downsampling algorithm reduces image dimensions to keep token counts reasonable, but you can't specify JPEG quality levels or switch to more efficient formats like WebP. For installations with many cameras or use cases requiring specific image fidelity (facial recognition, license plate reading), you might need to fork and customize the snapshot tool. The truncation logic for large entity lists is also somewhat blunt—it removes items from the end of the array rather than using smarter strategies like prioritizing recently changed entities or grouping by area.
Verdict
Use MCP-HASS if you're building AI-driven home automation workflows with Claude Desktop or other MCP-compatible assistants, especially if you have 100+ entities where token management becomes critical. It's the fastest path from "AI assistant" to "AI assistant that actually controls my house" without writing Home Assistant API boilerplate. The dual-transport support makes it valuable for both personal local setups and containerized deployments. Skip it if you need per-user access control for multi-tenant scenarios, require Home Assistant operations beyond the public API surface (custom component internals, add-on management), or if your use case is simple enough that Home Assistant's webhooks or direct REST API calls would suffice. Also skip if you're not in the Home Assistant ecosystem—this is purpose-built for HA and won't help with SmartThings, Hubitat, or other platforms.