# Home Assistant MCP Server — Smart Home Control for AI Agents (`muhammadafzal/home-assistant-mcp-server`) Actor

MCP server that lets AI agents read states and control devices on a Home Assistant instance. Get states, list entities/areas/devices, call services (lights, switches, climate, media), render templates, and query history. Connect Claude, Cursor, ChatGPT, or any MCP client.

- **URL**: https://apify.com/muhammadafzal/home-assistant-mcp-server.md
- **Developed by:** [Muhammad Afzal](https://apify.com/muhammadafzal) (community)
- **Categories:** AI, Automation, MCP servers
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $25.00 / 1,000 mcp tool executions

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Home Assistant MCP Server — Smart Home Control for AI Agents

> MCP server exposing **10 Home Assistant tools** for AI agents. Connect Claude, Cursor, ChatGPT, n8n, OpenAI Agents SDK, or any MCP-compatible client to read states and control devices on your Home Assistant instance. Talk to your home in plain language.

### What it does

This Actor runs a [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server in Standby mode on the Apify platform. It connects to your Home Assistant instance through the official WebSocket API (`/api/websocket`) using a long-lived access token you create — no browser, no scrapers, no third-party services.

| Tool | What it returns |
|------|-----------------|
| `get_entity_state` | Current state, attributes, and friendly name of one entity (`light.living_room`) |
| `get_states` | Entity states filtered by domain, area, or entity IDs — "what lights are on?" |
| `get_areas` | All areas/rooms with their area IDs |
| `get_area_entities` | Every entity and its live state in a room — "what's in the living room?" |
| `get_devices` | Physical devices with manufacturer, model, and assigned area |
| `call_service` | Call any service to control devices: lights, switches, climate, media, scripts, automations, locks |
| `list_services` | Discover the exact service names and parameters an integration supports |
| `get_config` | Instance version, location, timezone, unit system — also a connection health check |
| `get_entity_history` | Time-series history for an entity — "was the garage open at 3am?" |
| `render_template` | Render sandboxed Jinja2 templates for advanced read-only queries |

### Use cases

- **AI home control** — "turn off the living room lights", "set the thermostat to 21°C"
- **Smart home assistants** — voice/chat agents that read sensors and act on rooms
- **Environment-aware agents** — agents that check occupancy, temperature, or energy before deciding
- **Accessibility** — hands-free control via AI for assisted-living scenarios
- **Automation scripting** — n8n/Make flows that trigger Home Assistant services

### Setup: 2 steps

#### 1. Create a Home Assistant long-lived access token

In Home Assistant: **Profile → Security → Long-lived access tokens → Create token**. Copy it — you will not see it again.

#### 2. Make your instance reachable and connect

The actor runs in Apify's cloud, so your Home Assistant must be reachable from the internet. Any of these works:

- **Nabu Casa** (recommended) — `https://<your-id>.ui.nabu.casa`
- **Cloudflare Tunnel / DuckDNS / public reverse proxy** — `https://home.example.com` (add `:8123` if on a non-standard port)
- **Self-hosted with self-signed certs** — set `verifyTls=false` (input) or `HOME_ASSISTANT_VERIFY_TLS=false`

Then add the server to your MCP client:

```json
{
    "mcpServers": {
        "home-assistant-mcp-server": {
            "url": "https://muhammadafzal--home-assistant-mcp-server.apify.actor/mcp",
            "headers": {
                "Authorization": "Bearer <YOUR_APIFY_API_TOKEN>"
            }
        }
    }
}
```

Get your Apify API token from [Apify Console → Account → Integrations](https://console.apify.com/account/integrations).

#### Passing your credentials

Credentials are resolved in this order: **tool arguments → Actor input → environment variables** (`HOME_ASSISTANT_URL`, `HOME_ASSISTANT_TOKEN`).

- **Self-hosted Standby** (recommended): set the Actor input fields `homeAssistantUrl` and `homeAssistantToken` (or the env vars) once — tool calls need no credentials.
- **Hosted MCP endpoint**: pass `homeAssistantUrl` and `homeAssistantToken` to each tool call. Agents remember them for the conversation.
- **Read-only safety**: enable the `readOnly` input (or `HOME_ASSISTANT_READ_ONLY=true`) to disable `call_service` so the agent can never change device state.

Your token is **never logged, never written to the dataset**, and never stored beyond the call that uses it.

### Pricing

This Actor uses pay-per-event pricing:

| Event | Price | When |
|-------|-------|------|
| Actor Start | $0.00005 per event | one per GB of memory, minimum one |
| MCP Tool Execution | $0.025 per call | every successful read/data tool call |
| MCP Service Call | $0.05 per call | every successful `call_service` action |

**Discovery is free** — `initialize`, `tools/list`, `ping`, and resource listings are never charged, so agents can connect and inspect tools at no cost.

**Typical cost:** "What's the temperature?" = 1 read call ≈ $0.025. "Turn off the living room lights" = 1 service call ≈ $0.05. A full home status overview ≈ $0.025–$0.075.

### Example conversations

```
User:  What's the current temperature in the living room?
Agent: get_entity_state(entityId="sensor.living_room_temperature")
       -> 21.4 °C, last updated 2 minutes ago

User:  Turn off all the lights in the kitchen.
Agent: get_areas() -> kitchen
       get_area_entities(areaId="kitchen") -> lights in kitchen
       call_service(domain="light", service="turn_off", entityIds=["light.kitchen_1", "light.kitchen_2"])
       -> Called light.turn_off on light.kitchen_1, light.kitchen_2.

User:  Was the front door opened during the night?
Agent: get_entity_history(entityId="binary_sensor.front_door", startTime="2026-08-02T22:00:00", endTime="2026-08-03T06:00:00")
       -> 3 transitions from closed to open
```

### Input

In Standby/MCP mode the input fields configure connection defaults. In batch mode they run a connectivity self-test.

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| homeAssistantUrl | string | `""` | Base URL of your instance, e.g. `https://abcd1234.ui.nabu.casa` |
| homeAssistantToken | string | `""` | Long-lived access token (never logged/saved) |
| readOnly | boolean | `false` | Disable `call_service` for read-only access |
| verifyTls | boolean | `true` | Set to false for self-signed certificates |

### Output

Every tool call returns a structured JSON object (flat, stable keys, ISO 8601 timestamps) and is also stored in the default dataset for auditing. Errors follow MCP's `isError` convention with actionable text — e.g. a rejected token tells you to create a new long-lived token, and an unknown entity points you to `get_states`.

### Technical details

- **Language:** Python 3.12
- **Framework:** [FastMCP](https://gofastmcp.com/) + [uvicorn](https://www.uvicorn.org/)
- **Transport:** Streamable HTTP (MCP standard)
- **Mode:** Standby (always-ready, auto-scales with demand)
- **Connection:** Home Assistant WebSocket API (`/api/websocket`), official and stable
- **Endpoint:** `https://muhammadafzal--home-assistant-mcp-server.apify.actor/mcp`

### Security notes

- The long-lived token grants full access to your instance — treat it like a password.
- Use `readOnly` mode for assistants that should observe but never change your home.
- `render_template` is sandboxed by Home Assistant and cannot call services.
- Service calls are charged separately and described as actions so agents confirm intent before executing.

### Export scraped data, run the scraper via API, schedule and monitor runs, or integrate with other tools

Apify gives you access to the raw data, APIs, webhooks, and automation tools you need to build data pipelines. Export to JSON, CSV, or Excel, or send to Google Sheets, Airtable, or any webhook via integrations.

### Support

Found a bug or have a feature request? [Open an issue](https://apify.com/muhammadafzal/home-assistant-mcp-server) on the Apify Store page.

# Actor input Schema

## `homeAssistantUrl` (type: `string`):

Base URL of your Home Assistant instance, reachable from the internet. Accepted formats: 'https://abcd1234.ui.nabu.casa' (Nabu Casa), 'https://home.example.com:8123', or a Cloudflare Tunnel URL. Leave empty when calling tools with the per-call homeAssistantUrl argument. NOT an entity ID — entity IDs belong in the entityId tool argument.

## `homeAssistantToken` (type: `string`):

Long-lived access token created in Home Assistant under Profile > Security > Long-lived access tokens. This is the token the server uses to read states and control devices, so it grants full access to your instance. Never share it; it is never logged or written to the dataset. Leave empty when passing the per-call homeAssistantToken argument.

## `readOnly` (type: `boolean`):

When enabled, the call\_service tool is disabled so the server can only read data and cannot change any device state. Use for safety when granting an agent access to an instance you do not want changed. Defaults to false. Can also be set with the HOME\_ASSISTANT\_READ\_ONLY environment variable.

## `verifyTls` (type: `boolean`):

When enabled, HTTPS/WSS connections are validated against the public certificate chain. Set to false for instances with self-signed certificates (common on self-hosted setups). Defaults to true. Can also be set with the HOME\_ASSISTANT\_VERIFY\_TLS environment variable.

## Actor input object example

```json
{
  "homeAssistantUrl": "https://abcd1234.ui.nabu.casa",
  "homeAssistantToken": "",
  "readOnly": false,
  "verifyTls": true
}
```

# Actor output Schema

## `mcpEndpoint` (type: `string`):

The MCP server endpoint. Connect MCP clients (Claude, Cursor, etc.) to this URL with an Apify API token as Bearer auth.

## `toolResults` (type: `string`):

Records from MCP tool calls (entity states, service call confirmations, config, etc.), stored in the default dataset.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {};

// Run the Actor and wait for it to finish
const run = await client.actor("muhammadafzal/home-assistant-mcp-server").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {}

# Run the Actor and wait for it to finish
run = client.actor("muhammadafzal/home-assistant-mcp-server").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call muhammadafzal/home-assistant-mcp-server --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,muhammadafzal/home-assistant-mcp-server"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/I95Bogmarw38aKZJw/builds/01og0iBMK9AXCQk0C/openapi.json
