A FastMCP server that exposes Home Assistant entities and services to AI assistants via the Model Context Protocol (MCP).
Alternative to the official integration: Home Assistant ships a built-in MCP Server integration that exposes all entities and services. This project is an intentional alternative for users who want an external, allowlist-gated server — useful when you want strict control over what an AI assistant can see and do, or when running the MCP server outside the Home Assistant process.
An allowlist gates every operation — the server rejects any entity or service not permitted by the config file before the request reaches Home Assistant.
| Tool | Description |
|---|---|
get_entity_state |
Returns the current state of an allowed entity as JSON |
call_ha_service |
Calls an allowed Home Assistant service |
list_allowed_entities |
Lists all entity IDs on the allowlist |
list_allowed_services |
Lists all services on the allowlist |
uv pip install -e .
# or
pip install -e .Copy the example allowlist and edit it:
cp allowlist.example.yaml allowlist.yamlAdd the entity IDs and services you want to expose. Anything not listed is blocked.
| Variable | Required | Description |
|---|---|---|
HA_URL |
Yes | Base URL of your Home Assistant instance (e.g. http://homeassistant.local:8123) |
HA_TOKEN |
Yes | Long-lived access token from your HA profile |
HA_ALLOWLIST |
No | Path to allowlist YAML file (default: ./allowlist.yaml) |
export HA_URL="http://homeassistant.local:8123"
export HA_TOKEN="your-long-lived-token"
export HA_ALLOWLIST="./allowlist.yaml"ha-mcpOr directly:
python -m ha_mcp.serverIn your MCP config (e.g. ~/.claude/claude_desktop_config.json):
{
"mcpServers": {
"ha-mcp": {
"command": "ha-mcp",
"env": {
"HA_URL": "http://homeassistant.local:8123",
"HA_TOKEN": "your-token-here",
"HA_ALLOWLIST": "/path/to/allowlist.yaml"
}
}
}
}Entities are split into two permission tiers:
read— allowed forget_entity_stateonly (sensors, weather, read-only state)read_write— allowed for bothget_entity_stateand as targets incall_ha_service
entities:
read:
- weather.forecast_home
- sensor.*
read_write:
- light.*
- climate.living_room
services:
- light.turn_on
- light.turn_off
- climate.set_temperatureService identifiers use the format {domain}.{service}.
fnmatch-style wildcards are supported in all sections. * matches any sequence of characters; ? matches a single character.
Exact entries and wildcard patterns can be mixed in the same list.
When call_ha_service is called with an entity_id in service_data (string or list), each entity is checked against the read_write list. Entities in read cannot be service targets.
- The server never exposes raw Home Assistant error responses to callers — only sanitized status descriptions.
HA_TOKENshould be a dedicated, minimal-scope token. Do not use your main account token.- Keep the allowlist as narrow as possible for your use case.