ha-mcp-readonly

Servidor MCP (Protocolo de Contexto de Modelo) de solo lectura para Home Assistant. Proporciona a los asistentes de IA (Claude Desktop, LibreChat, Cline) visibilidad completa de tu hogar inteligente — estados de entidades, automatizaciones, scripts, dispositivos, registros, diagnósticos — sin ningún acceso de escritura. También genera instantáneas de contexto de IA estáticas para sistemas RAG, Proyectos ChatGPT, Qwen y otras herramientas que aceptan archivos de conocimiento personalizados. Construido en Python, funciona en cualquier lugar — localmente, en Docker o como una integración MCP.

Documentación

HA-MCP-Readonly

CI Docker Python 3.11+ License: MIT

Servidor MCP (Model Context Protocol) de solo lectura para Home Assistant. Brinda a los asistentes de IA (Claude Desktop, LibreChat, Cline) visibilidad completa de tu hogar inteligente — estados de entidades, automatizaciones, scripts, dispositivos, registros, diagnósticos — sin ningún acceso de escritura. También genera instantáneas estáticas de contexto de IA para sistemas RAG, ChatGPT Projects, Qwen y otras herramientas que aceptan archivos de conocimiento personalizados. Desarrollado en Python, se ejecuta en cualquier lugar: localmente, en Docker o como integración MCP.

Requisitos

  • Python 3.11+ (para uso local) o Docker
  • Una instancia de Home Assistant con un token de acceso de larga duración
    • Crea uno en tu perfil de HA: Configuración → Seguridad → Tokens de acceso de larga duración
  • Acceso al directorio de configuración de Home Assistant (para herramientas del sistema de archivos)

Inicio rápido

1. Configurar el entorno

cp .env.example .env

Edita .env con tus credenciales:

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_PORT=9092                       # Streamable HTTP port when enabled
# 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

IMPORTANTE: El archivo .env contiene tu token de acceso. Está en gitignore y nunca debe enviarse al repositorio.

2. Ejecutar con Docker

Primero, configura tus credenciales. Usa un archivo .env (recomendado) o pasa las variables directamente.

Opción A — con archivo .env y docker compose:

cp .env.example .env
# edit .env with your HA_URL and HA_TOKEN
docker compose up -d

El docker-compose.yml incluido extrae la imagen del GitHub Container Registry y monta tu configuración de HA en modo solo lectura:

services:
  ha-mcp-readonly:
    image: ghcr.io/paulomac1000/ha-mcp-readonly:latest
    container_name: ha-mcp-readonly
    env_file: .env
    environment:
      MCP_TRANSPORT: http
      MCP_BIND_HOST: 0.0.0.0
      MCP_AUTH_TOKEN: ${MCP_AUTH_TOKEN:?Set a strong MCP_AUTH_TOKEN}
    ports:
      - "127.0.0.1:9091:9091"  # health
      - "127.0.0.1:9092:9092"  # authenticated Streamable HTTP MCP
    volumes:
      - /path/to/ha/config:/config:ro  # Replace with your HA config path (e.g., /config, ~/.homeassistant)
    tmpfs:
      - /app/output:size=256m,mode=0750,uid=10001,gid=10001
    restart: unless-stopped
    read_only: true
    cap_drop: ["ALL"]
    security_opt: ["no-new-privileges:true"]

Opción B — con docker run simple:

docker run -d \
  --name ha-mcp-readonly \
  -p 127.0.0.1:9091:9091 \
  -p 127.0.0.1:9092:9092 \
  -e HA_URL=http://your-ha-ip:8123 \
  -e HA_TOKEN=your_token \
  -e MCP_TRANSPORT=http \
  -e MCP_BIND_HOST=0.0.0.0 \
  -e MCP_AUTH_TOKEN=replace-with-a-high-entropy-caller-token \
  -v /path/to/ha/config:/config:ro \
  ghcr.io/paulomac1000/ha-mcp-readonly:latest

Compilación local:

docker build -t ha-mcp-readonly .
docker compose -f docker-compose.build.yml up -d

3. Ejecutar localmente (Python 3.11+)

pip install -r requirements.txt
HA_URL=http://localhost:8123 HA_TOKEN=your_token python server.py

Puertos

PuertoProtocoloPropósitoEndpoint
9091HTTPVerificación de saludGET /health
9092HTTPMCP HTTP Streamable autenticado/mcp
9093HTTPAPI REST autenticada opcional + Generador de contexto/api/*

Verificar

# Health check
curl http://localhost:9091/health

# Readiness
curl http://localhost:9091/ready

# MCP uses an official Streamable HTTP client at http://127.0.0.1:9092/mcp.
# REST/context routes on 9093 exist only when REST_API_ENABLED=1 and require a bearer token.

Herramientas disponibles (158 con herramientas de desarrollo, 145 sin ellas)

Las herramientas están organizadas por categoría (75 se muestran en la tabla a continuación). Todas son de solo lectura: sin cambios de estado, sin llamadas de servicio, sin modificaciones.

CategoríaHerramientas clave
Estadosget_entity_state, get_states_grouped, search_entities, get_domains_summary, get_system_overview
Automatizacioneslist_automations, get_automation_code, get_automation_file_location, diagnose_automation, search_automations_by_entity, get_automation_conflicts, get_automation_entity_id
Scripts y escenaslist_scripts, get_script_code, list_scenes, get_scene_code
Blueprintslist_blueprints, get_blueprint_code, get_blueprint_instances, get_blueprint_usage_summary, resolve_blueprint_automation
Dispositivos y áreasget_device_details, search_devices, get_devices_by_area, get_area_devices_summary
Entradas de configuraciónget_config_entry_details, search_config_entries, diagnose_config_entry, list_config_entry_domains
Integracionesget_integration_entities, get_integration_summary
Diagnósticosdiagnose_system_health, get_unavailable_entities_grouped, get_integration_health, diagnose_person_tracking
Registrosget_log_insights, analyze_log_errors, get_startup_errors, get_log_timeline, search_logs
Historialget_entity_state_history_summary, get_recent_state_changes
Contextoentity_get_context_tree, get_entity_dependencies, get_entity_consumers, get_context_chain
Configuraciónget_main_configuration, search_in_config, validate_yaml_syntax, read_config_file
Almacenamientosearch_registries_batch, get_entity_registry, get_device_registry, get_area_registry, get_template_entity_code, get_cache_stats
Lovelaceget_lovelace_dashboards, get_lovelace_config, get_lovelace_resources, search_lovelace_config, get_lovelace_config_summary, diagnose_lovelace_setup
Lotebulk_search_entities, compare_entities_state, validate_yaml_batch, get_automation_codes_batch
Compuestoinvestigate_entity, get_area_diagnostic, get_entity_with_automations, audit_config_orphans
Grafograph_build_index, graph_find_references, graph_entity_impact, graph_get_neighbors, graph_detect_ghost_references, graph_detect_orphans, graph_export_mermaid
Herramientas de desarrollotest_template, compare_templates, diagnose_entity, check_entity_exists, validate_automation_trigger, diagnose_template

Catálogo completo de herramientas con esquemas disponible en GET /api/tools

Novedades en v2.0.0

  • Cambio importante — limpieza de transporte: Se eliminó el transporte heredado HTTP+SSE de dos endpoints. Los transportes MCP compatibles ahora son solo stdio y Streamable HTTP; MCP_TRANSPORT=sse se rechaza.
  • Despliegue de red reforzado: Aplicación ASGI explícita con límites de tamaño de solicitud/cabecera, política de Host de confianza (MCP_ALLOWED_HOSTS), CORS de origen exacto, límites de conexión y selección de modo sin estado/con estado.
  • Redacción recursiva de credenciales: Todas las respuestas de herramientas se sanitizan en el límite de la operación: tokens de portador, JWT, claves de API, contraseñas y direcciones IP se redactan tanto de las cargas útiles de respuesta como de la salida de registros.
  • Descubrimiento de capacidades: El descubrimiento público ahora separa los transportes/componentes compatibles y activos, e informa la identidad del servidor, SDK, protocolo y perfil de despliegue.
  • Correcciones de fiabilidad: Corrección de rendimiento de diagnose_automation_aliases (>120 s a ~4,5 s en una instancia con 131 automatizaciones); sondeo de salud del backend con reintentos al inicio y reconciliación en segundo plano; corrutinas de almacenamiento bloqueantes ejecutadas a través del ejecutor de invocación limitado.
  • Verificación y evidencia: La alineación con ai-skills utiliza un validador fijado y pruebas de cassette grabadas en Home Assistant real. CI alojado de cabecera exacta verifica 1.234 pruebas unitarias, 17 pruebas de protocolo, la rueda instalada y artefactos de contenedor amd64/arm64. La evidencia de HA en vivo vinculada a revisión se documenta por separado en docs/evidence-live-27d32c9b.md y se aplica solo a la revisión nombrada allí.

También heredado de v1.6.0

  • 5 herramientas: get_context_chain, resolve_blueprint_automation, get_cache_stats, compare_templates, get_automation_entity_id
  • Paginación de registros (limit/offset en get_entity_registry, get_device_registry, get_area_registry, get_config_entries)
  • Campo data_quality en herramientas de diagnóstico compuestas
  • choose_analysis en diagnose_automation (detail_level="full")

Configuración del cliente

Stdio local

Instala la rueda y configura el cliente para iniciar el servidor como subproceso. Este es el transporte predeterminado y no expone un puerto de red MCP.

{
  "mcpServers": {
    "ha-mcp-readonly": {
      "command": "ha-mcp-readonly",
      "env": {
        "HA_URL": "http://homeassistant.local:8123",
        "HA_TOKEN": "replace-with-a-long-lived-access-token",
        "HA_CONFIG_PATH": "/path/to/home-assistant/config"
      }
    }
  }
}

Streamable HTTP autenticado

Establece MCP_TRANSPORT=http, MCP_AUTH_TOKEN y una dirección de enlace controlada. El endpoint es /mcp. Se eliminó la compatibilidad heredada con /sse y MCP_TRANSPORT=sse se rechaza.

{
  "mcpServers": {
    "ha-mcp-readonly": {
      "url": "http://127.0.0.1:9092/mcp",
      "headers": {
        "Authorization": "Bearer replace-with-a-high-entropy-caller-token"
      }
    }
  }
}

El catálogo predeterminado contiene 145 herramientas de solo lectura. Las herramientas solo para desarrolladores permanecen deshabilitadas a menos que se establezca MCP_DEV_TOOLS_ENABLED=1.

Generador de contexto

El generador de contexto crea una instantánea Markdown limitada para análisis sin conexión, sistemas de recuperación, conocimiento de proyectos de IA, auditorías y resolución de problemas.

ModoAcceso a datos
offlineSolo configuración local de Home Assistant y registros de almacenamiento seguros. El acceso a la red está deshabilitado por construcción.
onlineAPIs REST y WebSocket de Home Assistant. La falta de acceso de red requerido falla la ejecución.
hybridFuentes locales más todas las fuentes de API compatibles disponibles para el token configurado.

El artefacto incluye las secciones de análisis normales y una matriz de Procedencia de fuentes y completitud. Cada fuente intentada registra su método, estado, número de registros, número de bytes, número de redacciones, ventana solicitada y motivo de fallo u omisión. La Instantánea integral de datos seguros incluye todos los datos compatibles y accesibles dentro de los límites configurados:

  • estados, servicios, componentes, eventos, configuración, historial, logbook, registro de errores, calendarios y eventos de calendario;
  • datos de entidad, dispositivo, área, piso, etiqueta, categoría, entrada de configuración, energía, panel, recurso Lovelace, reparación, salud del sistema y pipeline de Assist expuestos por Home Assistant;
  • elementos de tareas pendientes y cada tipo de pronóstico meteorológico anunciado descubierto dinámicamente a partir de los estados de entidad;
  • todos los registros seguros descubribles de .storage más datos de inventario YAML, JSON y archivos bajo la raíz configurada;
  • análisis de automatización, script, escena, blueprint, plantilla, helper, persona, zona, energía, HACS, caché, dependencia, panel y diagnóstico.

Los almacenes de credenciales están excluidos. Los campos sensibles, tokens de portador, JWT, parámetros de consulta secretos y valores de !secret se redactan. Los medios binarios, transmisiones de cámara, contenidos de copias de seguridad, bases de datos y registros con credenciales no se copian. Las fuentes no disponibles por permisos, integraciones faltantes, comandos no compatibles, ventanas configuradas o límites de tamaño permanecen visibles en la procedencia en lugar de omitirse silenciosamente.

Los límites relevantes son HA_CONTEXT_HISTORY_HOURS, HA_CONTEXT_LOG_HOURS, HA_CONTEXT_CALENDAR_DAYS, HA_CONTEXT_MAX_SOURCE_BYTES y HA_CONTEXT_MAX_OUTPUT_BYTES.

Generación consciente del presupuesto

El generador puede limitar la salida en el origen en lugar de emitir todo y dejar que los consumidores lo reduzcan. Las opciones están disponibles a través del entorno (HA_CONTEXT_PROFILE, HA_CONTEXT_SECTIONS, HA_CONTEXT_DETAIL, HA_CONTEXT_INCLUDE_FILES, HA_CONTEXT_INCLUDE_STORAGE, HA_CONTEXT_ON_BUDGET_EXCEEDED) y mediante la llamada de generación REST:

OpciónValoresPredeterminadoEfecto
profilefull, agent, compactfullPreajuste de sección. full renderiza todo (comportamiento histórico); agent elimina las secciones pesadas de instantánea sin procesar, registros y cambios recientes; compact renderiza solo resumen, procedencia, salud del sistema, topología y referencia rápida.
maxBytesentero ≥ 1024, ≤ 128 MiBHA_CONTEXT_MAX_OUTPUT_BYTES (96 MiB si no se establece)Presupuesto de bytes de salida. Omitir maxBytes hereda el valor de entorno configurado. Las secciones que no caben se omiten completas y se informan.
sectionsclaves de sección o aliasperfil predeterminadoSelección explícita que anula el perfil. Alias: runtime, health, provenance, logs. El resumen ejecutivo y las secciones de procedencia de fuentes siempre se incluyen.
repositoryFiles / include_filesbooleanotrueCuando false, la instantánea integral sin procesar no recopila ni serializa los cuerpos de archivos de configuración. Las secciones de análisis estructurado (registros, automatizaciones, dispositivos) permanecen como vistas de metadatos derivados y no se ven afectadas.
storageRecordsbooleanotrueCuando false, la instantánea integral sin procesar no recopila registros seguros de .storage.
detailfull, compactfullAlias que se resuelve a profile=compact cuando no se proporciona un perfil explícito.
onBudgetExceededauto, fail, truncateautoPolítica resuelta: auto se comporta como fail para el perfil full (preservando la ejecución histórica de cierre ante fallo) y como truncate para agent/compact; fail/truncate explícitos siempre ganan.

Los valores predeterminados de las opciones REST se resuelven por la capa REST como se muestra; no heredan sus valores predeterminados no booleanos de las variables de entorno correspondientes — solo maxBytes recurre a su valor de entorno.

El resultado de la generación informa output_bytes, uncompressed_bytes, output_sha256, profile, requested_sections (la selección original resuelta), selected_sections (la selección efectiva incluido el mínimo obligatorio), rendered_sections, omitted_sections (con tamaños de bytes exactos por sección y motivos) y truncated. Deshabilitar archivos de repositorio o registros de almacenamiento registra una omisión explícita de policy: en la matriz de procedencia: nada se omite silenciosamente. El resumen ejecutivo y las secciones de procedencia de fuentes siempre se renderizan, incluso bajo selecciones de sección explícitas, por lo que cada artefacto lleva su registro de completitud. La identidad de la fuente y del entorno de ejecución se transportan mediante campos de resultado dedicados: config_path identifica la raíz auditada de configuración de Home Assistant (identidad de la fuente), mientras que mode, profile_revision y generated_at identifican las condiciones del entorno de ejecución que las generan (identidad del entorno); output_sha256 fija los bytes exactos del artefacto. Por lo tanto, los consumidores siempre pueden atribuir un artefacto al estado de la instancia y a la revisión del generador que lo produjo.

Las instancias vacías son un caso de éxito: una generación sobre una instancia válida pero con cero registros se completa normalmente, muestra secciones con conteo cero e informa contadores a cero con truncated: false. Solo las opciones no válidas, las violaciones de presupuesto bajo la política de fallo o los datos requeridos no disponibles hacen fallar la ejecución.

Dos decisiones de diseño deliberadas, registradas para los consumidores del issue #33: agent es la vista operativa acotada destinada al consumo por agentes, mientras que el valor predeterminado de la API sigue siendo el perfil histórico full por compatibilidad con versiones anteriores; los llamadores optan explícitamente por la vista acotada. El truncamiento se aplica a nivel de sección completa y se informa explícitamente; el truncamiento parcial (a mitad de sección) nunca se aplica de forma silenciosa, por lo que el contrato se asigna como included_sectionsrendered_sections, truncated_sectionsomitted_sections y bytesoutput_bytes.

Nota de seguridad: los ejemplos anteriores son solo de bucle local. Cuando el adaptador REST se expone a través de un proxy inverso remoto, termine TLS en el proxy y exija HTTPS a los clientes; el HTTP sin cifrar transmite el token de portador en texto claro.

curl -X POST http://127.0.0.1:9093/api/context/generate \
  -H "Authorization: Bearer $REST_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"mode":"hybrid","profile":"agent","maxBytes":2097152}'

curl -X POST http://127.0.0.1:9093/api/context/generate \
  -H "Authorization: Bearer $REST_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"mode":"offline","detail":"compact"}'
curl -H "Authorization: Bearer $REST_API_TOKEN" \
  http://127.0.0.1:9093/api/context/status

curl -H "Authorization: Bearer $REST_API_TOKEN" \
  http://127.0.0.1:9093/api/context/download > ha-ai-context.md

API REST

El adaptador de compatibilidad REST opcional está deshabilitado de forma predeterminada. Cuando está habilitado, todas las rutas excepto health requieren un token de portador y usan el mismo manifiesto, capacidades, plazo, concurrencia, tamaño de respuesta y política de errores que MCP.

curl -H "Authorization: Bearer $REST_API_TOKEN" \
  'http://127.0.0.1:9093/api/tools?detail=full'

curl -X POST http://127.0.0.1:9093/api/tools/get_entity_state \
  -H "Authorization: Bearer $REST_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"entity_id":"sun.sun"}'

curl -H "Authorization: Bearer $REST_API_TOKEN" \
  http://127.0.0.1:9093/api/openapi.json

Desarrollo

Configuración

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

Ejecutar pruebas

# Deterministic local gates
pytest tests/unit/ -q
pytest tests/protocol/ -q

# Backend-dependent suites; require an isolated Home Assistant and credentials
export HA_URL=http://your-ha:8123
export HA_TOKEN=your_token
pytest tests/smoke/ tests/integration/ tests/e2e/ -q

Las pruebas dependientes del backend informan omisiones cuando el entorno requerido de Home Assistant no está presente. CI instala el wheel en un entorno limpio, ejecuta un subproceso stdio real y verifica health, metadatos REST, el ciclo de vida del contexto sin conexión y Streamable HTTP autenticado contra los contenedores de lanzamiento compilados. El flujo de trabajo de lanzamiento compila por separado un candidato multiplataforma en cuarentena, prueba su digest exacto en amd64 y arm64, y promueve solo ese digest desde el publicador protegido.

Lint y formato

ruff check .
ruff format --check .

Arquitectura

server.py                  # Main entry point — FastMCP + REST API + health check
context_generator/
├── config.py              # Immutable per-run configuration
├── constants.py           # Legacy/static analyzer defaults and HA YAML loader
├── runtime.py             # Context-local runtime and provenance scope
├── provenance.py          # Completeness matrix and redaction
├── snapshot.py            # Safe filesystem, REST, and WebSocket collectors
├── storage_policy.py      # Positive allowlist for model-visible .storage data
├── core.py                # Isolated generation entry points
├── analyzers.py           # Domain analyzers
├── formatters.py          # Atomic bounded Markdown output
└── utils.py               # Runtime-aware registry and API adapters

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)

Seguridad

  • Solo lectura por diseño — sin operaciones de escritura en Home Assistant. No puede modificar estados, ejecutar servicios ni activar automatizaciones.
  • Restricciones del sistema de archivos — acceso limitado al directorio /config. El recorrido de rutas (.., ~) está bloqueado. Tamaño máximo de archivo 10 MB. Profundidad máxima de directorio 20.
  • Datos de autenticación bloqueados — los registros de auth, auth_provider.* y onboarding nunca se devuelven.
  • Redacción de credencialesHA_TOKEN nunca se registra ni se expone en las salidas. Los JWT, contraseñas, claves de API y direcciones IP se sanean de la salida de registros.

Notas

  • El servidor puede exponer 9091 (health), 9092 (Streamable HTTP MCP autenticado) y 9093 (adaptador REST/contexto autenticado opcional). Stdio sigue siendo el transporte MCP predeterminado.
  • MCP_DEV_TOOLS_ENABLED=0 deshabilita la ejecución de plantillas y las herramientas de depuración para uso en producción.
  • Nota de seguridad: los puertos 9091-9093 no deben exponerse públicamente. Use reglas de firewall o un proxy inverso con autenticación si es necesario.
  • Los archivos de registro (áreas, dispositivos, entidades, entradas de configuración) se almacenan en caché durante 5 minutos para reducir la E/S del sistema de archivos.
  • Todas las respuestas de las herramientas devuelven JSON con un campo success — verifique siempre este campo antes de leer data.

Solución de problemas

Para problemas comunes y sus soluciones, consulte docs/documentation.md#troubleshooting.

Licencia

MIT — consulte LICENSE para más detalles.