home-assistant-mcp
by mattmaas
README.md
# home-assistant-mcp
A [Model Context Protocol](https://modelcontextprotocol.io) server for
[Home Assistant](https://www.home-assistant.io/) over its REST API, in ~250 lines of
TypeScript with one dependency.
Two layers:
1. **Generic tools** — read states, call any service. Enough for an agent to operate a home
it has never seen.
2. **A scene catalog** (optional) — a JSON file of *named presets with plain-English
descriptions* that the agent can list and apply by name. "Make it cinema" becomes
`ha_scene {"name":"cinema"}` instead of the model guessing 18 bulb entity ids and color
temperatures. Presets are just `script.*` or `scene.*` entities you already have.
## Tools
| Tool | Purpose |
|---|---|
| `ha_ping` | Confirm the API is reachable and the token is accepted. |
| `ha_list_states` | List entity states; filter by domain / entity_id prefix / limit. |
| `ha_get_state` | Full state + attributes for one entity. |
| `ha_call_service` | Call any service (`light.turn_on`, `media_player.volume_set`, …) with optional target and data. |
| `ha_list_services` | All services grouped by domain. |
| `ha_list_scenes` | *(only when `HA_SCENES_FILE` is set)* List catalog presets. |
| `ha_scene` | *(only when `HA_SCENES_FILE` is set)* Apply a preset by name — enum-constrained so the model can't invent one. |
## Setup
```bash
npm install
npm run build # tsc -> dist/server.js
HA_URL=http://homeassistant.local:8123 HA_TOKEN=... node dist/server.js
```
| Variable | Required | Default | Purpose |
|---|---|---|---|
| `HA_URL` | no | `http://homeassistant.local:8123` | Home Assistant base URL |
| `HA_TOKEN` | **yes** | — | Long-lived access token (Profile → Security) |
| `HA_SCENES_FILE` | no | — | Path to a scene catalog JSON (see `scenes.example.json`) |
MCP client registration (stdio):
```json
{
"mcpServers": {
"home-assistant": {
"command": "node",
"args": ["/path/to/home-assistant-mcp/dist/server.js"],
"env": {
"HA_URL": "http://homeassistant.local:8123",
"HA_TOKEN": "<token>",
"HA_SCENES_FILE": "/path/to/scenes.json"
}
}
}
}
```
## Scene catalog pattern
The example catalog is the 13-theme setup this was written for. Each preset is layered in
Home Assistant so the same name works from any surface:
```
scene.home_<name> canonical light state (scenes.yaml)
script.home_<name> thin wrapper -> scene.turn_on, plus any extras (scripts.yaml)
ha_scene <name> MCP -> script.turn_on via REST
```
Anything else (n8n, a dashboard button, a voice assistant) can call the same script, so the
agent and the humans share one vocabulary. Keep the descriptions honest — they are what the
model reads to choose.
## Notes
- `HA_TOKEN` is a secret; pass it via environment, never commit it.
- Use on a trusted network or via a VPN; this server does not add authentication of its own.
## License
MIT — see [LICENSE](LICENSE).
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues