MCP server for ZenControl DALI-2 lighting control via the ZenControl Cloud API
Project description
zencontrol-cloud-mcp
MCP server for ZenControl DALI-2 lighting control via the ZenControl Cloud API.
Overview
zencontrol-cloud-mcp enables AI assistants — such as Claude, Cursor, and other MCP-compatible clients — to discover and control ZenControl DALI-2 lighting systems through natural language.
Built on the Model Context Protocol (MCP) with FastMCP, the server supports two transports:
- stdio — for local, single-user setups (Claude Desktop, Cursor, etc.)
- StreamableHTTP — for hosted / multi-user deployments
Features
| Tool | Description |
|---|---|
list_sites |
Discover accessible ZenControl sites |
get_site_details |
Explore site hierarchy (floors, zones, gateways, tenancies) |
list_groups |
List lighting groups by scope (site, floor, map, or gateway) |
list_devices |
List devices and their ECGs by scope |
control_light |
On/off, dim, set level (0–100 %), recall scenes, identify |
set_colour |
Colour temperature (Kelvin) or RGBWAF control |
Prerequisites
- Python 3.11+
- ZenControl Cloud account with API credentials (
client_idandclient_secret) — see How to use OAuth 2.0 authentication for zencontrol cloud APIs for instructions on obtaining credentials - uv package manager (recommended) or
pip
Quick Start
-
Set your credentials:
export ZENCONTROL_CLIENT_ID=your_client_id export ZENCONTROL_CLIENT_SECRET=your_client_secret
-
Run with
uvx:uvx zencontrol-cloud-mcpOn first launch a browser window will open so you can log in to ZenControl. After that, tokens are cached and refreshed automatically.
Configuration
Claude Desktop (stdio mode)
Add the following to your Claude Desktop configuration file:
{
"mcpServers": {
"zencontrol": {
"command": "uvx",
"args": ["zencontrol-cloud-mcp"],
"env": {
"ZENCONTROL_CLIENT_ID": "your_client_id",
"ZENCONTROL_CLIENT_SECRET": "your_client_secret"
}
}
}
}
HTTP mode (hosted)
Start the server on a network port:
uvx zencontrol-cloud-mcp --transport streamable-http --port 9000
Then point your MCP client at the HTTP endpoint:
{
"mcpServers": {
"zencontrol": {
"url": "http://localhost:9000/mcp"
}
}
}
Environment Variables
| Variable | Required | Default | Description |
|---|---|---|---|
ZENCONTROL_CLIENT_ID |
Yes (stdio) | — | OAuth client ID |
ZENCONTROL_CLIENT_SECRET |
Yes (stdio) | — | OAuth client secret |
ZENCONTROL_REDIRECT_URI |
No | http://localhost:9000/callback |
OAuth redirect URI |
ZENCONTROL_PORT |
No | 9000 |
HTTP server port |
ZENCONTROL_PUBLIC_URL |
No | — | Public HTTPS URL for HTTP mode (e.g. https://mcp.example.com) |
ZENCONTROL_SCOPE_SITE |
No | — | Lock operations to a site (UUID, tag, or name) |
Authentication
The server uses OAuth 2.0 Authorization Code flow to authenticate with the ZenControl Cloud API.
- On first run the server opens your default browser so you can log in.
- Tokens are stored encrypted in a platform-appropriate location (via
platformdirs). - Tokens are refreshed automatically when they expire — you should rarely need to re-authenticate.
Usage Examples
Typical interactions with an AI assistant:
User: "What sites do I have access to?"
→ Calls list_sites
User: "Show me the structure of the Main Office site"
→ Calls get_site_details
User: "Turn on all lights in the Lobby group"
→ Calls control_light(target_type="group", target_id="...", action="on")
User: "Set the office lights to 50% brightness"
→ Calls control_light(target_type="group", target_id="...", action="set_level", level=50)
User: "Change the lobby to warm white (3000K)"
→ Calls set_colour(target_type="group", target_id="...", mode="temperature", kelvin=3000)
Core Tool Families
- Site discovery:
list_sites,get_site_details - Topology inventory:
list_groups,list_devices,list_gateways,list_device_locations - Lighting control:
control_light,set_colour,set_profile - Live telemetry:
get_live_light_levels,get_sensor_readings,get_system_variables - Diagnostics:
get_device_health - Scope controls:
set_scope,get_scope,clear_scope
Safe Control Workflow
- Start with
list_sites. - Resolve a concrete target with
get_site_detailsorlist_groups. - Prefer controlling groups over individual devices.
- Use moderate levels first (for example, 30-50%) before full output.
- Use scope controls to avoid cross-site mistakes in multi-site environments.
Troubleshooting
Required environment variable(s) not set:- Set
ZENCONTROL_CLIENT_IDandZENCONTROL_CLIENT_SECRETfor stdio mode.
- Set
- HTTP 401 on live endpoints:
- Verify account entitlement for Live API and valid token scope.
- HTTP 403 on diagnostics:
- Account may not have access to diagnostics endpoints.
get_site_detailsparsing inconsistencies:- This server tolerates both label payload shapes (
{"value": "..."}and plain strings).
- This server tolerates both label payload shapes (
Architecture
┌─────────────────────┐ stdio / StreamableHTTP ┌─────────────────────┐
│ MCP Client │ ──────────────────────────────▶ │ zencontrol-cloud-mcp│
│ (Claude, Cursor, …) │ │ FastMCP Server │
└─────────────────────┘ └──────────┬──────────┘
│
REST + Live API│
▼
┌──────────────────┐
┌──────────────────┐ │ ZenControl │
│ Encrypted │◀─────▶│ Cloud API │
│ Token Store │ └──────────────────┘
└──────────────────┘
Development
git clone https://github.com/oWretch/zencontrol-cloud-mcp.git
cd zencontrol-cloud-mcp
uv sync
# Lint & format
uv run ruff check src/
uv run ruff format --check src/
# Run tests
uv run pytest
# Generate full API docs (Markdown)
uv run python scripts/generate_docs.py
Generated documentation entry points:
docs/reference/api.md
See CONTRIBUTING.md for full guidelines.
API Payload Compatibility Notes
Some ZenControl payloads can represent labels in two shapes:
- Wrapped sync field:
{ "value": "Office", "state": "OK", "error": null } - Plain string:
"Office"
The server accepts both formats for label fields (for example, tenancy and floor
labels) so tools such as get_site_details remain robust across mixed API
responses.
License
This project is licensed under the Apache License 2.0.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file zencontrol_cloud_mcp-1.0.1.tar.gz.
File metadata
- Download URL: zencontrol_cloud_mcp-1.0.1.tar.gz
- Upload date:
- Size: 43.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c74fab1a4d637a38c5b4453d38ab6aa0b0397fac1a19ffaf784236af5a239f65
|
|
| MD5 |
43c7fa911fc59682650e585cdb129491
|
|
| BLAKE2b-256 |
2b7a7317e559478c99b250c77aeb7e3cdb284d1464ef3abc5e8ce3ae266dc123
|
Provenance
The following attestation bundles were made for zencontrol_cloud_mcp-1.0.1.tar.gz:
Publisher:
release.yml on oWretch/zencontrol-cloud-mcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
zencontrol_cloud_mcp-1.0.1.tar.gz -
Subject digest:
c74fab1a4d637a38c5b4453d38ab6aa0b0397fac1a19ffaf784236af5a239f65 - Sigstore transparency entry: 1417314367
- Sigstore integration time:
-
Permalink:
oWretch/zencontrol-cloud-mcp@ecb8fa0568478d5fe5536343d429ac3bea0ca7cc -
Branch / Tag:
refs/heads/main - Owner: https://github.com/oWretch
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@ecb8fa0568478d5fe5536343d429ac3bea0ca7cc -
Trigger Event:
push
-
Statement type:
File details
Details for the file zencontrol_cloud_mcp-1.0.1-py3-none-any.whl.
File metadata
- Download URL: zencontrol_cloud_mcp-1.0.1-py3-none-any.whl
- Upload date:
- Size: 56.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
719569164ccb55f202b3e148936eb9aca923232b5ca8b9eff0fcbf780a279c17
|
|
| MD5 |
886aa5d5679adf2f097f3385b30d79ee
|
|
| BLAKE2b-256 |
563e651b2ff8f4a4d2134c2135cf266609c08a808d9cba5b58e32d5e6e5b9cf9
|
Provenance
The following attestation bundles were made for zencontrol_cloud_mcp-1.0.1-py3-none-any.whl:
Publisher:
release.yml on oWretch/zencontrol-cloud-mcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
zencontrol_cloud_mcp-1.0.1-py3-none-any.whl -
Subject digest:
719569164ccb55f202b3e148936eb9aca923232b5ca8b9eff0fcbf780a279c17 - Sigstore transparency entry: 1417314369
- Sigstore integration time:
-
Permalink:
oWretch/zencontrol-cloud-mcp@ecb8fa0568478d5fe5536343d429ac3bea0ca7cc -
Branch / Tag:
refs/heads/main - Owner: https://github.com/oWretch
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@ecb8fa0568478d5fe5536343d429ac3bea0ca7cc -
Trigger Event:
push
-
Statement type: