Skip to main content
Glama
lemanjo

Home Assistant Admin MCP

by lemanjo

Home Assistant Admin MCP

Home Assistant Admin MCP lets AI tools inspect, troubleshoot, control, and manage a Home Assistant installation. It works with MCP clients such as OpenCode, Codex, and Claude Code.

The server connects to Home Assistant with a long-lived access token. It can also use a restricted mount of the Home Assistant configuration directory for YAML changes, checkpoints, and local Git history.

WARNING

admin mode can change Home Assistant configuration and restart Home Assistant. Start with read_only, use a dedicated Home Assistant account, and expose the MCP port only to devices you trust.

What it can do

  • List states, devices, entities, areas, integrations, services, history, logs, and traces.

  • Find unavailable or misconfigured entities, broken automations, missing references, and other common problems.

  • Control devices and run Home Assistant services.

  • Manage automations, scripts, scenes, helpers, areas, registries, and selected integration settings.

  • Read and patch approved YAML files, create checkpoints, validate changes, and roll back failed changes.

It does not manage Home Assistant add-ons, Supervisor backups, Docker, or the host operating system. It cannot run shell commands or read arbitrary files.

Some administrative tools use Home Assistant interfaces that can change between Home Assistant releases. Test administrative changes after upgrading Home Assistant.

Related MCP server: hass-mcp-server

Permission modes

Set MCP_MODE to one of these values:

Mode

What it allows

read_only

Reading, searches, diagnostics, logs, history, and validation.

control

Everything above, plus device control and normal Home Assistant service calls.

admin

Everything above, plus persistent configuration changes, reloads, and restart.

The mode is a hard limit. An MCP client cannot raise it.

High-impact actions require confirm: true by default. Locks, alarms, sirens, and covers with garage or gate in the entity ID also require confirmation. These rules can be changed in config.yaml.

Git-backed configuration history

Git support gives file-backed Home Assistant changes an audit trail. After a successful YAML change, the server can create a local commit containing only the files changed by that operation. This makes it easier to see what an AI client changed, compare the working tree with committed configuration, and safely undo the latest service-created commit.

Git complements the transaction checkpoints in .ha-mcp/backups: checkpoints support file recovery during validation failures, while Git provides readable long-term history and diffs. Neither replaces a Home Assistant backup.

Prepare the repository

The Home Assistant configuration directory must already be inside a Git repository. The server deliberately does not initialize repositories, clone, pull, push, or configure remotes. With the standard Docker and Unraid mounts, the simplest arrangement is to initialize the repository directly in the directory mounted at /ha-config.

On the Docker host, create a baseline commit before allowing MCP configuration changes. Review the ignore rules and tracked files for your installation; do not commit secrets or Home Assistant runtime data.

cd /absolute/path/to/home-assistant/config
git init
cat > .gitignore <<'EOF'
.storage/
.ha-mcp/
secrets.yaml
secrets.yml
home-assistant_v2.db*
*.log*
EOF
git add .gitignore configuration.yaml
git -c user.name="Home Assistant owner" \
  -c user.email="owner@example.com" \
  commit -m "Baseline Home Assistant configuration"

Add other YAML files and allowed directories, such as automations.yaml or packages/, only after checking that they contain no credentials. Existing repositories only need to be accessible through the configuration mount.

The container's PUID and PGID must be able to read and write both the tracked files and the repository's .git directory. You can verify access using the same container identity:

docker compose run --rm --entrypoint /usr/bin/git hac-mcp \
  -C /ha-config status --short

Enable the feature in .env:

HA_GIT_ENABLED=true

It is enabled by default in the supplied configuration. Set HA_GIT_ENABLED=false if the mounted directory is not a repository and you only want transaction checkpoints.

Set the identity used for service-created commits in config.yaml if you want to distinguish installations or environments:

git:
  enabled: true
  authorName: Home Assistant Admin MCP
  authorEmail: home-assistant-admin-mcp@example.invalid

How it behaves

  • patch_yaml_file commits by default when Git is enabled. A custom commit_message can describe the reason for the change.

  • A dry run returns the proposed diff without writing files or creating a commit.

  • The server creates a checkpoint, writes atomically, validates with Home Assistant, performs the requested reload and health check, and only then creates the Git commit.

  • A commit includes only the configuration paths selected by that operation. Unrelated staged or working-tree changes are left alone.

  • If a target file already had uncommitted changes before the operation, the configuration transaction can still succeed, but the automatic commit is skipped and a warning is returned. Resolve and commit those changes manually before asking the server to try again.

  • Git failures do not undo an otherwise validated Home Assistant change. The result includes a warning, and the checkpoint remains available.

History and diff tools are available in read_only mode. Applying configuration changes requires admin mode, and rollback additionally requires the normal high-impact confirmation. Git-aware MCP tools include:

Tool

Use

get_config_history

Show bounded commit history for the whole configuration or one allowed file.

get_config_diff

Show the current unstaged or staged diff for explicitly allowed paths, with sensitive values redacted.

get_recent_changes

Show recent Git commits alongside transaction checkpoints.

rollback_to_commit

Undo the service-created current HEAD, create a rollback commit, validate Home Assistant, and reload.

rollback_change

Restore a transaction checkpoint independently of Git history.

Useful requests include:

  • Show the last 10 configuration changes and explain what changed.

  • Show the uncommitted diff for packages/lighting.yaml.

  • Dry-run this YAML change and show me the diff. Do not apply or commit it yet.

  • Apply the reviewed change with commit message "Adjust evening lighting schedule".

  • Dry-run rolling back the latest MCP-created commit, then wait for confirmation.

For safety, Git rollback is intentionally narrow: it only accepts the current HEAD, the commit must use the configured service author email, and affected files must have no newer uncommitted changes. Rollback creates a new commit instead of rewriting history. If Home Assistant validation fails, the server attempts a compensating commit to restore the pre-rollback state.

Docker Compose setup

Requirements

  • Docker Engine with Compose v2.

  • A Home Assistant URL reachable from the container.

  • A Home Assistant long-lived access token.

  • The Home Assistant configuration directory if you want file-backed configuration tools.

Use a Home Assistant administrator token only if you need administrative tools.

Install

git clone https://github.com/lemanjo/hac-mcp.git
cd hac-mcp
cp .env.example .env
cp config.example.yaml config.yaml
install -d -m 700 secrets
openssl rand -hex 32 > secrets/mcp_auth_token
read -rsp "Home Assistant token: " HA_TOKEN
printf '%s' "$HA_TOKEN" > secrets/home_assistant_token
unset HA_TOKEN
chmod 600 secrets/home_assistant_token secrets/mcp_auth_token

Edit .env and set at least:

MCP_IMAGE=lemanjo/hac-mcp:1.0.0
HOME_ASSISTANT_URL=http://192.168.1.10:8123
HA_CONFIG_PATH=/absolute/path/to/home-assistant/config
MCP_SETTINGS_FILE=./config.yaml
PUID=1000
PGID=1000
MCP_MODE=read_only

PUID and PGID must identify a non-root user that can read and write HA_CONFIG_PATH. The example pins an exact release so upgrades are deliberate.

Start the published image:

docker compose pull hac-mcp
docker compose up -d --no-build hac-mcp
docker compose ps

To build from the current source instead, leave MCP_IMAGE=home-assistant-admin-mcp:local and run:

docker compose build --pull
docker compose up -d

Check the service:

curl --fail http://127.0.0.1:3000/livez
curl --fail http://127.0.0.1:3000/readyz
  • /livez checks that the MCP server is running.

  • /readyz checks that the server can authenticate with Home Assistant.

Access from other LAN devices

The default Compose setup publishes the port only on the Docker host. To use clients on other trusted LAN devices, set:

MCP_BIND_IP=0.0.0.0
MCP_ALLOWED_HOSTS=192.168.1.10,home-server,home-server.local,localhost,127.0.0.1,hac-mcp

Replace the example IP and names with the addresses used to reach the Docker host. MCP_ALLOWED_HOSTS contains server addresses from the client URL, not client device addresses.

Connect clients to http://192.168.1.10:3000/mcp. Leave MCP_ALLOWED_ORIGINS empty for command-line clients. Restrict port 3000 to your LAN with firewall rules, and do not expose it directly to the internet. The server does not provide HTTPS; use a trusted reverse proxy if traffic leaves a trusted network.

Unraid setup

Prepare files

Open the Unraid terminal and adjust the paths, user ID, and group ID for your installation:

APPDATA=/mnt/user/appdata/hac-mcp
HA_CONFIG=/mnt/user/appdata/home-assistant
RUN_UID=99
RUN_GID=100

test -f "$HA_CONFIG/configuration.yaml"
install -d -o "$RUN_UID" -g "$RUN_GID" -m 700 "$APPDATA/secrets"
curl --fail --location \
  --output "$APPDATA/config.yaml" \
  https://raw.githubusercontent.com/lemanjo/hac-mcp/main/config.example.yaml
openssl rand -hex 32 > "$APPDATA/secrets/mcp_auth_token"
read -rsp "Home Assistant token: " HA_TOKEN
printf '%s' "$HA_TOKEN" > "$APPDATA/secrets/home_assistant_token"
unset HA_TOKEN
chown "$RUN_UID:$RUN_GID" "$APPDATA/config.yaml" "$APPDATA/secrets/"*
chmod 600 "$APPDATA/config.yaml" "$APPDATA/secrets/"*

The example uses Unraid's common 99:100 identity. Use the IDs that can access your actual Home Assistant configuration directory.

Add the container

In Docker > Add Container, enable Advanced View and use:

Field

Value

Name

hac-mcp

Repository

lemanjo/hac-mcp:1.0.0, or another exact release tag

Network Type

bridge

Privileged

Off

Port

Container 3000, host 3000, TCP

Extra Parameters

--user=99:100 --read-only --security-opt=no-new-privileges:true --cap-drop=ALL --pids-limit=256 --stop-timeout=20 --tmpfs=/tmp:rw,noexec,nosuid,size=64m

Replace 99:100 in Extra Parameters if you selected different IDs. Do not add PUID or PGID variables in Unraid; the application does not read them.

Add these paths:

Host path

Container path

Access

/mnt/user/appdata/hac-mcp/config.yaml

/app/config.yaml

Read Only

/mnt/user/appdata/hac-mcp/secrets/home_assistant_token

/run/secrets/home_assistant_token

Read Only

/mnt/user/appdata/hac-mcp/secrets/mcp_auth_token

/run/secrets/mcp_auth_token

Read Only

Your Home Assistant configuration directory

/ha-config

Read/Write

Do not mount /var/run/docker.sock.

Add these variables:

Variable

Value

HOME_ASSISTANT_URL

Home Assistant URL reachable from the container, such as http://192.168.1.10:8123

HOME_ASSISTANT_TOKEN_FILE

/run/secrets/home_assistant_token

MCP_CONFIG_FILE

/app/config.yaml

MCP_AUTH_TOKEN_FILE

/run/secrets/mcp_auth_token

MCP_MODE

Start with read_only; use control or admin when needed

MCP_TRANSPORT

http

MCP_HOST

0.0.0.0

MCP_PORT

3000

MCP_ALLOWED_HOSTS

Unraid IP and names used by clients, plus localhost,127.0.0.1,hac-mcp

MCP_ALLOWED_ORIGINS

Leave empty for command-line clients

HA_CONFIG_PATH

/ha-config

HA_GIT_ENABLED

true only if the mounted configuration is already a Git repository; otherwise use false

If Home Assistant uses host networking, do not use localhost in HOME_ASSISTANT_URL; inside this container, localhost means the MCP container itself.

Apply the container and test from the Unraid terminal:

curl --fail http://127.0.0.1:3000/livez
curl --fail http://127.0.0.1:3000/readyz
docker inspect --format '{{json .State.Health}}' hac-mcp

Back up /mnt/user/appdata/hac-mcp and the Home Assistant configuration directory. File checkpoints are stored in /ha-config/.ha-mcp/backups and are not deleted automatically.

Connect an MCP client

The MCP endpoint is:

http://<server-address>:3000/mcp

Every HTTP request needs the MCP token from secrets/mcp_auth_token. This is not the Home Assistant token.

Load the token on the client device without putting it directly in a committed configuration file:

export HAC_MCP_TOKEN="$(tr -d '\r\n' < ~/.config/hac-mcp/token)"

OpenCode

Add this to opencode.json:

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "home-assistant-admin": {
      "type": "remote",
      "url": "http://192.168.1.10:3000/mcp",
      "enabled": true,
      "oauth": false,
      "headers": {
        "Authorization": "Bearer {env:HAC_MCP_TOKEN}"
      },
      "timeout": 150000
    }
  }
}

Restart OpenCode, then run:

opencode mcp debug home-assistant-admin

Codex

Add this to ~/.codex/config.toml or a trusted project's .codex/config.toml:

[mcp_servers.home-assistant-admin]
url = "http://192.168.1.10:3000/mcp"
bearer_token_env_var = "HAC_MCP_TOKEN"
enabled = true
default_tools_approval_mode = "writes"
tool_timeout_sec = 150

Claude Code

Add this to the project's .mcp.json:

{
  "mcpServers": {
    "home-assistant-admin": {
      "type": "http",
      "url": "http://192.168.1.10:3000/mcp",
      "headers": {
        "Authorization": "Bearer ${HAC_MCP_TOKEN}"
      },
      "timeout": 150000
    }
  }
}

Replace 192.168.1.10 with the Docker or Unraid host address. Add that exact IP or hostname to MCP_ALLOWED_HOSTS.

Useful first requests:

  • List unavailable entities. Do not make changes.

  • Explain why light.office is unavailable using recent logs and registry data.

  • In control mode: Turn on light.office.

  • In admin mode: Dry-run this change, show me the result, and wait before applying it.

Environment variables

Configuration is loaded from MCP_CONFIG_FILE first. Environment variables then override matching values from the file.

The defaults below are application defaults. The supplied Compose file and config.example.yaml override a few defaults as noted.

Application variables

Variable

Default

Required

Purpose

MCP_CONFIG_FILE

None

No

YAML configuration file. Compose sets this to /app/config.yaml.

HOME_ASSISTANT_URL

None

Yes, here or in YAML

Home Assistant base URL as seen from the server.

HOME_ASSISTANT_TOKEN

None

One HA token source

Home Assistant long-lived access token. Prefer the file variable.

HOME_ASSISTANT_TOKEN_FILE

None

One HA token source

File containing the Home Assistant token. Takes priority over HOME_ASSISTANT_TOKEN.

HA_REQUEST_TIMEOUT_MS

30000

No

REST request timeout, from 1000 to 120000 milliseconds.

HA_WEBSOCKET_TIMEOUT_MS

30000

No

WebSocket command timeout, from 1000 to 120000 milliseconds.

HA_VERIFY_TLS

true

No

Verify the Home Assistant HTTPS certificate.

MCP_MODE

read_only

No

Permission mode: read_only, control, or admin.

MCP_TRANSPORT

http

No

MCP transport: http or stdio.

MCP_HOST

127.0.0.1

No

Address the HTTP server listens on. Compose and the example YAML use 0.0.0.0 inside Docker.

MCP_PORT

3000

No

HTTP server port.

MCP_AUTH_TOKEN

None

One MCP token source for HTTP

MCP client token, at least 16 characters. Prefer the file variable.

MCP_AUTH_TOKEN_FILE

None

One MCP token source for HTTP

File containing the MCP client token. Takes priority over MCP_AUTH_TOKEN.

MCP_ALLOWED_HOSTS

localhost,127.0.0.1

No

Comma-separated server IPs and names accepted from request Host headers. No schemes or ports.

MCP_ALLOWED_ORIGINS

Empty

No

Comma-separated browser origin hostnames. Leave empty for non-browser clients.

HA_CONFIG_PATH

/ha-config

For filesystem tools

Home Assistant configuration root inside the server or container.

HA_FILESYSTEM_ENABLED

true

No

Enable approved configuration file reads and writes.

HA_ALLOW_SECRET_VALUES

false

No

Allow secret-bearing YAML values to be read or changed. Leave disabled in normal use.

HA_ALLOW_CUSTOM_COMPONENTS

false

No

Allow approved reads from custom_components.

HA_ALLOWED_CONFIG_DIRECTORIES

packages,themes

No

Comma-separated YAML subdirectories that filesystem tools may access.

HA_GIT_ENABLED

true

No

Enable local Git history and commits when the configuration is already in a Git repository.

Boolean variables accept true, false, 1, 0, yes, no, on, or off. Token files are trimmed when read.

Settings without environment-variable overrides remain in config.yaml. These include request-size limits, file-size limits, backup location, confirmation rules, sensitive entities, cache times, and Git author details. See config.example.yaml for the full YAML structure.

Compose-only variables

These variables are read by docker-compose.yml to configure the container:

Variable

Default

Required

Purpose

MCP_IMAGE

home-assistant-admin-mcp:local

No

Image to build or run. Use an exact tag such as lemanjo/hac-mcp:1.0.0.

MCP_BIND_IP

127.0.0.1

No

Host address that publishes the MCP port. Use 0.0.0.0 for intentional LAN access.

MCP_PUBLISHED_PORT

3000

No

Port exposed on the Docker host.

HA_CONFIG_PATH

None

Yes

Existing host configuration directory mounted at /ha-config.

MCP_SETTINGS_FILE

./config.example.yaml

No

Host YAML file mounted at /app/config.yaml.

HA_TOKEN_SECRET_FILE

./secrets/home_assistant_token

No

Host file mounted as the Home Assistant token.

MCP_TOKEN_SECRET_FILE

./secrets/mcp_auth_token

No

Host file mounted as the MCP client token.

PUID

1000

No

Numeric user ID used to run the container. Must have access to the configuration mount.

PGID

1000

No

Numeric group ID used to run the container.

Safety and file changes

  • The Home Assistant token controls what the server may do in Home Assistant. The separate MCP token controls who may call this server.

  • Most persistent changes support dry_run: true. Device controls do not simulate an action.

  • YAML changes create a checkpoint, write files safely, ask Home Assistant to validate its configuration, and attempt rollback if validation fails.

  • Filesystem tools are limited to root YAML files and configured YAML directories. Protected storage, databases, Git internals, private keys, symlinks, and paths outside the configuration root are blocked.

  • Secret values are hidden by default. Keep HA_ALLOW_SECRET_VALUES=false unless you have a specific recovery need and fully trust the MCP client.

  • Git support is local only. The server does not clone, pull, push, or manage remotes.

  • File checkpoints are not Home Assistant backups. Back up Home Assistant separately and clean old .ha-mcp/backups files according to your own retention policy.

Troubleshooting

Problem

What to check

MCP client gets 401

The MCP bearer token is missing or does not match MCP_AUTH_TOKEN_FILE.

MCP client gets 403 or an SSE 403 error

Add the IP or hostname from the client URL to MCP_ALLOWED_HOSTS. Browser clients may also need MCP_ALLOWED_ORIGINS.

/readyz returns 503

Check HOME_ASSISTANT_URL, the Home Assistant token, container networking, and Home Assistant permissions.

Home Assistant URL uses localhost

In a container, localhost is that container. Use the host LAN IP, host.docker.internal, or a shared Docker-network name.

Tool returns OPERATION_NOT_PERMITTED

Raise MCP_MODE to control or admin if the operation should be allowed.

Tool returns CONFIRMATION_REQUIRED

Review the requested action, then retry with confirm: true if it is correct.

Administrative Home Assistant calls fail

Use a token belonging to a Home Assistant administrator and check compatibility with the installed Home Assistant release.

File operations report permission errors

Make sure /ha-config is mounted read/write and the container UID/GID can access it.

Git reports that no repository was detected

Initialize and manage the repository outside this server, or set HA_GIT_ENABLED=false.

Requests are rejected as too large

Reduce the request or raise mcp.maxRequestBytes in config.yaml, up to the documented schema limit.

Container logs are available with:

docker compose logs -f hac-mcp

Local development

Node.js 22 and pnpm 11.21.0 are required.

corepack enable
pnpm install --frozen-lockfile
pnpm build
pnpm test

Run all repository checks before publishing changes:

pnpm supply-chain:check
pnpm audit --prod --audit-level high
pnpm typecheck
pnpm lint
pnpm format:check
pnpm test
pnpm build

Every container build reports all known runtime vulnerabilities and fails on fixable findings. Publishing workflows scan both linux/amd64 and linux/arm64 before pushing. Every push to main publishes the moving lemanjo/hac-mcp:nightly tag and an immutable nightly-<commit-sha> image. GitHub releases publish exact, major/minor, major, and latest tags for both architectures.

NOTE

This project is built with AI-assisted development tools.

License

MIT

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    D
    maintenance
    MCP server for controlling and querying Home Assistant via its REST API, exposing tools to get entity states, list all states, and call services.
    16
    189 npm
    MIT
  • A
    license
    B
    quality
    C
    maintenance
    MCP server for full Home Assistant control, enabling AI agents to manage dashboards, automations, files, apps, entities, and more via REST API, WebSocket, and SSH.
    66
    90 npm
    MIT
  • A
    license
    B
    quality
    C
    maintenance
    MCP server for controlling HomeSeer HS4 with safe, auditable, and guarded write operations.
    63
    1
    MIT