Skip to main content
Glama
ambient-home-systems

Ambient Home Assistant MCP

Official

Ambient Home Assistant MCP

Ambient Home Assistant MCP is a secure, semantic bridge that gives ChatGPT and other MCP clients purpose-built access to Home Assistant. It is the server foundation for the future user-facing Ambient Home Assistant application.

Phase 7 status: v0.6.9 passed real Home Assistant validation across all 24 read-only tools and is the stable App baseline. The v0.7.0 source introduces seven semantic control tools behind independent, disabled-by-default safety gates and a central policy/execution/audit pipeline. No automated live write is enabled. Deployment remains local/private until a later authentication phase is complete.

What it is—and what it is not

The bridge is an abstraction and security layer. Over time, it can choose among Home Assistant REST, WebSocket, and native MCP/Assist interfaces while presenting small, semantic tools to the model.

It is not:

  • a replacement for Home Assistant;

  • an unrestricted Home Assistant administrator API;

  • a generic API wrapper exposed to an LLM; or

  • a reverse proxy for Home Assistant's /api/mcp endpoint.

Related MCP server: homeassistant-gateway

Architecture

flowchart TD
    C[ChatGPT or MCP client] -->|MCP| A[Ambient Home Assistant MCP]
    A --> T[Semantic tools]
    A --> P[Policy and security]
    A --> N[Normalized data and diagnostics]
    T --> H[Home Assistant client facade]
    P --> H
    N --> H
    H --> R[REST state API]
    H --> W[WebSocket registries]
    H -. selective future use .-> M[HA MCP or Assist API]

MCP tools never make raw HTTP requests. They depend on HomeAssistantClient, which owns interface selection and immediately normalizes upstream responses. See the architecture decision record.

Capabilities

Surface

Purpose

ha_connection_status

Reports reachability and authentication state without exposing credentials.

ha_server_info

Returns only version, time zone, and unit-system metadata.

ha_get_entity

Gets one current entity by exact entity ID with resolved location and safe attributes.

ha_search_entities

Searches current entities by name/ID and composable domain, area, floor, state, and availability filters.

ha_list_areas / ha_get_area

Lists compact areas or gets one area with domain counts and an optional bounded entity list.

ha_list_floors / ha_get_floor

Lists floors or gets one floor with area and domain aggregates.

ha_domain_summary

Summarizes observed states and availability for any entity domain.

ha_get_entity_history

Returns bounded recorded state transitions and only proven state durations.

ha_get_logbook

Returns bounded, privacy-filtered recorded logbook facts.

ha_get_recent_changes

Finds recorded state changes by time, area, floor, domain, or entity.

ha_get_home_summary

Returns a bounded whole-home snapshot containing only supported sections.

ha_find_unavailable_entities

Finds unavailable entities with optional factual duration filtering.

ha_find_low_batteries

Finds genuine numeric percentage battery sensors below a threshold.

ha_get_openings

Lists doors, windows, garage doors, and other openings by semantic class.

ha_get_lights_on

Lists compact current light entities reporting on.

ha_diagnose_home

Returns deterministic, evidence-backed findings with exact severities.

ha_list_automations

Lists compact current automation metadata with deterministic search.

ha_get_automation

Returns a bounded, sanitized loaded automation definition when supported.

ha_find_automations_for_entity

Finds conservative static entity/device/template references.

ha_get_automation_traces

Lists compact metadata for recent stored automation traces.

ha_get_automation_trace

Normalizes one bounded stored execution trace with nested paths.

ha_find_activity_cause

Correlates Recorder contexts, traces, static references, and timing under strict evidence rules.

ha_control_light

Controls exact light IDs with supported on/off, brightness, color-temperature, and RGB values.

ha_control_fan

Controls exact fan IDs with on/off and supported percentages.

ha_control_media_player

Performs play/pause/stop, bounded volume, and mute operations without arbitrary media URLs.

ha_control_climate

Sets supported HVAC modes and target temperatures within device and policy limits.

ha_control_switch

Controls only exact switch IDs explicitly authorized by server policy.

ha_activate_scene

Accepts exact scene IDs but remains confirmation-blocked throughout Phase 7.

ha_run_script

Runs only exact explicitly authorized scripts, without variables or raw service data.

GET /health

Reports application liveness and separate Home Assistant readiness.

No generic service-call, administrative, lock, alarm, cover/garage, valve, automation-trigger, or configuration-mutation tool is implemented.

Security model

  • Home Assistant tokens come only from runtime configuration and use Pydantic secret types.

  • Logs are structured and redact bearer tokens and common credential fields.

  • Raw /api/config data is reduced to an allowlisted model before it can reach a tool result.

  • Detailed entity attributes use an explicit allowlist and exclude URLs, camera sources, tokens, credentials, coordinates, and location-bearing metadata.

  • Current states are never cached. Registry metadata uses one bounded 60-second TTL cache to avoid repeated WebSocket authentication and registry reads.

  • Historical queries use Home Assistant Recorder data, remain uncached, and are bounded to a 24-hour default / 7-day maximum window, 500 events, and 50 aggregate candidate entities by default.

  • Whole-home tools use one bulk current-state request plus the registry cache. Detail lists are bounded, raw tracker attributes are excluded, and safety text states only what Home Assistant reports.

  • Automation definitions use Home Assistant's admin-gated automation/config WebSocket command. Stored traces use trace/list, trace/get, and trace/contexts; unavailable commands degrade only those features.

  • Automation aliases, descriptions, templates, and action data are untrusted data. Strings and structures are bounded, secret-like values and private action content are redacted, Jinja is never executed, and context user IDs are never returned.

  • The reference index is an in-memory TTL snapshot with explicit refresh and a 500-automation bound. Current automation entity metadata and Recorder state changes remain fresh.

  • MCP transport Host and Origin allowlists protect against DNS rebinding.

  • Ambient policy is independent of the Home Assistant token's privilege. The engine supports allow, deny, and confirm_required, deterministic rule precedence, canonical targets, value limits, protected entities, and hard mass-action limits.

  • READ_ONLY=true and CONTROL_ENABLED=false are independent hard boundaries. Writes require both READ_ONLY=false and CONTROL_ENABLED=true; exact policy, capability, value, and mass-action checks still apply afterward.

  • Every executable plan crosses one central executor. Confirmation has no spoofable caller-supplied boolean; confirmation-required plans remain blocked.

  • Exact entity IDs are the only writable targets. The server never chooses a device merely because a display name appears similar.

  • Audit events are bounded and recursively redact credentials, webhooks, URLs, messages, commands, camera streams, and other secret-bearing service data.

  • Compose starts directly as a non-root user with a read-only filesystem. In App mode, a minimal root bootstrap reads Supervisor's root-only options file and then drops to the non-root ambient user before starting the MCP server.

Never commit .env, Home Assistant tokens, credentials, private URLs, or certificates. See Security before any deployment work.

Quick start

Requirements: Python 3.12+ and uv.

cp .env.example .env
# Edit .env and provide HOME_ASSISTANT_URL and HOME_ASSISTANT_TOKEN.
# Optional: copy policy.example.toml and set POLICY_FILE to its absolute path.
# Keep READ_ONLY=true and CONTROL_ENABLED=false unless controls are deliberately configured.
uv sync --all-extras
uv run ambient-ha-mcp

Standalone HTTP(S) URLs derive the standard Home Assistant /api/websocket endpoint. Gateways with a distinct route may set the optional, credential-free HOME_ASSISTANT_WEBSOCKET_URL. App mode sets Supervisor's documented endpoint internally; it is not an App option.

The Streamable HTTP MCP endpoint is http://127.0.0.1:8000/mcp; health is at http://127.0.0.1:8000/health.

Inspect the tools locally:

npx @modelcontextprotocol/inspector@latest

Then connect the Inspector to http://127.0.0.1:8000/mcp.

Home Assistant App

The repository now contains a Home Assistant App definition for amd64 and aarch64. The currently validated and advertised baseline is ghcr.io/ambient-home-systems/ambient-ha-mcp:0.6.9. Candidate images are published from immutable version tags and verified before a separate PR is allowed to update the App catalog version. The App never relies on latest for installation.

  1. Add https://github.com/ambient-home-systems/ambient-ha-mcp as a custom App repository.

  2. Install Ambient Home Assistant MCP.

  3. Keep port 8000/tcp disabled except during local MCP validation.

  4. Start the App and check its log and container health.

Supervisor supplies a short-lived token and the App connects through the documented REST and WebSocket Core proxies; no Home Assistant URL or token appears in App options. The v0.7.0 catalog-promotion metadata must default to read_only: true and control_enabled: false; it is deliberately deferred until the new image exists. After promotion, enabling controls requires changing both gates. Switches and scripts additionally require exact entity-ID allowlists. Scene IDs may be listed for future confirmation support, but Phase 7 never executes scenes. External policy files remain disabled in App mode. See Home Assistant App installation for exact setup, upgrade, rollback, troubleshooting, and security guidance. Record real-installation results in the sanitized Phase 6.6 validation template. Maintainers must follow the non-negotiable App release procedure.

Development commands

uv sync --all-extras          # install
uv run ambient-ha-mcp         # run locally
uv run pytest                 # unit tests; real HA tests skip by default
uv run ruff check .           # lint
uv run ruff format --check .  # formatting check
uv run mypy                   # type check
docker build -t ambient-ha-mcp .
docker compose up --build

Regenerate the dependency lock after an intentional dependency change:

uv lock

Docker Compose

Copy .env.example to .env, supply the two required Home Assistant settings, and run docker compose up --build. Compose publishes only to host loopback.

The Docker health probe tests application liveness. A temporary Home Assistant outage changes /health to status: degraded, but leaves HTTP status 200 so the orchestrator does not restart a healthy bridge in a loop.

Documentation

License

MIT. See LICENSE.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    B
    maintenance
    A self-learning discovery tool + MCP server that turns your Home Assistant into knowledge an AI assistant can actually use.
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables secure, auditable access to Home Assistant through MCP, with a read-only observer profile and an operator profile for controlled mutations.
    2
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Exposes a curated allowlist of Home Assistant entities to external clients over MCP with read-only list and get_state tools, using an isolated guest credential that cannot access other Home Assistant APIs.
    1
    Apache 2.0
  • A
    license
    A
    quality
    C
    maintenance
    Read-only MCP server for Home Assistant that computes statistical summaries, trends, and session detection from recorded sensor history, returning compact tables instead of raw data so small local models can answer questions about energy usage, climate, and appliance activity without token-heavy arithmetic.
    10
    1 npm
    Apache 2.0