deConz MCP
Servidor MCP para el servidor deConz desarrollado por Dresden Elektronik (puente entre plataformas de automatización del hogar inteligente y redes inalámbricas Zigbee)
Documentación
Servidor deConZ MCP
Un servidor MCP (Model Context Protocol) que expone la API REST de deCONZ a asistentes de IA. Controla luces Zigbee, sensores, grupos, escenas, reglas y horarios mediante lenguaje natural.
Soporta transportes stdio, SSE y HTTP Streamable. Los transportes HTTP están protegidos por un token de portador configurable.
Requisitos
- Python ≥ 3.10
- uv (recomendado) o pip
- Una pasarela deCONZ / Phoscon en funcionamiento con un adaptador ConBee o RaspBee
- Una clave de API REST de deCONZ válida (consulta Obtención de una clave de API)
Instalación
# 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 .
Obtención de una clave de API
- Abre la aplicación Phoscon en tu navegador (normalmente
http://<gateway-ip>/pwa). - Ve a Menú → Configuración → Pasarela → Avanzado.
- Haz clic en Autenticar aplicación — esto abre la red durante 60 segundos.
- Dentro de esos 60 segundos, ejecuta:
curl -s -X POST http://<gateway-ip>/api \
-H "Content-Type: application/json" \
-d '{"devicetype": "deconz-mcp"}'
La respuesta contiene tu clave de API:
[{"success": {"username": "YOUR-API-KEY-HERE"}}]
Guárdala como DECONZ_API_KEY.
Inicio rápido
stdio (Claude Desktop)
DECONZ_HOST=192.168.1.10 DECONZ_API_KEY=abc123def deconz-mcp
HTTP Streamable con autenticación de portador
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 + HTTP Streamable 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
Variables de entorno
| Variable | Obligatoria | Valor predeterminado | Descripción |
|---|---|---|---|
DECONZ_HOST | Sí* | — | IP o nombre de host de la pasarela deCONZ |
DECONZ_PORT | No | 80 | Puerto HTTP de la pasarela deCONZ |
DECONZ_API_KEY | Sí* | — | Clave de API REST de deCONZ |
DECONZ_TLS | No | false | Establece true para usar HTTPS |
DECONZ_TLS_VERIFY | No | true | false acepta un certificado de pasarela autofirmado; cualquier otro valor es una ruta a un paquete de CA |
DECONZ_ALLOW_RUNTIME_CONFIG | No | ver‡ | Establece true para exponer configure_deconz incluso cuando la pasarela proviene del entorno |
MCP_AUTH_TOKEN | No† | — | Token de portador que los clientes deben enviar a este servidor MCP |
MCP_BASE_URL | No | http://<host>:<port> | URL base pública (usada como URL del emisor OAuth) |
* No obligatoria al usar stdio y llamar a configure_deconz en tiempo de ejecución.
† Muy recomendada para transportes HTTP expuestos más allá de localhost.
‡ Predeterminada a habilitada solo cuando DECONZ_HOST / DECONZ_API_KEY están ausentes. Una vez que la pasarela
se configura desde el entorno, la herramienta se retira para que un cliente no pueda redirigir este
servidor a otro host.
Referencia de 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]
| Indicador | Valor predeterminado | Descripción |
|---|---|---|
--transport | stdio | Modo de transporte |
--host | 127.0.0.1 | Dirección de enlace (transportes HTTP) |
--port | 8000 | Puerto de escucha (transportes HTTP) |
--log-level | INFO | Verbosidad del registro |
--auth-token | $MCP_AUTH_TOKEN | Token de portador MCP |
--base-url | $MCP_BASE_URL | URL del emisor OAuth |
Modos de transporte
| Modo | Punto(s) final(es) | Descripción |
|---|---|---|
stdio | stdin/stdout | Basado en tuberías — para Claude Desktop y uso local |
sse | /sse, /messages/ | SSE heredado (MCP anterior a 2025-03-26) |
streamable-http | /mcp | HTTP Streamable moderno (MCP 2025-03-26) |
server | todos los anteriores | SSE + HTTP Streamable en un solo puerto |
Autenticación
Clave de API de deCONZ
La clave de API REST de deCONZ es una credencial de pasarela que viaja como parte de la ruta de URL (/api/<apikey>/...). Se configura en el lado del servidor mediante DECONZ_API_KEY y nunca se expone a los clientes MCP: las URL de solicitud se mantienen fuera de los errores de herramientas, y el registro de solicitudes del cliente HTTP se silencia porque de lo contrario escribiría la clave en stderr en cada llamada.
Los ID de recursos proporcionados por un cliente (ID de luces, grupos, escenas, sensores, reglas, horarios y Touchlink) se validan antes de colocarse en una ruta de solicitud, por lo que un ID manipulado no puede escapar de su recurso y alcanzar, por ejemplo, la configuración de la pasarela o su lista de claves de API.
Token de portador MCP
La opción MCP_AUTH_TOKEN / --auth-token protege el propio servidor MCP. Cada solicitud HTTP de un cliente MCP debe incluir:
Authorization: Bearer <token>
El token se verifica con una comparación de tiempo constante para prevenir ataques de temporización. Cuando se ejecuta solo sobre localhost (enlace predeterminado 127.0.0.1), la autenticación de portador es opcional pero recomendada.
Herramientas
Conexión / configuración
| Herramienta | Descripción |
|---|---|
configure_deconz | Apunta el servidor a una pasarela deCONZ en tiempo de ejecución (host, puerto, clave de API). Se registra solo cuando la pasarela no está configurada desde el entorno, o cuando DECONZ_ALLOW_RUNTIME_CONFIG=true |
get_gateway_config | Lee nombre de la pasarela, firmware, canal Zigbee, IP, puerto WebSocket |
set_permit_join | Abre la red Zigbee para emparejar nuevos dispositivos (0–255 segundos) |
Luces
| Herramienta | Descripción |
|---|---|
list_lights | Lista todas las luces con estado de encendido/apagado, brillo y alcanzabilidad |
get_light | Detalles JSON completos de una sola luz |
set_light_state | Controla encendido, brillo, tono, saturación, temperatura de color, xy, efecto, alerta |
rename_light | Renombra una luz |
delete_light | Elimina una luz de la pasarela |
Grupos
| Herramienta | Descripción |
|---|---|
list_groups | Lista todos los grupos con número de miembros y estado de acción |
get_group | Detalles JSON completos de un solo grupo |
create_group | Crea un nuevo grupo (opcionalmente precargado con luces) |
set_group_action | Controla todas las luces de un grupo simultáneamente |
modify_group | Renombra un grupo o cambia sus luces miembro |
delete_group | Elimina un grupo (las luces permanecen) |
Escenas
| Herramienta | Descripción |
|---|---|
list_scenes | Lista todas las escenas de un grupo |
get_scene | Detalles JSON completos de una escena |
create_scene | Crea una escena (captura el estado actual del grupo) |
recall_scene | Activa una escena |
store_scene | Sobrescribe una escena con el estado actual del grupo |
rename_scene | Renombra una escena |
delete_scene | Elimina una escena |
Sensores
| Herramienta | Descripción |
|---|---|
list_sensors | Lista todos los sensores con lecturas más recientes y niveles de batería |
get_sensor | Detalles JSON completos de un solo sensor |
rename_sensor | Renombra un sensor |
set_sensor_config | Actualiza la configuración del sensor (habilitado, nivel de batería, sensibilidad) |
delete_sensor | Elimina un sensor de la pasarela |
Reglas (automatizaciones)
| Herramienta | Descripción |
|---|---|
list_rules | Lista todas las reglas de automatización con estado y contadores de disparo |
get_rule | Detalles JSON completos (condiciones + acciones) de una regla |
create_rule | Crea una nueva regla con condiciones y acciones |
set_rule_status | Habilita o deshabilita una regla |
delete_rule | Elimina una regla |
Horarios
| Herramienta | Descripción |
|---|---|
list_schedules | Lista todos los horarios programados |
get_schedule | Detalles JSON completos de un horario |
create_schedule | Crea un nuevo horario con expresión de tiempo ISO 8601 |
set_schedule_status | Habilita o deshabilita un horario |
delete_schedule | Elimina un horario |
Touchlink
| Herramienta | Descripción |
|---|---|
touchlink_scan | Inicia un escaneo Touchlink (~10 s) para encontrar dispositivos Zigbee cercanos |
get_touchlink_results | Devuelve resultados del último escaneo Touchlink |
touchlink_identify | Hace parpadear un dispositivo Touchlink para identificación |
touchlink_reset | Restablece de fábrica un dispositivo Touchlink |
Recursos
Los recursos son instantáneas de solo lectura y almacenables en caché que los clientes MCP pueden obtener sin emitir llamadas a herramientas.
| URI | Descripción |
|---|---|
deconz://config | Configuración de la pasarela JSON |
deconz://lights | Todas las luces con estado JSON |
deconz://groups | Todos los grupos con estado de acción JSON |
deconz://sensors | Todos los sensores con estado JSON |
deconz://rules | Todas las reglas de automatización JSON |
deconz://schedules | Todos los horarios JSON |
deconz://state | Estado completo de la pasarela (todos los recursos combinados) |
Indicaciones
Las indicaciones son iniciadores de conversación preconstruidos que guían a la IA a través de flujos de trabajo comunes.
| Indicación | Argumentos | Descripción |
|---|---|---|
home_overview | — | Informe de estado completo: todas las luces, sensores, alcanzabilidad, anomalías |
control_lights | room (opcional) | Enciende/apaga luces, establece brillo o color |
manage_scenes | group_id (opcional) | Crea, recupera, actualiza o elimina escenas |
add_device | — | Guía paso a paso para emparejar un nuevo dispositivo Zigbee |
setup_automation | — | Crea una regla activada por un evento de sensor |
diagnose_device | device_name (opcional) | Diagnostica dispositivos inalcanzables o con mal funcionamiento |
evening_routine | bedtime (predeterminado 23:00) | Activa una escena nocturna y programa el apagado de luces |
Configuración de Claude Desktop
Añade 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"
}
}
}
}
O si está instalado en un entorno 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"
}
}
}
}
Configuración del cliente HTTP
Para transporte HTTP Streamable:
{
"mcpServers": {
"deconz": {
"url": "http://localhost:8080/mcp",
"headers": {
"Authorization": "Bearer my-mcp-secret"
}
}
}
}
Para transporte SSE heredado:
{
"mcpServers": {
"deconz": {
"url": "http://localhost:8080/sse",
"headers": {
"Authorization": "Bearer my-mcp-secret"
}
}
}
}
Docker
Una imagen multiplataforma (linux/amd64 + linux/arm64) se publica en GitHub Container Registry mediante el flujo de trabajo de lanzamiento cada vez que se envía una etiqueta de versión:
ghcr.io/marcinn2/deconz-mcp:latest
ghcr.io/marcinn2/deconz-mcp:0.2
ghcr.io/marcinn2/deconz-mcp:0.2.1
También se incluye un Dockerfile de múltiples etapas si prefieres compilar localmente. La etapa de compilación usa la imagen oficial uv para instalar dependencias y compilar el paquete como una rueda; la etapa de ejecución es python:3.14-slim y se ejecuta como el usuario sin privilegios app (uid 1000).
Extraer
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 .
Ejecutar — servidor HTTP (SSE + HTTP Streamable)
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
Ejecutar — 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
Un archivo Compose listo para usar está en docs/docker-compose.yml. Define dos servicios:
| Servicio | Transporte | Iniciado por defecto |
|---|---|---|
deconz-mcp | server (SSE + HTTP Streamable) en el puerto 8000 | Sí |
deconz-mcp-stdio | stdio | No — requiere --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
Usa el servicio stdio en 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
El manifiesto en docs/k8s-deployment.yaml contiene todos los recursos necesarios para ejecutar el servidor en un clúster:
| Recurso | Propósito |
|---|---|
Namespace | deconz-mcp — aísla todos los recursos |
Secret | DECONZ_API_KEY y MCP_AUTH_TOKEN (codificados en base64) |
ConfigMap | DECONZ_HOST, DECONZ_PORT, DECONZ_TLS, MCP_BASE_URL |
Deployment | 1 réplica, no root, sistema de archivos raíz de solo lectura, límites de recursos |
Service | ClusterIP en el puerto 80 → pod 8000 |
Ingress | Plantilla comentada para nginx / cert-manager |
Desplegar
# 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
Verificación de salud
kubectl -n deconz-mcp port-forward svc/deconz-mcp 8000:80
curl http://localhost:8000/health
# {"status": "ok", "deconz_configured": true}
El Deployment configura tanto una sonda de actividad como una sonda de preparación contra /health, por lo que Kubernetes reinicia automáticamente el pod si el servidor deja de responder.
Ingress (opcional)
Descomenta la sección Ingress al final de docs/k8s-deployment.yaml y establece tu nombre de host. No añadas una anotación rewrite-target: los puntos finales viven en /mcp, /sse y /messages/ y deben llegar al pod con sus rutas intactas. La terminación TLS ocurre en el controlador de ingress; el pod siempre habla HTTP plano internamente.
Verificación de salud
Los transportes HTTP exponen una sonda de actividad:
curl http://localhost:8080/health
# {"status": "ok", "deconz_configured": true}
Estructura del proyecto
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
Resumen de la API de deCONZ
El servidor cubre estas categorías de API:
| Categoría | Endpoints |
|---|---|
| Config | GET /config, PUT /config (permitir unión) |
| Luces | GET /lights, GET /lights/<id>, PUT /lights/<id>/state, DELETE /lights/<id> |
| Grupos | GET /groups, POST /groups, PUT /groups/<id>/action, DELETE /groups/<id> |
| Escenas | CRUD completo bajo /groups/<id>/scenes/<sid> incl. recuperación y almacenamiento |
| Sensores | GET /sensors, PUT /sensors/<id>/config, DELETE /sensors/<id> |
| Reglas | CRUD completo bajo /rules/<id> |
| Horarios | CRUD completo bajo /schedules/<id> |
| Touchlink | POST /touchlink/scan, identificar, restablecer |
Para la referencia completa de la API, consulte la documentación de la API REST de deCONZ.
Datos y Privacidad
Evaluación preliminar únicamente — no es asesoramiento legal. Consulte las notas completas a continuación.
Uso personal en el hogar
Cuando este servidor se ejecuta en un hogar privado y solo es accedido por los residentes, el procesamiento de datos de dispositivos domésticos inteligentes probablemente esté cubierto por la exención de hogar (Recital 18 del RGPD). En ese escenario, el RGPD no se aplica y no se requieren pasos de cumplimiento adicionales.
Implementaciones comerciales o compartidas
Implementar este servidor en oficinas, propiedades de alquiler, hoteles, espacios de coworking o cualquier entorno donde procese datos en nombre de otras personas lo saca de la exención de hogar. En esos casos:
- Los datos de sensores de presencia y movimiento constituyen datos de comportamiento personal (Art. 4(1) del RGPD). Establezca una base legal documentada (Art. 6) antes de procesarlos.
- Realice una Evaluación de Impacto de Protección de Datos (Art. 35) si la implementación implica el monitoreo sistemático de ocupantes a gran escala.
- Proporcione un aviso de privacidad a los interesados que describa qué se recopila, durante cuánto tiempo y bajo qué base legal.
Recomendaciones de seguridad
| Riesgo | Recomendación |
|---|---|
| La clave de API viaja en las rutas de URL, por lo que los registros de acceso de la puerta de enlace la registran | Rote la clave de API de deCONZ periódicamente; restrinja el acceso a los registros de la puerta de enlace. Este servidor mantiene la clave fuera de sus propios registros y fuera de los errores que devuelve a los clientes |
| Transporte no cifrado | Habilite TLS para cualquier implementación orientada a la red (DECONZ_TLS=true); use un proxy inverso con un certificado válido. Configure DECONZ_TLS_VERIFY=false solo para un certificado de puerta de enlace autofirmado en una red de confianza |
| Endpoint MCP accesible públicamente | Siempre configure MCP_AUTH_TOKEN al vincular a una dirección que no sea de bucle local |
Lo que este software NO hace
- No se envían datos a terceros, servicios de análisis o proveedores de nube.
- No hay telemetría, píxeles de seguimiento ni bibliotecas de consentimiento en este código.
- Toda la comunicación permanece entre el cliente MCP, este servidor y la puerta de enlace deCONZ local.
Aviso legal
Esta evaluación del RGPD se generó como una evaluación preliminar y exploratoria. No constituye asesoramiento legal y no reemplaza una auditoría legal. Para obtener orientación vinculante, consulte a un abogado de protección de datos calificado en su jurisdicción.
Publicación de versiones
Las versiones se publican empujando una etiqueta de versión. .github/workflows/release.yml entonces:
- Verifica que la etiqueta coincida con
versionenpyproject.tomly falla temprano si no coincide. - Ejecuta el flujo de trabajo completo de CI (lint, formato, verificación de tipos, pruebas en Python 3.10–3.12).
- Construye la imagen para linux/amd64 y linux/arm64, con un SBOM y procedencia de compilación, y la empuja a
ghcr.io/marcinn2/deconz-mcp. - Crea la versión de GitHub con notas generadas, el digest de la imagen y la rueda y el sdist construidos adjuntos.
# 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
Una etiqueta que contiene un guion, como v0.3.0-rc.1, se publica como pre-lanzamiento y no mueve la etiqueta de imagen latest.
Etiquetas de imagen producidas para v0.3.0: 0.3.0, 0.3 y latest.
No es necesario configurar secretos: el flujo de trabajo se autentica en GHCR con el GITHUB_TOKEN integrado. Después del primer lanzamiento, configure la visibilidad del paquete en Packages → deconz-mcp → Package settings si la imagen debe poder extraerse de forma anónima.
Licencia
Apache 2.0 — consulte LICENSE.
Descargo de responsabilidad
Este software no está afiliado ni respaldado por Dresden Elektronik. Úselo bajo su propio riesgo. No viene con ninguna garantía de ningún tipo. No hay responsabilidad para el desarrollador. Este software es un proyecto personal que mantengo en mi tiempo libre. Consulte la licencia para obtener más información.