ha-mcp-readonly Server
Serveur MCP (Model Context Protocol) en lecture seule pour Home Assistant. Offre aux assistants IA (Claude Desktop, LibreChat, Cline) une observabilité complète de votre maison intelligente — états des entités, automatisations, scripts, appareils, journaux, diagnostics — sans aucun accès en écriture. Génère également des instantanés de contexte IA statiques pour les systèmes RAG, les projets ChatGPT, Qwen et d'autres outils acceptant des fichiers de connaissances personnalisés. Développé en Python, fonctionne partout — localement, dans Docker ou en tant qu'intégration MCP.
Documentation
HA-MCP-Readonly
Read-only MCP (Model Context Protocol) server for Home Assistant. Gives AI assistants (Claude Desktop, LibreChat, Cline) full observability into your smart home — entity states, automations, scripts, devices, logs, diagnostics — without any write access. Also generates static AI context snapshots for RAG systems, ChatGPT Projects, Qwen, and other tools that accept custom knowledge files. Built in Python, runs anywhere — locally, in Docker, or as an MCP integration.
Requirements
- Python 3.11+ (for local use) or Docker
- A Home Assistant instance with a long-lived access token
- Create one in your HA profile: Settings → Security → Long-Lived Access Tokens
- Access to your Home Assistant config directory (for filesystem tools)
Quick Start
1. Configure environment
cp .env.example .env
Edit .env with your credentials:
HA_URL=http://your-ha-ip:8123
HA_TOKEN=your_long_lived_access_token_here
# HA_CONFIG_PATH=/config # optional, default shown
# MCP_DEV_TOOLS_ENABLED=1 # optional, default shown
# HEALTH_CHECK_PORT=9091 # optional, default shown
# MCP_SSE_PORT=9092 # optional, default shown
# REST_API_PORT=9093 # optional, default shown
# RUN_TESTS_ON_STARTUP=0 # optional, default shown
# OUTPUT_PATH=/app/output/ha-ai-context.md # optional, default shown
IMPORTANT: The .env file contains your access token. It is gitignored and must never be committed.
2. Run with Docker
First, configure your credentials. Either use a .env file (recommended) or pass variables directly.
Option A — with .env file and docker compose:
cp .env.example .env
# edit .env with your HA_URL and HA_TOKEN
docker compose up -d
The included docker-compose.yml pulls the image from GitHub Container Registry and mounts your HA config read-only:
services:
ha-mcp-readonly:
image: ghcr.io/paulomac1000/ha-mcp-readonly:latest
container_name: ha-mcp-readonly
env_file: .env
ports:
- "9091:9091" # health
- "9092:9092" # MCP SSE
- "9093:9093" # REST API
volumes:
- /path/to/ha/config:/config:ro # Replace with your HA config path (e.g., /config, ~/.homeassistant)
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-fsS", "http://localhost:9091/health"]
interval: 30s
timeout: 5s
retries: 3
start_period: 15s
Option B — with plain docker run:
docker run -d \
--name ha-mcp-readonly \
-p 9091:9091 \
-p 9092:9092 \
-p 9093:9093 \
-e HA_URL=http://your-ha-ip:8123 \
-e HA_TOKEN=your_token \
-v /path/to/ha/config:/config:ro \
ghcr.io/paulomac1000/ha-mcp-readonly:latest
Building locally:
docker build -t ha-mcp-readonly .
docker compose -f docker-compose.build.yml up -d
3. Run locally (Python 3.11+)
pip install -r requirements.txt
HA_URL=http://localhost:8123 HA_TOKEN=your_token python server.py
Ports
| Port | Protocol | Purpose | Endpoint |
|---|---|---|---|
| 9091 | HTTP | Health check | GET /health |
| 9092 | SSE | MCP transport | /sse, /messages |
| 9093 | HTTP | REST API + Context Generator | /api/* |
Verify
# Health check
curl http://localhost:9091/health
# List all MCP tools
curl http://localhost:9093/api/tools
# Generate a context snapshot
curl -X POST http://localhost:9093/api/context/generate \
-H "Content-Type: application/json" \
-d '{"mode": "hybrid"}'
Available Tools (158 with dev tools, 145 without)
Tools are organized by category (75 shown in table below). All are read-only — no state changes, no service calls, no modifications.
| Category | Key tools |
|---|---|
| States | get_entity_state, get_states_grouped, search_entities, get_domains_summary, get_system_overview |
| Automations | list_automations, get_automation_code, get_automation_file_location, diagnose_automation, search_automations_by_entity, get_automation_conflicts, get_automation_entity_id |
| Scripts & Scenes | list_scripts, get_script_code, list_scenes, get_scene_code |
| Blueprints | list_blueprints, get_blueprint_code, get_blueprint_instances, get_blueprint_usage_summary, resolve_blueprint_automation |
| Devices & Areas | get_device_details, search_devices, get_devices_by_area, get_area_devices_summary |
| Config entries | get_config_entry_details, search_config_entries, diagnose_config_entry, list_config_entry_domains |
| Integrations | get_integration_entities, get_integration_summary |
| Diagnostics | diagnose_system_health, get_unavailable_entities_grouped, get_integration_health, diagnose_person_tracking |
| Logs | get_log_insights, analyze_log_errors, get_startup_errors, get_log_timeline, search_logs |
| History | get_entity_state_history_summary, get_recent_state_changes |
| Context | entity_get_context_tree, get_entity_dependencies, get_entity_consumers, get_context_chain |
| Config | get_main_configuration, search_in_config, validate_yaml_syntax, read_config_file |
| Storage | search_registries_batch, get_entity_registry, get_device_registry, get_area_registry, get_template_entity_code, get_cache_stats |
| Lovelace | get_lovelace_dashboards, get_lovelace_config, get_lovelace_resources, search_lovelace_config, get_lovelace_config_summary, diagnose_lovelace_setup |
| Batch | bulk_search_entities, compare_entities_state, validate_yaml_batch, get_automation_codes_batch |
| Composite | investigate_entity, get_area_diagnostic, get_entity_with_automations, audit_config_orphans |
| Graph | graph_build_index, graph_find_references, graph_entity_impact, graph_get_neighbors, graph_detect_ghost_references, graph_detect_orphans, graph_export_mermaid |
| Dev tools | test_template, compare_templates, diagnose_entity, check_entity_exists, validate_automation_trigger, diagnose_template |
Full tool catalog with schemas available at GET /api/tools
What's New in v1.6.0
- 5 new tools:
get_context_chain(Context),resolve_blueprint_automation(Blueprints),get_cache_stats(Storage),compare_templates(Dev tools),get_automation_entity_id(Automations) choose_analysisindiagnose_automation: Whendetail_level="full", returns conditional branch analysis for automations usingchooseactions- Registry pagination:
limitandoffsetparameters added toget_entity_registry,get_device_registry,get_area_registry, andget_config_entriesfor efficient scanning of large registries data_qualityfield: Composite diagnostic tools (investigate_entity,get_area_diagnostic,get_entity_with_automations) now include adata_qualityassessment flagging stale sensors, missing entities, and unavailable devices- New pre-commit hooks:
mypy strict,Bandit,Semgrep, and AFDS documentation validation added to the pre-commit pipeline - Test infrastructure: 67 integration tests and 158 E2E tests for expanded real-HA and end-to-end coverage
Claude Desktop Configuration
Add the following to your Claude Desktop config:
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Linux: ~/.config/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"ha-mcp-readonly": {
"url": "http://localhost:9092/sse"
}
}
}
After restarting Claude Desktop, the 139 Home Assistant tools will be available (127 without dev tools enabled).
LibreChat
mcpServers:
ha-mcp-readonly:
url: http://ha-mcp-readonly:9092/sse
timeout: 30000
Context Generator
Generates a comprehensive Markdown snapshot of your entire Home Assistant instance. Designed for scenarios where live MCP access isn't available or desired:
Use cases:
- RAG systems — use the generated file as a knowledge base for retrieval-augmented generation (e.g., with LangChain, LlamaIndex, or custom RAG pipelines)
- ChatGPT Projects / Qwen / Claude Projects — upload the file as custom knowledge to give the AI full awareness of your smart home without network access to HA
- Static context for AI coding tools — provide the file alongside your codebase so AI assistants understand your automations, devices, and entity relationships
- Documentation snapshots — freeze configuration state for auditing, debugging, or sharing with other users
Modes:
| Mode | Description |
|---|---|
offline | Reads only from local filesystem (/config), no API calls |
online | Fetches data from HA REST API (states, history, config) |
hybrid | Combines offline and online data (default) |
The generated file includes entity inventory, automation analysis, script/scene listing, dashboard usage, log error patterns, device topology, config entry health, blueprint usage, and template entity references.
# Via REST API
curl -X POST http://localhost:9093/api/context/generate \
-H "Content-Type: application/json" \
-d '{"mode": "hybrid"}'
curl http://localhost:9093/api/context/download > ha-ai-context.md
REST API
The REST API on port 9093 provides HTTP access to all tools and the context generator with an OpenAPI schema.
# List tools
curl http://localhost:9093/api/tools
# Call a tool
curl -X POST http://localhost:9093/api/tools/get_entity_state \
-H "Content-Type: application/json" \
-d '{"entity_id": "sun.sun"}'
# OpenAPI schema
curl http://localhost:9093/api/openapi.json
Development
Setup
git clone https://github.com/paulomac1000/ha-mcp-readonly.git
cd ha-mcp-readonly
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt
Run tests
# Unit tests (no credentials needed, 1142 tests, <20s)
pytest tests/unit/ -q
# Smoke tests (requires local MCP server, 84 tests, <5s)
pytest tests/smoke/ -q
# Integration tests (requires real HA, 278 tests, ~2min)
export HA_URL=http://your-ha:8123
export HA_TOKEN=your_token
pytest tests/integration/ -q
# E2E tests (requires real HA + local MCP server, 182 tests, ~30s)
pytest tests/e2e/ -q
# All tests
pytest tests/unit/ tests/smoke/ tests/e2e/ tests/integration/ -q
All unit tests use mocked dependencies — no real Home Assistant instance required. 1602 total tests across 4 suites.
Lint & format
ruff check .
ruff format --check .
Architecture
server.py # Main entry point — FastMCP + REST API + health check
context_generator/
├── core.py # Entry points: main(), generate_context_file()
├── analyzers.py # RegistryCollector, AutomationAnalyzer, LogAnalyzer, etc.
├── formatters.py # ReportGenerator — Markdown output
├── constants.py # ENTITY_PATTERN, HA URLs, ignorable domains, YAML loader
└── utils.py # Registry cache, HA API client, YAML helpers
ha_graph/
└── graph_builder.py # HA Semantic Graph: build, query, and export
tools/
├── automations.py # Automation analysis (17 tools)
├── batch_operations.py # Bulk entity operations (5 tools)
├── blueprints.py # Blueprint management (4 tools)
├── capabilities.py # Zero-I/O MCP introspection tool catalog (1 tool)
├── categories.py # Category management (automation, script, scene, helpers) (1 tool)
├── composite.py # Composite diagnostic tools (4 tools)
├── config.py # Configuration file tools (10 tools)
├── config_entries.py # Config entry diagnostics (4 tools)
├── devices.py, areas.py # Device and area tools (6+1 tools)
├── dev_tools.py # Template testing, validation (13 tools)
├── diagnostics.py # System health, energy dashboard (18 tools)
├── entity_context.py # Entity context tree (2 tools)
├── entity_dependencies.py # Entity dependency graph (2 tools)
├── filesystem_explorer.py # Secured filesystem browsing (3 tools)
├── graph_tools.py # HA entity graph tools (7 tools)
├── health_reporter.py # Health score and metrics (1 tool)
├── helpers_health.py # Helper entity health diagnostics (1 tool)
├── history.py # State history and recent changes (2 tools)
├── integrations.py # Integration entity analysis (2 tools)
├── logs.py # Log analysis and insights (8 tools)
├── manifests.py # TOOL_MANIFESTS, risk prefix injection
├── observability.py # request_id, invocation counters
├── scripts.py, scenes.py # Script and scene inspection (2+2 tools)
├── states.py # Entity state queries (12 tools)
├── storage.py # Registry dump and search tools (30 tools)
├── utils.py # Shared: HA API client, registry loader, log sanitizer
└── yaml_utils.py # HomeAssistantLoader for HA-specific YAML tags
tests/
├── unit/ # 39 test files, 1181 tests, fully mocked
├── integration/ # Real HA tests (requires HA_URL + HA_TOKEN)
├── smoke/ # REST API smoke tests (requires local server)
└── e2e/ # End-to-end pipeline tests (requires real HA)
Security
- Read-only by design — no write operations to Home Assistant. Cannot modify states, execute services, or trigger automations.
- Filesystem restrictions — access limited to
/configdirectory. Path traversal (..,~) blocked. Max file size 10MB. Max directory depth 20. - Auth data blocked —
auth,auth_provider.*,onboardingregistries are never returned. - Credential redaction —
HA_TOKENis never logged or exposed in outputs. JWTs, passwords, API keys, and IP addresses are sanitized from log output.
Notes
- The server exposes three ports: 9091 (health), 9092 (MCP SSE), 9093 (REST API). Ports are configurable via env.
MCP_DEV_TOOLS_ENABLED=0disables template execution and debugging tools for production use.- Security note: Ports 9091-9093 should not be exposed publicly. Use firewall rules or reverse proxy with authentication if needed.
- Registry files (areas, devices, entities, config entries) are cached for 5 minutes to reduce filesystem I/O.
- All tool responses return JSON with a
successfield — always check this before readingdata.
Troubleshooting
For common issues and solutions, see docs/documentation.md#troubleshooting.
License
MIT — see LICENSE for details.