HA Admin MCP
An MCP server for safely previewing, creating, validating, editing and rolling back AI-managed Home Assistant automations.
README
HA Admin MCP
A self-hosted Model Context Protocol (MCP) server for safely previewing, creating, validating, editing and rolling back AI-managed Home Assistant automations.
This is an early open-source release. Every user runs their own instance against their own Home Assistant installation. There is no hosted service, central MCP endpoint, telemetry or cloud dependency.
Why it exists
Home Assistant's official MCP server is well suited to discovering entities, understanding state and performing normal day-to-day control.
HA Admin MCP provides a complementary configuration-administration layer:
AI client
|
+-- Official Home Assistant MCP
| +-- entities
| +-- state and context
| +-- normal control
|
+-- HA Admin MCP
+-- AI automation lifecycle
+-- validation
+-- backups and rollback
+-- audit logging
It is not a replacement for Home Assistant's official MCP server.
Features
- Streamable HTTP MCP transport
- Separate bearer authentication for MCP clients
- Home Assistant API authentication
- Isolated AI-managed automation file
- Automation preview and structural validation
- Create, update and delete operations
- Enable, disable and manual trigger operations
- Full Home Assistant configuration validation before reload
- Transactional writes with file locking and atomic replacement
- Timestamped backups, diffs and rollback
- JSON Lines mutation audit log with credential redaction
- Home Assistant and file health checks
- Read-only integration tests
- Hardened Docker deployment:
- non-root UID/GID 10001
- read-only container root
- all Linux capabilities dropped
- no Docker socket
- no privileged mode
- only dedicated data mounts
The reference deployment is tested with Home Assistant 2026.7.4. Other recent Home Assistant versions may work but are not yet part of a compatibility matrix.
Tools
The server currently exposes 15 tools:
ha_healthlist_ai_automationsget_ai_automationpreview_ai_automationcreate_ai_automationupdate_ai_automationdelete_ai_automationenable_ai_automationdisable_ai_automationtrigger_ai_automationvalidate_home_assistantreload_ai_automationsdiff_ai_automationslist_ai_automation_backupsrollback_ai_automations
New automations default to disabled unless the caller explicitly requests an enabled initial state.
Safety model
HA Admin MCP never needs access to Home Assistant's normal
automations.yaml. AI-managed automations live in a separate file and are
loaded under a separate labelled automation configuration.
Every file mutation follows this sequence:
AI requests a change
|
v
parse and structurally validate
|
v
lock file and create backup
|
v
write temporary file and atomically replace
|
v
run full Home Assistant configuration validation
|
+----+----+
| |
failure success
| |
restore reload automations
old bytes |
| v
validate verify Home Assistant health
and reload
A validation failure restores the exact previous bytes. Rollback itself creates a new backup before restoring an older version. Mutations and runtime actions are written to the rotating audit log.
This design reduces risk; it does not make arbitrary automation changes safe. Review generated automations before enabling them.
See ARCHITECTURE.md for the full trust and failure boundaries.
Requirements
- Docker Engine with Docker Compose v2
- A Home Assistant installation reachable from the container
- A Home Assistant long-lived access token from an appropriately privileged account
- Write access to one dedicated AI automation directory
- An MCP client that supports Streamable HTTP and bearer authentication
Home Assistant preparation
Back up the Home Assistant configuration before changing it.
Keep the existing UI automation include and add a separately labelled include
to configuration.yaml:
automation: !include automations.yaml
automation ai_managed: !include ai_managed/ai_automations.yaml
Then create the dedicated file within the Home Assistant configuration directory:
mkdir -p /path/to/home-assistant/config/ai_managed
printf '[]\n' > /path/to/home-assistant/config/ai_managed/ai_automations.yaml
The directory mounted at /ha-ai must be writable by container UID/GID 10001.
Choose permissions that also allow Home Assistant to read the file. Do not
mount the complete Home Assistant configuration directory into HA Admin MCP.
Run Home Assistant's configuration validation before restarting or reloading after adding the labelled include.
Installation
-
Clone the repository:
git clone https://github.com/paulcakeface/ha-admin-mcp.git cd ha-admin-mcp -
Create the local environment file:
cp .env.example .env chmod 600 .env -
Generate a dedicated MCP client token:
openssl rand -hex 32Put the generated value in
MCP_CLIENT_TOKEN. Do not reuse the Home Assistant token. -
Edit
.env:- Set
HA_URLto a Home Assistant address reachable from the container. - Set
HA_TOKENto a Home Assistant long-lived access token. - Set
MCP_CLIENT_TOKENto the independently generated random token. - Set
HA_AI_DIRECTORYto the host's dedicatedai_manageddirectory.
- Set
-
Make the persistent directories writable by UID/GID 10001:
mkdir -p data/backups data/logs sudo chown -R 10001:10001 data/backups data/logs sudo chown -R 10001:10001 /path/to/home-assistant/config/ai_managed -
Build and start the service:
docker compose up -d --build docker compose ps -
Check the deliberately minimal container health endpoint:
curl --fail http://127.0.0.1:8765/healthzDetailed Home Assistant and automation-file status is available only through the authenticated
ha_healthMCP tool.
The default endpoint is http://127.0.0.1:8765/mcp.
Home Assistant networking
HA_URL must work from inside the HA Admin MCP container.
- Home Assistant Container: use a shared Docker network hostname, a LAN
address, or
http://host.docker.internal:8123. - Home Assistant OS or Supervised: use an address routable from the Docker host, normally a trusted LAN address or HTTPS hostname.
- Home Assistant Core: use the address on which Home Assistant is listening.
The Compose file includes the Linux host-gateway mapping for
host.docker.internal; using it is optional. A shared Docker network can be
added in a local Compose override without changing the project.
Configuration
| Variable | Purpose | Default |
|---|---|---|
HA_URL |
Home Assistant API base URL reachable from the container | empty |
HA_TOKEN |
Home Assistant long-lived access token | empty |
MCP_CLIENT_TOKEN |
Independent MCP client bearer token; minimum 32 bytes | required |
HA_AI_DIRECTORY |
Host directory mounted at /ha-ai by Compose |
./ha-ai |
HA_AUTOMATIONS_FILE |
AI automation file inside the container | /ha-ai/ai_automations.yaml |
BACKUP_DIR |
Backup directory inside the container | /data/backups |
LOG_DIR |
Audit-log directory inside the container | /data/logs |
LOG_LEVEL |
Application log level | INFO |
MCP_HOST |
Listen address inside the container | 0.0.0.0 |
MCP_PORT |
Listen port inside the container | 8000 |
MCP_PUBLISH_HOST |
Host address to which Compose publishes the port | 127.0.0.1 |
MCP_PUBLISH_PORT |
Published host port | 8765 |
MCP_ISSUER_URL |
Static-auth issuer identifier; use the public base URL remotely | http://127.0.0.1:8765 |
MCP_ALLOWED_HOSTS |
Comma-separated Host header allowlist | 127.0.0.1:*,localhost:* |
MCP_ALLOWED_ORIGINS |
Comma-separated Origin header allowlist | local origins |
For a remote endpoint at https://ha-admin.example.com/mcp, add
ha-admin.example.com to MCP_ALLOWED_HOSTS, add
https://ha-admin.example.com to MCP_ALLOWED_ORIGINS, and set
MCP_ISSUER_URL=https://ha-admin.example.com.
Authentication
There are two separate trust directions:
MCP client -- MCP_CLIENT_TOKEN --> HA Admin MCP
HA Admin MCP -- HA_TOKEN -------> Home Assistant API
Never reuse one token for both purposes.
MCP_CLIENT_TOKEN is compared in constant time. Invalid bearer bursts receive
a bounded application-level delay. Credentials are never intentionally
returned in errors and both configured secrets are redacted from mutation audit
records.
Protect .env as a secret. It is ignored by Git and excluded from the Docker
build context.
Connecting Codex
Codex supports Streamable HTTP MCP servers and can load the bearer token from an environment variable:
export HA_ADMIN_MCP_TOKEN='your-mcp-client-token'
codex mcp add ha-admin-mcp \
--url http://127.0.0.1:8765/mcp \
--bearer-token-env-var HA_ADMIN_MCP_TOKEN
codex mcp list
Equivalent ~/.codex/config.toml:
[mcp_servers.ha-admin-mcp]
url = "http://127.0.0.1:8765/mcp"
bearer_token_env_var = "HA_ADMIN_MCP_TOKEN"
Keep the token in the process environment or a protected launcher/secret
manager, not in config.toml. For remote access, replace the URL with the
user's own HTTPS endpoint.
See client configuration for a generic example and the complementary official Home Assistant MCP layout.
Remote and private access
Remote access is optional. The default Compose binding is loopback-only and requires no domain.
Supported deployment patterns include:
- local host:
http://127.0.0.1:8765/mcp - trusted LAN or private DNS:
http://home-server.local:8765/mcp - Tailscale or another private VPN
- SSH local forwarding
- an HTTPS reverse proxy
- Cloudflare Tunnel or another secure HTTPS tunnel
Do not directly expose raw TCP port 8765 to the public internet. For remote
clients, use HTTPS, preserve the Authorization header, disable caching and
proxy buffering, and allow Streamable HTTP's GET/POST behaviour and streaming
responses.
Cloudflare Tunnel is one optional approach, not a dependency. See remote access.
Example workflow
A harmless conceptual request might be:
Create an automation that sends a persistent Home Assistant notification at sunset, but leave it disabled until I approve it.
The client should first call preview_ai_automation. Creation then backs up the
current AI file, writes and validates the candidate, reloads automations and
verifies health. The client can inspect the result before explicitly enabling
the automation.
Backups and logs
Backups are stored under data/backups by the default Compose deployment. Use
list_ai_automation_backups, diff_ai_automations and
rollback_ai_automations rather than editing backup files manually.
Mutation audit records are JSON Lines under:
data/logs/mutations.jsonl
Both locations are ignored by Git.
Testing
Create a development environment:
python3 -m venv .venv
.venv/bin/pip install -r requirements-dev.txt
Run the standard checks:
.venv/bin/ruff format --check .
.venv/bin/ruff check .
.venv/bin/mypy app scripts
.venv/bin/pytest -q
docker build -t ha-admin-mcp:test .
The real-API integration tests are read-only and require explicit environment variables:
export HA_INTEGRATION_URL='http://homeassistant:8123'
export HA_INTEGRATION_TOKEN='your-test-token'
.venv/bin/pytest -q -m integration
unset HA_INTEGRATION_TOKEN
scripts/live_acceptance.py is not part of the normal suite. It deliberately
creates, enables, triggers and removes a harmless automation in the isolated AI
file. Read the script and use a disposable test instance before running it.
Troubleshooting
Home Assistant authentication fails
Confirm HA_TOKEN is a valid long-lived access token and that HA_URL is
reachable from inside the container:
docker compose exec ha-admin-mcp python -c \
"import os, urllib.request; r=urllib.request.Request(os.environ['HA_URL'] + '/api/', headers={'Authorization': 'Bearer ' + os.environ['HA_TOKEN']}); print(urllib.request.urlopen(r).status)"
Do not paste the token into an issue or command output.
MCP returns HTTP 401
The client's bearer value does not exactly match MCP_CLIENT_TOKEN, or the
client did not send an Authorization: Bearer header. Restart the MCP client
after exporting its token environment variable.
MCP returns HTTP 421 or 403
Add the exact hostname to MCP_ALLOWED_HOSTS. If the client sends an Origin
header, add that exact origin to MCP_ALLOWED_ORIGINS. Do not disable DNS
rebinding protection globally.
Home Assistant validation rejects a change
The service automatically restores the previous bytes. Inspect the MCP error, Home Assistant logs and the created backup. Correct the candidate and preview it again.
Permission denied on the AI file
Confirm that /ha-ai maps to the intended dedicated directory and that UID/GID
10001 can create temporary files and atomically rename them there.
Reverse proxy or handshake problems
Verify that the proxy:
- forwards
Authorization,Content-Type,Acceptand MCP headers - permits GET and POST at
/mcp - does not cache, buffer or transform responses
- has a suitable streaming/read timeout
- forwards the expected Host header
Security
MCP administration access can create and trigger Home Assistant automations. Treat it as privileged access. Read SECURITY.md before exposing the service beyond a trusted host.
Roadmap
Potential future work, not functionality claimed by this release:
- standards-compliant OAuth
- Home Assistant App/add-on packaging
- a companion HACS integration for setup and diagnostics
- richer onboarding and audit visibility
- Home Assistant trace analysis
- a human-approval automation lifecycle interface
Docker remains the primary installation method for this release.
Contributing
Contributions are welcome. See CONTRIBUTING.md.
Licence
Licensed under the Apache License 2.0.
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。