HA Admin MCP

HA Admin MCP

An MCP server for safely previewing, creating, validating, editing and rolling back AI-managed Home Assistant automations.

Category
Visit Server

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_health
  • list_ai_automations
  • get_ai_automation
  • preview_ai_automation
  • create_ai_automation
  • update_ai_automation
  • delete_ai_automation
  • enable_ai_automation
  • disable_ai_automation
  • trigger_ai_automation
  • validate_home_assistant
  • reload_ai_automations
  • diff_ai_automations
  • list_ai_automation_backups
  • rollback_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

  1. Clone the repository:

    git clone https://github.com/paulcakeface/ha-admin-mcp.git
    cd ha-admin-mcp
    
  2. Create the local environment file:

    cp .env.example .env
    chmod 600 .env
    
  3. Generate a dedicated MCP client token:

    openssl rand -hex 32
    

    Put the generated value in MCP_CLIENT_TOKEN. Do not reuse the Home Assistant token.

  4. Edit .env:

    • Set HA_URL to a Home Assistant address reachable from the container.
    • Set HA_TOKEN to a Home Assistant long-lived access token.
    • Set MCP_CLIENT_TOKEN to the independently generated random token.
    • Set HA_AI_DIRECTORY to the host's dedicated ai_managed directory.
  5. 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
    
  6. Build and start the service:

    docker compose up -d --build
    docker compose ps
    
  7. Check the deliberately minimal container health endpoint:

    curl --fail http://127.0.0.1:8765/healthz
    

    Detailed Home Assistant and automation-file status is available only through the authenticated ha_health MCP 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, Accept and 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.

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured
E2B

E2B

Using MCP to run code via e2b.

Official
Featured