deConz MCP
Servidor MCP para o servidor deConz desenvolvido pela Dresden Elektronik (ponte entre plataformas de automação residencial inteligente e redes Zigbee sem fio)
Documentação
Servidor deConz MCP
Um servidor MCP (Model Context Protocol) que expõe a API REST do deCONZ para assistentes de IA. Controle luzes Zigbee, sensores, grupos, cenas, regras e agendamentos por meio de linguagem natural.
Suporta transportes stdio, SSE e Streamable HTTP. Os transportes HTTP são protegidos por um token bearer configurável.
Requisitos
- Python ≥ 3.10
- uv (recomendado) ou pip
- Um gateway deCONZ / Phoscon em execução com um adaptador ConBee ou RaspBee
- Uma chave de API REST do deCONZ válida (veja Obtendo uma chave de API)
Instalação
# Clone the repository
git clone https://github.com/marcinn2/deconz-mcp.git
cd deconz-mcp
# Install with uv (creates an isolated virtual environment)
uv sync
# Or install with pip into your environment
pip install -e .
Obtendo uma chave de API
- Abra o Phoscon App no seu navegador (geralmente
http://<gateway-ip>/pwa). - Vá para Menu → Configurações → Gateway → Avançado.
- Clique em Autenticar aplicativo — isso abre a rede por 60 segundos.
- Dentro desses 60 segundos, execute:
curl -s -X POST http://<gateway-ip>/api \
-H "Content-Type: application/json" \
-d '{"devicetype": "deconz-mcp"}'
A resposta contém sua chave de API:
[{"success": {"username": "YOUR-API-KEY-HERE"}}]
Armazene-a como DECONZ_API_KEY.
Início rápido
stdio (Claude Desktop)
DECONZ_HOST=192.168.1.10 DECONZ_API_KEY=abc123def deconz-mcp
Streamable HTTP com autenticação bearer
DECONZ_HOST=192.168.1.10 \
DECONZ_API_KEY=abc123def \
MCP_AUTH_TOKEN=my-mcp-secret \
deconz-mcp --transport streamable-http --host 0.0.0.0 --port 8080
SSE + Streamable HTTP combinados
DECONZ_HOST=192.168.1.10 \
DECONZ_API_KEY=abc123def \
MCP_AUTH_TOKEN=my-mcp-secret \
deconz-mcp --transport server --host 0.0.0.0 --port 8080
Variáveis de ambiente
| Variável | Obrigatória | Padrão | Descrição |
|---|---|---|---|
DECONZ_HOST | Sim* | — | IP ou hostname do gateway deCONZ |
DECONZ_PORT | Não | 80 | Porta HTTP do gateway deCONZ |
DECONZ_API_KEY | Sim* | — | Chave da API REST do deCONZ |
DECONZ_TLS | Não | false | Defina true para usar HTTPS |
DECONZ_TLS_VERIFY | Não | true | false aceita um certificado de gateway autoassinado; qualquer outro valor é um caminho para um pacote de CA |
DECONZ_ALLOW_RUNTIME_CONFIG | Não | veja‡ | Defina true para expor configure_deconz mesmo quando o gateway vem do ambiente |
MCP_AUTH_TOKEN | Não† | — | Token bearer que os clientes devem enviar a este servidor MCP |
MCP_BASE_URL | Não | http://<host>:<port> | URL base pública (usada como URL do emissor OAuth) |
* Não obrigatória ao usar stdio e chamar configure_deconz em tempo de execução.
† Fortemente recomendada para transportes HTTP expostos além de localhost.
‡ Padrão habilitado apenas quando DECONZ_HOST / DECONZ_API_KEY estão ausentes. Uma vez que o gateway
é configurado a partir do ambiente, a ferramenta é retida para que um cliente não possa redirecionar este
servidor para outro host.
Referência da CLI
usage: deconz-mcp [--transport {stdio,sse,streamable-http,server}]
[--host HOST] [--port PORT]
[--log-level {DEBUG,INFO,WARNING,ERROR}]
[--auth-token TOKEN] [--base-url URL]
| Flag | Padrão | Descrição |
|---|---|---|
--transport | stdio | Modo de transporte |
--host | 127.0.0.1 | Endereço de bind (transportes HTTP) |
--port | 8000 | Porta de escuta (transportes HTTP) |
--log-level | INFO | Nível de verbosidade do log |
--auth-token | $MCP_AUTH_TOKEN | Token bearer do MCP |
--base-url | $MCP_BASE_URL | URL do emissor OAuth |
Modos de transporte
| Modo | Endpoint(s) | Descrição |
|---|---|---|
stdio | stdin/stdout | Baseado em pipe — para Claude Desktop e uso local |
sse | /sse, /messages/ | SSE legado (MCP pré-2025-03-26) |
streamable-http | /mcp | Streamable HTTP moderno (MCP 2025-03-26) |
server | todos os acima | SSE + Streamable HTTP em uma única porta |
Autenticação
Chave da API do deCONZ
A chave da API REST do deCONZ é uma credencial do gateway que viaja como parte do caminho da URL (/api/<apikey>/...). Ela é configurada no lado do servidor via DECONZ_API_KEY e nunca é exposta aos clientes MCP: as URLs de requisição são mantidas fora dos erros das ferramentas, e o log de requisições do cliente HTTP é silenciado porque, caso contrário, escreveria a chave no stderr a cada chamada.
IDs de recursos fornecidos por um cliente (IDs de luz, grupo, cena, sensor, regra, agendamento e Touchlink) são validados antes de serem colocados em um caminho de requisição, de modo que um ID malformado não possa escapar de seu recurso e alcançar, por exemplo, a configuração do gateway ou sua lista de chaves de API.
Token bearer do MCP
A opção MCP_AUTH_TOKEN / --auth-token protege o próprio servidor MCP. Toda requisição HTTP de um cliente MCP deve incluir:
Authorization: Bearer <token>
O token é verificado com uma comparação de tempo constante para prevenir ataques de timing. Ao executar apenas em localhost (bind padrão 127.0.0.1), a autenticação bearer é opcional, mas recomendada.
Ferramentas
Conexão / configuração
| Ferramenta | Descrição |
|---|---|
configure_deconz | Aponta o servidor para um gateway deCONZ em tempo de execução (host, porta, chave da API). Registrada apenas quando o gateway não é configurado a partir do ambiente, ou quando DECONZ_ALLOW_RUNTIME_CONFIG=true |
get_gateway_config | Lê nome do gateway, firmware, canal Zigbee, IP, porta WebSocket |
set_permit_join | Abre a rede Zigbee para pareamento de novos dispositivos (0–255 segundos) |
Luzes
| Ferramenta | Descrição |
|---|---|
list_lights | Lista todas as luzes com ligado/desligado, brilho e acessibilidade |
get_light | Detalhes JSON completos de uma única luz |
set_light_state | Controla energia, brilho, matiz, saturação, temperatura de cor, xy, efeito, alerta |
rename_light | Renomeia uma luz |
delete_light | Remove uma luz do gateway |
Grupos
| Ferramenta | Descrição |
|---|---|
list_groups | Lista todos os grupos com contagem de membros e estado de ação |
get_group | Detalhes JSON completos de um único grupo |
create_group | Cria um novo grupo (opcionalmente pré-populado com luzes) |
set_group_action | Controla todas as luzes de um grupo simultaneamente |
modify_group | Renomeia um grupo ou altera suas luzes membro |
delete_group | Exclui um grupo (as luzes permanecem) |
Cenas
| Ferramenta | Descrição |
|---|---|
list_scenes | Lista todas as cenas de um grupo |
get_scene | Detalhes JSON completos de uma cena |
create_scene | Cria uma cena (captura o estado atual do grupo) |
recall_scene | Ativa uma cena |
store_scene | Sobrescreve uma cena com o estado atual do grupo |
rename_scene | Renomeia uma cena |
delete_scene | Exclui uma cena |
Sensores
| Ferramenta | Descrição |
|---|---|
list_sensors | Lista todos os sensores com leituras mais recentes e níveis de bateria |
get_sensor | Detalhes JSON completos de um único sensor |
rename_sensor | Renomeia um sensor |
set_sensor_config | Atualiza a configuração do sensor (habilitado, nível de bateria, sensibilidade) |
delete_sensor | Remove um sensor do gateway |
Regras (automações)
| Ferramenta | Descrição |
|---|---|
list_rules | Lista todas as regras de automação com status e contagens de gatilho |
get_rule | Detalhes JSON completos (condições + ações) de uma regra |
create_rule | Cria uma nova regra com condições e ações |
set_rule_status | Habilita ou desabilita uma regra |
delete_rule | Exclui uma regra |
Agendamentos
| Ferramenta | Descrição |
|---|---|
list_schedules | Lista todos os agendamentos temporizados |
get_schedule | Detalhes JSON completos de um agendamento |
create_schedule | Cria um novo agendamento com expressão de tempo ISO 8601 |
set_schedule_status | Habilita ou desabilita um agendamento |
delete_schedule | Exclui um agendamento |
Touchlink
| Ferramenta | Descrição |
|---|---|
touchlink_scan | Inicia uma varredura Touchlink (~10 s) para encontrar dispositivos Zigbee próximos |
get_touchlink_results | Retorna resultados da última varredura Touchlink |
touchlink_identify | Faz um dispositivo Touchlink piscar para identificação |
touchlink_reset | Restaura um dispositivo Touchlink para os padrões de fábrica |
Recursos
Recursos são instantâneos somente leitura e armazenáveis em cache que os clientes MCP podem buscar sem emitir chamadas de ferramentas.
| URI | Descrição |
|---|---|
deconz://config | JSON de configuração do gateway |
deconz://lights | Todas as luzes com JSON de estado |
deconz://groups | Todos os grupos com JSON de estado de ação |
deconz://sensors | Todos os sensores com JSON de estado |
deconz://rules | Todas as regras de automação em JSON |
deconz://schedules | Todos os agendamentos em JSON |
deconz://state | Estado completo do gateway (todos os recursos combinados) |
Prompts
Prompts são iniciadores de conversa pré-construídos que guiam a IA por fluxos de trabalho comuns.
| Prompt | Argumentos | Descrição |
|---|---|---|
home_overview | — | Relatório de status completo: todas as luzes, sensores, acessibilidade, anomalias |
control_lights | room (opcional) | Liga/desliga luzes, define brilho ou cor |
manage_scenes | group_id (opcional) | Cria, recupera, atualiza ou exclui cenas |
add_device | — | Guia passo a passo para parear um novo dispositivo Zigbee |
setup_automation | — | Cria uma regra acionada por um evento de sensor |
diagnose_device | device_name (opcional) | Diagnostica dispositivos inacessíveis ou com mau funcionamento |
evening_routine | bedtime (padrão 23:00) | Ativa uma cena noturna e agenda o desligamento das luzes |
Configuração do Claude Desktop
Adicione a ~/Library/Application Support/Claude/claude_desktop_config.json (macOS):
{
"mcpServers": {
"deconz": {
"command": "deconz-mcp",
"env": {
"DECONZ_HOST": "192.168.1.10",
"DECONZ_API_KEY": "your-api-key-here"
}
}
}
}
Ou se instalado em um ambiente virtual:
{
"mcpServers": {
"deconz": {
"command": "/path/to/deconz-mcp/.venv/bin/deconz-mcp",
"env": {
"DECONZ_HOST": "192.168.1.10",
"DECONZ_API_KEY": "your-api-key-here"
}
}
}
}
Configuração do cliente HTTP
Para transporte Streamable HTTP:
{
"mcpServers": {
"deconz": {
"url": "http://localhost:8080/mcp",
"headers": {
"Authorization": "Bearer my-mcp-secret"
}
}
}
}
Para transporte SSE legado:
{
"mcpServers": {
"deconz": {
"url": "http://localhost:8080/sse",
"headers": {
"Authorization": "Bearer my-mcp-secret"
}
}
}
}
Docker
Uma imagem multi-plataforma (linux/amd64 + linux/arm64) é publicada no GitHub Container Registry pelo fluxo de release sempre que uma tag de versão é enviada:
ghcr.io/marcinn2/deconz-mcp:latest
ghcr.io/marcinn2/deconz-mcp:0.2
ghcr.io/marcinn2/deconz-mcp:0.2.1
Um Dockerfile multi-estágio também é incluído se você preferir compilar localmente. O estágio de build usa a imagem oficial uv para instalar dependências e compilar o pacote como uma wheel; o estágio de runtime é python:3.14-slim e executa como o usuário não privilegiado app (uid 1000).
Pull
docker pull ghcr.io/marcinn2/deconz-mcp:latest
Compilar localmente
# Single-platform (current machine)
docker build -t deconz-mcp:latest .
# Multi-platform push (requires a buildx builder with multi-platform support).
# Releases do this automatically; this is for pushing to another registry by hand.
docker buildx build \
--platform linux/amd64,linux/arm64 \
--tag registry.mne.pl/deconz-mcp:latest \
--tag registry.mne.pl/deconz-mcp:0.2.1 \
--push .
Executar — servidor HTTP (SSE + Streamable HTTP)
docker run -p 8000:8000 \
-e DECONZ_HOST=192.168.1.10 \
-e DECONZ_API_KEY=abc123def \
-e MCP_AUTH_TOKEN=my-mcp-secret \
ghcr.io/marcinn2/deconz-mcp:latest
Executar — stdio
docker run -i \
-e DECONZ_HOST=192.168.1.10 \
-e DECONZ_API_KEY=abc123def \
ghcr.io/marcinn2/deconz-mcp:latest --transport stdio
Docker Compose
Um arquivo Compose pronto para uso está em docs/docker-compose.yml. Ele define dois serviços:
| Serviço | Transporte | Iniciado por padrão |
|---|---|---|
deconz-mcp | server (SSE + Streamable HTTP) na porta 8000 | Sim |
deconz-mcp-stdio | stdio | Não — requer --profile stdio |
# Copy and edit the environment file
cp .env.example .env # set DECONZ_HOST, DECONZ_API_KEY, MCP_AUTH_TOKEN
# Start the HTTP server (--env-file is required: the compose file lives in docs/,
# so a repository-root .env is not picked up automatically)
docker compose --env-file .env -f docs/docker-compose.yml up
# Run a one-shot stdio session
docker compose --env-file .env -f docs/docker-compose.yml --profile stdio run --rm deconz-mcp-stdio
Use o serviço stdio no Claude Desktop:
{
"mcpServers": {
"deconz": {
"command": "docker",
"args": ["compose", "-f", "/path/to/docs/docker-compose.yml",
"--profile", "stdio", "run", "--rm", "deconz-mcp-stdio"],
"env": {
"DECONZ_HOST": "192.168.1.10",
"DECONZ_API_KEY": "your-api-key-here"
}
}
}
}
Kubernetes
O manifesto em docs/k8s-deployment.yaml contém todos os recursos necessários para executar o servidor em um cluster:
| Recurso | Propósito |
|---|---|
Namespace | deconz-mcp — isola todos os recursos |
Secret | DECONZ_API_KEY e MCP_AUTH_TOKEN (codificados em base64) |
ConfigMap | DECONZ_HOST, DECONZ_PORT, DECONZ_TLS, MCP_BASE_URL |
Deployment | 1 réplica, não-root, sistema de arquivos raiz somente leitura, limites de recursos |
Service | ClusterIP na porta 80 → pod 8000 |
Ingress | Modelo comentado para nginx / cert-manager |
Implantar
# 1. Encode your secrets
echo -n 'your-api-key' | base64 # → paste into Secret.DECONZ_API_KEY
echo -n 'your-mcp-token' | base64 # → paste into Secret.MCP_AUTH_TOKEN
# 2. Edit the ConfigMap (DECONZ_HOST, MCP_BASE_URL) in docs/k8s-deployment.yaml
# 3. Apply
kubectl apply -f docs/k8s-deployment.yaml
# 4. Verify
kubectl -n deconz-mcp get pods
kubectl -n deconz-mcp logs -f deploy/deconz-mcp
Verificação de saúde
kubectl -n deconz-mcp port-forward svc/deconz-mcp 8000:80
curl http://localhost:8000/health
# {"status": "ok", "deconz_configured": true}
O Deployment configura tanto uma sonda de vivacidade quanto uma sonda de prontidão contra /health, de modo que o Kubernetes reinicia automaticamente o pod se o servidor ficar sem resposta.
Ingress (opcional)
Descomente a seção Ingress na parte inferior de docs/k8s-deployment.yaml e defina seu hostname. Não adicione uma anotação rewrite-target: os endpoints vivem em /mcp, /sse e /messages/ e devem alcançar o pod com seus caminhos intactos. A terminação TLS ocorre no controlador de ingress; o pod sempre fala HTTP simples internamente.
Verificação de saúde
Os transportes HTTP expõem uma sonda de vivacidade:
curl http://localhost:8080/health
# {"status": "ok", "deconz_configured": true}
Estrutura do projeto
deConz-mcp/
├── Dockerfile # Multi-stage image build (runs as uid 1000)
├── pyproject.toml # Package metadata and dependencies
├── uv.lock # Locked dependency versions (committed)
├── .env.example # Template for docker compose
├── README.md
├── docs/
│ ├── docker-compose.yml # Compose services (HTTP + stdio)
│ └── k8s-deployment.yaml # Kubernetes: Namespace, Secret, ConfigMap,
│ # Deployment, Service, Ingress (template)
├── tests/
│ └── test_smoke.py # Client, credential-handling and MCP surface tests
└── src/
└── deconz_mcp/
├── __init__.py
├── __main__.py # CLI entrypoint and transport wiring
├── client.py # Async deCONZ REST API HTTP client
└── server.py # FastMCP server: tools, resources, prompts
Visão geral da API do deCONZ
O servidor cobre estas categorias de API:
| Categoria | Endpoints |
|---|---|
| Config | GET /config, PUT /config (permitir join) |
| Luzes | GET /lights, GET /lights/<id>, PUT /lights/<id>/state, DELETE /lights/<id> |
| Grupos | GET /groups, POST /groups, PUT /groups/<id>/action, DELETE /groups/<id> |
| Cenas | CRUD completo em /groups/<id>/scenes/<sid>, incl. recall e store |
| Sensores | GET /sensors, PUT /sensors/<id>/config, DELETE /sensors/<id> |
| Regras | CRUD completo em /rules/<id> |
| Agendamentos | CRUD completo em /schedules/<id> |
| Touchlink | POST /touchlink/scan, identify, reset |
Para a referência completa da API, consulte a documentação da API REST deCONZ.
Dados e Privacidade
Avaliação preliminar apenas — não é aconselhamento jurídico. Consulte as notas completas abaixo.
Uso doméstico pessoal
Quando este servidor é executado em uma residência privada e é acessado apenas pelos moradores, o processamento de dados de dispositivos de casa inteligente provavelmente é coberto pela isenção doméstica (Recital 18 do GDPR). Nesse cenário, o GDPR não se aplica e nenhuma etapa adicional de conformidade é necessária.
Implantações comerciais ou compartilhadas
Implantar este servidor em escritórios, imóveis para aluguel, hotéis, espaços de coworking ou qualquer ambiente onde você processa dados em nome de outras pessoas o coloca fora da isenção doméstica. Nesses casos:
- Dados de sensores de presença e movimento constituem dados comportamentais pessoais (Art. 4(1) do GDPR). Estabeleça uma base legal documentada (Art. 6) antes de processá-los.
- Realize uma Avaliação de Impacto na Proteção de Dados (Art. 35) se a implantação envolver monitoramento sistemático de ocupantes em grande escala.
- Forneça um aviso de privacidade aos titulares dos dados descrevendo o que é coletado, por quanto tempo e sob qual base legal.
Recomendações de segurança
| Risco | Recomendação |
|---|---|
| A chave da API viaja nos caminhos de URL, então os logs de acesso do gateway a registram | Rotacione a chave da API deCONZ periodicamente; restrinja o acesso aos logs do gateway. Este servidor mantém a chave fora de seus próprios logs e fora dos erros que retorna aos clientes |
| Transporte não criptografado | Habilite TLS para qualquer implantação voltada à rede (DECONZ_TLS=true); use um proxy reverso com um certificado válido. Defina DECONZ_TLS_VERIFY=false apenas para um certificado de gateway autoassinado em uma rede confiável |
| Endpoint MCP acessível publicamente | Sempre defina MCP_AUTH_TOKEN ao vincular a um endereço não loopback |
O que este software NÃO faz
- Nenhum dado é enviado a terceiros, serviços de análise ou provedores de nuvem.
- Nenhuma telemetria, pixels de rastreamento ou bibliotecas de consentimento estão presentes neste código.
- Toda a comunicação permanece entre o cliente MCP, este servidor e o gateway deCONZ local.
Aviso legal
Esta avaliação de GDPR foi gerada como uma avaliação preliminar e exploratória. Ela não constitui aconselhamento jurídico e não substitui uma auditoria legal. Para orientação vinculativa, consulte um advogado qualificado em proteção de dados na sua jurisdição.
Lançamentos
Os lançamentos são feitos ao enviar uma tag de versão. .github/workflows/release.yml então:
- Verifica se a tag corresponde ao
versionempyproject.tomle falha cedo se não corresponder. - Executa o fluxo de trabalho completo de CI (lint, formatação, verificação de tipos, testes em Python 3.10–3.12).
- Constrói a imagem para linux/amd64 e linux/arm64, com um SBOM e proveniência de build, e a envia para
ghcr.io/marcinn2/deconz-mcp. - Cria o release do GitHub com notas geradas, o digest da imagem e a wheel e o sdist construídos anexados.
# bump version = "0.3.0" in pyproject.toml first, then:
git tag -a v0.3.0 -m "v0.3.0"
git push origin v0.3.0
Uma tag contendo um hífen, como v0.3.0-rc.1, é publicada como pré-lançamento e não move a tag de imagem latest.
Tags de imagem produzidas para v0.3.0: 0.3.0, 0.3 e latest.
Nenhum segredo precisa ser configurado: o fluxo de trabalho autentica no GHCR com o GITHUB_TOKEN integrado. Após o primeiro lançamento, defina a visibilidade do pacote em Packages → deconz-mcp → Package settings se a imagem deve ser puxável anonimamente.
Licença
Apache 2.0 — consulte LICENSE.
Aviso legal
Este software não é afiliado ou endossado pela Dresden Elektronik. Use por sua conta e risco. Ele não vem com nenhuma garantia de qualquer tipo. Não há responsabilidade para o desenvolvedor. Este software é um projeto pessoal que mantenho no meu tempo livre. Consulte a licença para mais informações.