ha-mcp-readonly

Servidor MCP (Model Context Protocol) somente leitura para Home Assistant. Oferece aos assistentes de IA (Claude Desktop, LibreChat, Cline) visibilidade total da sua casa inteligente — estados de entidades, automações, scripts, dispositivos, logs, diagnósticos — sem qualquer acesso de escrita. Também gera snapshots estáticos de contexto de IA para sistemas RAG, Projetos ChatGPT, Qwen e outras ferramentas que aceitam arquivos de conhecimento personalizados. Desenvolvido em Python, funciona em qualquer lugar — localmente, em Docker ou como integração MCP.

Documentação

HA-MCP-Readonly

CI Docker Python 3.11+ License: MIT

Servidor MCP (Model Context Protocol) somente leitura para Home Assistant. Dá aos assistentes de IA (Claude Desktop, LibreChat, Cline) visibilidade total da sua casa inteligente — estados de entidades, automações, scripts, dispositivos, logs, diagnósticos — sem qualquer acesso de escrita. Também gera snapshots estáticos de contexto de IA para sistemas RAG, ChatGPT Projects, Qwen e outras ferramentas que aceitam arquivos de conhecimento personalizados. Construído em Python, roda em qualquer lugar — localmente, em Docker ou como integração MCP.

Requisitos

  • Python 3.11+ (para uso local) ou Docker
  • Uma instância do Home Assistant com um token de acesso de longa duração
    • Crie um no seu perfil do HA: Configurações → Segurança → Tokens de acesso de longa duração
  • Acesso ao diretório de configuração do seu Home Assistant (para ferramentas de sistema de arquivos)

Início Rápido

1. Configure o ambiente

cp .env.example .env

Edite o .env com suas credenciais:

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: O arquivo .env contém seu token de acesso. Ele está no gitignore e nunca deve ser commitado.

2. Execute com Docker

Primeiro, configure suas credenciais. Use um arquivo .env (recomendado) ou passe as variáveis diretamente.

Opção A — com arquivo .env e docker compose:

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

O docker-compose.yml incluído puxa a imagem do GitHub Container Registry e monta sua configuração do HA somente leitura:

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"]

Opção B — com docker run simples:

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

Compilando localmente:

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

3. Execute localmente (Python 3.11+)

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

Portas

PortaProtocoloFinalidadeEndpoint
9091HTTPVerificação de saúdeGET /health
9092HTTPMCP HTTP Streamable autenticado/mcp
9093HTTPAPI REST autenticada opcional + Gerador de Contexto/api/*

Verifique

# 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.

Ferramentas Disponíveis (158 com ferramentas de desenvolvimento, 145 sem)

As ferramentas são organizadas por categoria (75 mostradas na tabela abaixo). Todas são somente leitura — sem mudanças de estado, sem chamadas de serviço, sem modificações.

CategoriaFerramentas principais
Estadosget_entity_state, get_states_grouped, search_entities, get_domains_summary, get_system_overview
Automaçõeslist_automations, get_automation_code, get_automation_file_location, diagnose_automation, search_automations_by_entity, get_automation_conflicts, get_automation_entity_id
Scripts e Cenaslist_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 e Áreasget_device_details, search_devices, get_devices_by_area, get_area_devices_summary
Entradas de configuraçãoget_config_entry_details, search_config_entries, diagnose_config_entry, list_config_entry_domains
Integraçõesget_integration_entities, get_integration_summary
Diagnósticosdiagnose_system_health, get_unavailable_entities_grouped, get_integration_health, diagnose_person_tracking
Logsget_log_insights, analyze_log_errors, get_startup_errors, get_log_timeline, search_logs
Históricoget_entity_state_history_summary, get_recent_state_changes
Contextoentity_get_context_tree, get_entity_dependencies, get_entity_consumers, get_context_chain
Configuraçãoget_main_configuration, search_in_config, validate_yaml_syntax, read_config_file
Armazenamentosearch_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
Compostoinvestigate_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
Ferramentas de desenvolvimentotest_template, compare_templates, diagnose_entity, check_entity_exists, validate_automation_trigger, diagnose_template

Catálogo completo de ferramentas com schemas disponível em GET /api/tools

Novidades na v2.0.0

  • Quebra — limpeza de transporte: Removido o transporte legado HTTP+SSE de dois endpoints. Os transportes MCP suportados agora são apenas stdio e Streamable HTTP; MCP_TRANSPORT=sse é rejeitado.
  • Implantação de rede endurecida: Aplicação ASGI explícita com limites de tamanho de requisição/cabeçalho, política de Host confiável (MCP_ALLOWED_HOSTS), CORS de origem exata, limites de conexão e seleção de modo stateless/stateful.
  • Redação recursiva de credenciais: Todas as respostas de ferramentas são sanitizadas na fronteira da operação — bearer tokens, JWTs, chaves de API, senhas e endereços IP são redigidos tanto nos payloads de resposta quanto na saída de logs.
  • Descoberta de capacidades: A descoberta pública agora separa transportes/componentes suportados e ativos e reporta identidade do servidor, SDK, protocolo e perfil de implantação.
  • Correções de confiabilidade: Correção de desempenho do diagnose_automation_aliases (>120s para ~4.5s em uma instância com 131 automações); sondas de saúde do backend com novas tentativas na inicialização e reconciliação em segundo plano; corrotinas de armazenamento bloqueantes executadas através do executor de invocação limitado.
  • Verificação e evidência: O alinhamento com ai-skills usa um validador fixado e testes de cassete gravados em Home Assistant real. CI hospedada com head exato verifica 1.234 testes de unidade, 17 testes de protocolo, o wheel instalado e artefatos de contêiner amd64/arm64. Evidência de HA ao vivo vinculada a revisão é documentada separadamente em docs/evidence-live-27d32c9b.md e se aplica apenas à revisão nomeada ali.

Também mantido da v1.6.0

  • 5 ferramentas: get_context_chain, resolve_blueprint_automation, get_cache_stats, compare_templates, get_automation_entity_id
  • Paginação de registros (limit/offset em get_entity_registry, get_device_registry, get_area_registry, get_config_entries)
  • Campo data_quality em ferramentas de diagnóstico compostas
  • choose_analysis em diagnose_automation (detail_level="full")

Configuração do cliente

Stdio local

Instale o wheel e configure o cliente para iniciar o servidor como um subprocesso. Este é o transporte padrão e não expõe uma porta de rede 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

Defina MCP_TRANSPORT=http, MCP_AUTH_TOKEN e um endereço de bind controlado. O endpoint é /mcp. O suporte legado a /sse foi removido e MCP_TRANSPORT=sse é rejeitado.

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

O catálogo padrão contém 145 ferramentas somente leitura. Ferramentas exclusivas para desenvolvedores permanecem desabilitadas a menos que MCP_DEV_TOOLS_ENABLED=1 esteja definido.

Gerador de Contexto

O gerador de contexto cria um snapshot Markdown limitado para análise offline, sistemas de recuperação, conhecimento de projetos de IA, auditorias e solução de problemas.

ModoAcesso a dados
offlineApenas configuração local do Home Assistant e registros de armazenamento seguro. O acesso à rede é desabilitado por construção.
onlineAPIs REST e WebSocket do Home Assistant. A falta de acesso de rede necessário falha a execução.
hybridFontes locais mais todas as fontes de API suportadas disponíveis para o token configurado.

O artefato inclui as seções normais de análise e uma matriz de Proveniência e Completude de Fontes. Cada fonte tentada registra seu método, status, contagem de registros, contagem de bytes, contagem de redações, janela solicitada e motivo de falha ou omissão. O Snapshot Abrangente de Dados Seguros inclui todos os dados suportados e acessíveis dentro dos limites configurados:

  • estados, serviços, componentes, eventos, configuração, histórico, logbook, log de erros, calendários e eventos de calendário;
  • dados de entidade, dispositivo, área, piso, rótulo, categoria, entrada de configuração, energia, painel, recurso Lovelace, reparo, saúde do sistema e pipeline Assist expostos pelo Home Assistant;
  • itens de tarefas e todos os tipos de previsão do tempo anunciados descobertos dinamicamente a partir dos estados das entidades;
  • todos os registros seguros descobertos de .storage mais dados de inventário YAML, JSON e arquivos sob a raiz configurada;
  • análise de automação, script, cena, blueprint, template, helper, pessoa, zona, energia, HACS, cache, dependência, painel e diagnóstico.

Armazenamentos de credenciais são excluídos. Campos sensíveis, bearer tokens, JWTs, parâmetros de consulta secretos e valores de !secret são redigidos. Mídia binária, streams de câmera, conteúdos de backup, bancos de dados e registros com credenciais não são copiados. Fontes indisponíveis devido a permissões, integrações ausentes, comandos não suportados, janelas configuradas ou limites de tamanho permanecem visíveis na proveniência em vez de serem omitidas silenciosamente.

Limites relevantes são HA_CONTEXT_HISTORY_HOURS, HA_CONTEXT_LOG_HOURS, HA_CONTEXT_CALENDAR_DAYS, HA_CONTEXT_MAX_SOURCE_BYTES e HA_CONTEXT_MAX_OUTPUT_BYTES.

Geração com orçamento consciente

O gerador pode limitar a saída na fonte em vez de emitir tudo e deixar os consumidores reduzirem. As opções estão disponíveis através do ambiente (HA_CONTEXT_PROFILE, HA_CONTEXT_SECTIONS, HA_CONTEXT_DETAIL, HA_CONTEXT_INCLUDE_FILES, HA_CONTEXT_INCLUDE_STORAGE, HA_CONTEXT_ON_BUDGET_EXCEEDED) e através da chamada REST de geração:

OpçãoValoresPadrãoEfeito
profilefull, agent, compactfullPredefinição de seção. full renderiza tudo (comportamento histórico); agent remove as seções pesadas de snapshot bruto, log e mudanças recentes; compact renderiza apenas resumo, proveniência, saúde do sistema, topologia e referência rápida.
maxBytesinteiro ≥ 1024, ≤ 128 MiBHA_CONTEXT_MAX_OUTPUT_BYTES (96 MiB quando não definido)Orçamento de bytes de saída. Omitir maxBytes herda o valor de ambiente configurado. Seções que não cabem são omitidas inteiras e reportadas.
sectionschaves de seção ou aliasespadrão do perfilSeleção explícita que substitui o perfil. Aliases: runtime, health, provenance, logs. O resumo executivo e as seções de proveniência de fontes são sempre incluídos.
repositoryFiles / include_filesbooleanotrueQuando false, o snapshot bruto abrangente não coleta nem serializa corpos de arquivos de configuração. Seções de análise estruturada (registros, automações, dispositivos) permanecem como visualizações de metadados derivados e não são afetadas.
storageRecordsbooleanotrueQuando false, o snapshot bruto abrangente não coleta registros seguros de .storage.
detailfull, compactfullAlias que resolve para profile=compact quando nenhum perfil explícito é fornecido.
onBudgetExceededauto, fail, truncateautoPolítica resolvida: auto se comporta como fail para o perfil full (preservando a execução histórica com falha fechada) e como truncate para agent/compact; fail/truncate explícitos sempre vencem.

Os padrões das opções REST são resolvidos pela camada REST conforme mostrado; eles não herdam seus padrões não booleanos das variáveis de ambiente correspondentes — apenas maxBytes recorre ao seu valor de ambiente.

O resultado da geração reporta output_bytes, uncompressed_bytes, output_sha256, profile, requested_sections (a seleção original resolvida), selected_sections (a seleção efetiva incluindo o piso obrigatório), rendered_sections, omitted_sections (com tamanhos exatos de bytes por seção e motivos) e truncated. Desabilitar arquivos de repositório ou registros de armazenamento registra uma omissão explícita de policy: na matriz de proveniência — nada é omitido silenciosamente. O resumo executivo e as seções de proveniência de fontes são sempre renderizados, inclusive sob seleções explícitas de seção, para que todo artefato carregue seu registro de completude. A identidade de origem e de runtime é transportada por campos de resultado dedicados: config_path identifica a raiz de configuração do Home Assistant auditada (identidade de origem), enquanto mode, profile_revision e generated_at identificam as condições de runtime que geraram o artefato (identidade de runtime); output_sha256 fixa os bytes exatos do artefato. Os consumidores podem, portanto, sempre atribuir um artefato ao estado da instância e à revisão do gerador que o produziu.

Instâncias vazias são um caso de sucesso: uma geração sobre uma instância válida, mas com zero registros, é concluída normalmente, renderiza seções com contagem zero e reporta contadores zerados com truncated: false. Apenas opções inválidas, violações de orçamento sob a política de falha ou dados obrigatórios indisponíveis fazem a execução falhar.

Duas decisões de design deliberadas, registradas para os consumidores da issue #33: agent é a visão operacional limitada destinada ao consumo por agentes, enquanto o padrão da API permanece o perfil histórico full para compatibilidade retroativa — os chamadores optam explicitamente pela visão limitada. A truncagem é aplicada na granularidade de seção inteira e reportada explicitamente; a truncagem parcial de conteúdo (no meio da seção) nunca é aplicada silenciosamente, então o contrato mapeia como included_sectionsrendered_sections, truncated_sectionsomitted_sections e bytesoutput_bytes.

Nota de segurança: os exemplos acima são apenas de loopback. Quando o adaptador REST for exposto por meio de um proxy reverso remoto, encerre o TLS no proxy e exija HTTPS dos clientes — HTTP simples transmite o token de portador em 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

O adaptador de compatibilidade REST opcional está desabilitado por padrão. Quando habilitado, todas as rotas, exceto health, exigem um token de portador e usam a mesma política de manifesto, capacidade, prazo, concorrência, tamanho de resposta e erro que o 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

Desenvolvimento

Configuração

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

Executar testes

# 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

Testes dependentes do backend relatam pulos quando o ambiente Home Assistant necessário está ausente. A CI instala o wheel em um ambiente limpo, executa um subprocesso stdio real e verifica health, metadados REST, o ciclo de vida do contexto offline e Streamable HTTP autenticado contra contêineres de release construídos. O fluxo de trabalho de release separadamente constrói um candidato multi-plataforma em quarentena, testa o digest exato em amd64 e arm64 e promove apenas esse digest do publicador protegido.

Lint e formatação

ruff check .
ruff format --check .

Arquitetura

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)

Segurança

  • Somente leitura por design — nenhuma operação de escrita no Home Assistant. Não pode modificar estados, executar serviços ou acionar automações.
  • Restrições de sistema de arquivos — acesso limitado ao diretório /config. Travessia de caminho (.., ~) bloqueada. Tamanho máximo de arquivo 10MB. Profundidade máxima de diretório 20.
  • Dados de autenticação bloqueados — registros de auth, auth_provider.*, onboarding nunca são retornados.
  • Redação de credenciaisHA_TOKEN nunca é registrado ou exposto nas saídas. JWTs, senhas, chaves de API e endereços IP são sanitizados da saída de log.

Notas

  • O servidor pode expor 9091 (health), 9092 (Streamable HTTP MCP autenticado) e 9093 (adaptador REST/contexto autenticado opcional). Stdio permanece o transporte MCP padrão.
  • MCP_DEV_TOOLS_ENABLED=0 desabilita a execução de templates e ferramentas de depuração para uso em produção.
  • Nota de segurança: As portas 9091-9093 não devem ser expostas publicamente. Use regras de firewall ou proxy reverso com autenticação, se necessário.
  • Arquivos de registro (áreas, dispositivos, entidades, entradas de configuração) são armazenados em cache por 5 minutos para reduzir I/O do sistema de arquivos.
  • Todas as respostas de ferramentas retornam JSON com um campo success — sempre verifique isso antes de ler data.

Solução de problemas

Para problemas comuns e soluções, consulte docs/documentation.md#troubleshooting.

Licença

MIT — consulte LICENSE para detalhes.