trackmcp
Back to directory
marcinn2

deConz-mcp

View on GitHub

MCP Server for deConz server developed by Dresden Elektronik (bridge between smart home automation platforms and wireless Zigbee networks)

0 stars PythonOthers Updated Sep 3, 2026
deconzmcp-serverzigbee

Documentation

deConz MCP Server

An MCP (Model Context Protocol) server that exposes the deCONZ REST API to AI assistants. Control Zigbee lights, sensors, groups, scenes, rules, and schedules through natural language.

Supports stdio, SSE, and Streamable HTTP transports. HTTP transports are protected by a configurable bearer token.


Requirements

  • Python ≥ 3.10
  • uv (recommended) or pip
  • A running deCONZ / Phoscon gateway with a ConBee or RaspBee adapter
  • A valid deCONZ REST API key (see Obtaining an API key)

Installation

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

Obtaining an API key

1. Open the Phoscon App in your browser (usually `http:///pwa`).

2. Go to Menu → Settings → Gateway → Advanced.

3. Click Authenticate app — this opens the network for 60 seconds.

4. Within those 60 seconds, run:

bash
curl -s -X POST http:///api \
  -H "Content-Type: application/json" \
  -d '{"devicetype": "deconz-mcp"}'

The response contains your API key:

json
[{"success": {"username": "YOUR-API-KEY-HERE"}}]

Store it as `DECONZ_API_KEY`.


Quick start

stdio (Claude Desktop)

bash
DECONZ_HOST=192.168.1.10 DECONZ_API_KEY=abc123def deconz-mcp

Streamable HTTP with bearer auth

bash
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

Combined SSE + Streamable HTTP

bash
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

Environment variables

VariableRequiredDefaultDescription
`DECONZ_HOST`Yes*IP or hostname of the deCONZ gateway
`DECONZ_PORT`No`80`HTTP port of the deCONZ gateway
`DECONZ_API_KEY`Yes*deCONZ REST API key
`DECONZ_TLS`No`false`Set `true` to use HTTPS
`DECONZ_TLS_VERIFY`No`true``false` accepts a self-signed gateway certificate; any other value is a path to a CA bundle
`DECONZ_ALLOW_RUNTIME_CONFIG`Nosee‡Set `true` to expose `configure_deconz` even when the gateway comes from the environment
`MCP_AUTH_TOKEN`No†Bearer token clients must send to this MCP server
`MCP_BASE_URL`No`http://:`Public base URL (used as OAuth issuer URL)

\* Not required when using stdio and calling `configure_deconz` at runtime.

† Strongly recommended for HTTP transports exposed beyond localhost.

‡ Defaults to enabled only when `DECONZ_HOST` / `DECONZ_API_KEY` are absent. Once the gateway

is configured from the environment, the tool is withheld so that a client cannot repoint this

server at another host.


CLI reference

code
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]
FlagDefaultDescription
`--transport``stdio`Transport mode
`--host``127.0.0.1`Bind address (HTTP transports)
`--port``8000`Listen port (HTTP transports)
`--log-level``INFO`Logging verbosity
`--auth-token``$MCP_AUTH_TOKEN`MCP bearer token
`--base-url``$MCP_BASE_URL`OAuth issuer URL

Transport modes

ModeEndpoint(s)Description
`stdio`stdin/stdoutPipe-based — for Claude Desktop and local use
`sse``/sse`, `/messages/`Legacy SSE (MCP pre-2025-03-26)
`streamable-http``/mcp`Modern Streamable HTTP (MCP 2025-03-26)
`server`all of the aboveSSE + Streamable HTTP on one port

Authentication

deCONZ API key

The deCONZ REST API key is a gateway credential that travels as part of the URL path (`/api//...`). It is configured server-side via `DECONZ_API_KEY` and is never exposed to MCP clients: request URLs are kept out of tool errors, and the HTTP client's request logging is silenced because it would otherwise write the key to stderr on every call.

Resource IDs supplied by a client (light, group, scene, sensor, rule, schedule, and Touchlink IDs) are validated before they are placed in a request path, so a crafted ID cannot escape its resource and reach, for example, the gateway's configuration or its list of API keys.

MCP bearer token

The `MCP_AUTH_TOKEN` / `--auth-token` option protects the MCP server itself. Every HTTP request from an MCP client must include:

code
Authorization: Bearer

The token is verified with a constant-time comparison to prevent timing attacks. When running over localhost only (default bind `127.0.0.1`), bearer auth is optional but recommended.


Tools

Connection / configuration

ToolDescription
`configure_deconz`Point the server at a deCONZ gateway at runtime (host, port, API key). Registered only when the gateway is not configured from the environment, or when `DECONZ_ALLOW_RUNTIME_CONFIG=true`
`get_gateway_config`Read gateway name, firmware, Zigbee channel, IP, WebSocket port
`set_permit_join`Open the Zigbee network for new device pairing (0–255 seconds)

Lights

ToolDescription
`list_lights`List all lights with on/off, brightness, and reachability
`get_light`Full JSON details for a single light
`set_light_state`Control power, brightness, hue, saturation, colour temp, xy, effect, alert
`rename_light`Rename a light
`delete_light`Remove a light from the gateway

Groups

ToolDescription
`list_groups`List all groups with member count and action state
`get_group`Full JSON details for a single group
`create_group`Create a new group (optionally pre-populate with lights)
`set_group_action`Control all lights in a group simultaneously
`modify_group`Rename a group or change its member lights
`delete_group`Delete a group (lights remain)

Scenes

ToolDescription
`list_scenes`List all scenes for a group
`get_scene`Full JSON details for a scene
`create_scene`Create a scene (captures current group state)
`recall_scene`Activate a scene
`store_scene`Overwrite a scene with the current group state
`rename_scene`Rename a scene
`delete_scene`Delete a scene

Sensors

ToolDescription
`list_sensors`List all sensors with latest readings and battery levels
`get_sensor`Full JSON details for a single sensor
`rename_sensor`Rename a sensor
`set_sensor_config`Update sensor config (enabled, battery level, sensitivity)
`delete_sensor`Remove a sensor from the gateway

Rules (automations)

ToolDescription
`list_rules`List all automation rules with status and trigger counts
`get_rule`Full JSON details (conditions + actions) for a rule
`create_rule`Create a new rule with conditions and actions
`set_rule_status`Enable or disable a rule
`delete_rule`Delete a rule

Schedules

ToolDescription
`list_schedules`List all timed schedules
`get_schedule`Full JSON details for a schedule
`create_schedule`Create a new schedule with ISO 8601 time expression
`set_schedule_status`Enable or disable a schedule
`delete_schedule`Delete a schedule
ToolDescription
`touchlink_scan`Start a Touchlink scan (~10 s) to find nearby Zigbee devices
`get_touchlink_results`Return results from the last Touchlink scan
`touchlink_identify`Make a Touchlink device blink for identification
`touchlink_reset`Factory-reset a Touchlink device

Resources

Resources are read-only, cacheable snapshots that MCP clients can fetch without issuing tool calls.

URIDescription
`deconz://config`Gateway configuration JSON
`deconz://lights`All lights with state JSON
`deconz://groups`All groups with action state JSON
`deconz://sensors`All sensors with state JSON
`deconz://rules`All automation rules JSON
`deconz://schedules`All schedules JSON
`deconz://state`Complete gateway state (all resources combined)

Prompts

Prompts are pre-built conversation starters that guide the AI through common workflows.

PromptArgumentsDescription
`home_overview`Full status report: all lights, sensors, reachability, anomalies
`control_lights``room` (optional)Turn lights on/off, set brightness or colour
`manage_scenes``group_id` (optional)Create, recall, update, or delete scenes
`add_device`Step-by-step guide to pair a new Zigbee device
`setup_automation`Create a rule triggered by a sensor event
`diagnose_device``device_name` (optional)Diagnose unreachable or misbehaving devices
`evening_routine``bedtime` (default `23:00`)Activate an evening scene and schedule lights off

Claude Desktop configuration

Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS):

json
{
  "mcpServers": {
    "deconz": {
      "command": "deconz-mcp",
      "env": {
        "DECONZ_HOST": "192.168.1.10",
        "DECONZ_API_KEY": "your-api-key-here"
      }
    }
  }
}

Or if installed in a virtual environment:

json
{
  "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"
      }
    }
  }
}

HTTP client configuration

For Streamable HTTP transport:

json
{
  "mcpServers": {
    "deconz": {
      "url": "http://localhost:8080/mcp",
      "headers": {
        "Authorization": "Bearer my-mcp-secret"
      }
    }
  }
}

For legacy SSE transport:

json
{
  "mcpServers": {
    "deconz": {
      "url": "http://localhost:8080/sse",
      "headers": {
        "Authorization": "Bearer my-mcp-secret"
      }
    }
  }
}

Docker

A multi-platform image (linux/amd64 + linux/arm64) is published to GitHub Container Registry by the release workflow whenever a version tag is pushed:

code
ghcr.io/marcinn2/deconz-mcp:latest
ghcr.io/marcinn2/deconz-mcp:0.2
ghcr.io/marcinn2/deconz-mcp:0.2.1

A multi-stage `Dockerfile` is also included if you prefer to build locally. The builder stage uses the official `uv` image to install dependencies and compile the package as a wheel; the runtime stage is `python:3.14-slim` and runs as the unprivileged user `app` (uid 1000).

Pull

bash
docker pull ghcr.io/marcinn2/deconz-mcp:latest

Build locally

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

Run — HTTP server (SSE + Streamable HTTP)

bash
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

Run — stdio

bash
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

A ready-to-use Compose file is in `docs/docker-compose.yml`. It defines two services:

ServiceTransportStarted by default
`deconz-mcp``server` (SSE + Streamable HTTP) on port 8000Yes
`deconz-mcp-stdio``stdio`No — requires `--profile stdio`
bash
# 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 the stdio service in Claude Desktop:

json
{
  "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

The manifest at `docs/k8s-deployment.yaml` contains all resources needed to run the server in a cluster:

ResourcePurpose
`Namespace``deconz-mcp` — isolates all resources
`Secret``DECONZ_API_KEY` and `MCP_AUTH_TOKEN` (base64-encoded)
`ConfigMap``DECONZ_HOST`, `DECONZ_PORT`, `DECONZ_TLS`, `MCP_BASE_URL`
`Deployment`1 replica, non-root, read-only root FS, resource limits
`Service``ClusterIP` on port 80 → pod 8000
`Ingress`Commented-out template for nginx / cert-manager

Deploy

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

Health check

bash
kubectl -n deconz-mcp port-forward svc/deconz-mcp 8000:80
curl http://localhost:8000/health
# {"status": "ok", "deconz_configured": true}

The `Deployment` configures both a liveness probe and a readiness probe against `/health`, so Kubernetes automatically restarts the pod if the server becomes unresponsive.

Ingress (optional)

Uncomment the `Ingress` section at the bottom of `docs/k8s-deployment.yaml` and set your hostname. Do not add a `rewrite-target` annotation: the endpoints live at `/mcp`, `/sse` and `/messages/` and must reach the pod with their paths intact. TLS termination happens at the ingress controller; the pod always speaks plain HTTP internally.


Health check

HTTP transports expose a liveness probe:

bash
curl http://localhost:8080/health
# {"status": "ok", "deconz_configured": true}

Project structure

code
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

deCONZ API overview

The server covers these API categories:

CategoryEndpoints
Config`GET /config`, `PUT /config` (permit join)
Lights`GET /lights`, `GET /lights/`, `PUT /lights//state`, `DELETE /lights/`
Groups`GET /groups`, `POST /groups`, `PUT /groups//action`, `DELETE /groups/`
ScenesFull CRUD under `/groups//scenes/` incl. recall and store
Sensors`GET /sensors`, `PUT /sensors//config`, `DELETE /sensors/`
RulesFull CRUD under `/rules/`
SchedulesFull CRUD under `/schedules/`
Touchlink`POST /touchlink/scan`, identify, reset

For the full API reference, see the deCONZ REST API documentation.


Data & Privacy

> Preliminary assessment only — not legal advice. See full notes below.

Personal home use

When this server runs in a private household and is accessed only by the residents, processing of smart-home device data is likely covered by the household exemption (GDPR Recital 18). In that scenario the GDPR does not apply and no additional compliance steps are required.

Commercial or shared deployments

Deploying this server in offices, rental properties, hotels, co-working spaces, or any environment where you process data on behalf of other people takes you outside the household exemption. In those cases:

  • Presence and motion sensor data constitutes personal behavioral data (Art. 4(1) GDPR). Establish a documented lawful basis (Art. 6) before processing it.
  • Conduct a Data Protection Impact Assessment (Art. 35) if the deployment involves systematic monitoring of occupants on a large scale.
  • Provide a privacy notice to data subjects describing what is collected, for how long, and under what legal basis.

Security recommendations

RiskRecommendation
API key travels in URL paths, so the gateway's own access logs record itRotate the deCONZ API key periodically; restrict access to gateway logs. This server keeps the key out of its own logs and out of the errors it returns to clients
Unencrypted transportEnable TLS for any network-facing deployment (`DECONZ_TLS=true`); use a reverse proxy with a valid certificate. Set `DECONZ_TLS_VERIFY=false` only for a self-signed gateway certificate on a trusted network
MCP endpoint publicly accessibleAlways set `MCP_AUTH_TOKEN` when binding to a non-loopback address

What this software does NOT do

  • No data is sent to third parties, analytics services, or cloud providers.
  • No telemetry, tracking pixels, or consent libraries are present in this codebase.
  • All communication stays between the MCP client, this server, and the local deCONZ gateway.

This GDPR assessment was generated as a preliminary, exploratory evaluation. It does not constitute legal advice and does not replace a legal audit. For binding guidance, consult a qualified data protection lawyer in your jurisdiction.


Releasing

Releases are cut by pushing a version tag. `.github/workflows/release.yml` then:

1. Checks that the tag matches the `version` in `pyproject.toml` and fails early if it does not.

2. Runs the full CI workflow (lint, format, type-check, tests on Python 3.10–3.12).

3. Builds the image for linux/amd64 and linux/arm64, with an SBOM and build provenance, and pushes it to `ghcr.io/marcinn2/deconz-mcp`.

4. Creates the GitHub release with generated notes, the image digest, and the built wheel and sdist attached.

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

A tag containing a hyphen, such as `v0.3.0-rc.1`, is published as a pre-release and does not move the `latest` image tag.

Image tags produced for `v0.3.0`: `0.3.0`, `0.3`, and `latest`.

No secrets need to be configured: the workflow authenticates to GHCR with the built-in `GITHUB_TOKEN`. After the first release, set the package visibility under Packages → deconz-mcp → Package settings if the image should be pullable anonymously.


License

Apache 2.0 — see LICENSE.

Disclaimer

This software is not affiliated with or endorsed by Dresden Elektronik. Use at your own risk. It does not come with any warranty of any kind. There is no liability for the developer. This software is a personal project that I maintain in my free time.

Refer to the licence for more information.

Frequently asked questions

What is deConz-mcp?

deConz-mcp is MCP Server for deConz server developed by Dresden Elektronik (bridge between smart home automation platforms and wireless Zigbee networks)

How do I install deConz-mcp?

Open the GitHub repository and follow its README. Most MCP servers are added to your client's MCP config, then called by your agent.

Is deConz-mcp open source?

Yes — it is hosted on GitHub at https://github.com/marcinn2/deConz-mcp.

Related MCP tools

Run your own MCP server? See who uses it and what to fix.

Measure it with TrackMCP