halo-light
Serveur MCP pour les lumières Philips Hue, écrit à neuf sur l'API locale CLIP v2 du pont (https, en-tête hue-application-key). Un assistant (Claude, Lyra, etc.) peut lire l'état des lumières, des pièces et des scènes, puis les commander par identifiant ou par nom.
Fonctionnalités
- Lumières, pièces, zones et scènes de l'API v2 (
light,grouped_light,room,zone,scene). - Adressage par identifiant (UUID v2, ou ancien identifiant numérique v1 comme
12) ou par nom. - Noms insensibles à la casse et aux accents : correspondance exacte d'abord, partielle seulement si elle est unique, sinon une erreur liste les candidats.
- Une scène est activée dans sa propre pièce : aucun groupe n'est codé en dur.
- Couleur par nom (
rouge,bleu,orange...), hexadécimal (#ff8800), RGB ou xy ; température de blanc en Kelvin. - Erreurs remontées comme erreurs MCP (
isError) avec un message exploitable par le modèle. - Annotations MCP sur chaque outil (
readOnlyHint,destructiveHint,idempotentHint). - Extension optionnelle
hue_beat(synchronisation lumière / musique) via un script externe.
Installation
Prérequis : Python 3.10 ou plus récent et un pont Hue sur le réseau local.
git clone https://github.com/amineutron/halo-light.git
cd halo-light
uv sync
Configuration
L'application a besoin de l'adresse du pont (facultative : elle est découverte automatiquement s'il n'y a qu'un pont) et d'une clé d'application.
Appairage
uv run halo-light pair # adresse découverte automatiquement
uv run halo-light pair --host <adresse-du-pont>
Appuyez sur le bouton du pont quand la commande le demande. La clé est enregistrée dans ~/.config/halo-light/config.json, créé en mode 0600 (dossier en 0700). La clé n'est jamais affichée.
uv run halo-light discover liste les ponts connus du service de découverte de Philips.
Variables d'environnement (prioritaires sur le fichier)
| Variable | Rôle |
|---|---|
HUE_APP_KEY |
clé d'application |
HUE_BRIDGE_IP |
adresse du pont (sinon découverte via discovery.meethue.com, puis mDNS si zeroconf est installé : uv sync --extra mdns) |
HUE_BRIDGE_CA_CERT |
fichier PEM pour vérifier le certificat du pont (facultatif) |
HALO_LIGHT_CONFIG |
autre chemin pour le fichier de configuration |
Le pont présente un certificat signé par une autorité privée de Signify : par défaut il n'est pas vérifié (réseau local). Pour l'épingler, fournissez l'autorité avec HUE_BRIDGE_CA_CERT.
Brancher le serveur à un client MCP
{
"mcpServers": {
"hue": {
"command": "uv",
"args": ["--directory", "/chemin/vers/halo-light", "run", "halo-light"],
"env": { "HUE_APP_KEY": "<cle>" }
}
}
}
Évitez d'écrire la clé en clair : préférez le fichier en 0600 ou un gestionnaire de secrets.
Outils exposés
Tous les outils d'action acceptent light_id ou light_name (lumières), group_id ou group_name (pièces et zones). Si les deux sont fournis, l'identifiant l'emporte.
| Outil | Rôle | Nature |
|---|---|---|
get_all_lights, get_light, find_light_by_name |
lire les lumières | lecture seule |
get_all_groups, get_group |
lire pièces, zones et maison | lecture seule |
get_all_scenes |
lire les scènes et leur pièce | lecture seule |
turn_on_light, turn_off_light |
allumer / éteindre | écriture, idempotent |
set_brightness |
luminosité 0-100 (allume ; 0 éteint) | écriture, idempotent |
set_color, set_color_rgb, set_color_xy |
couleur par nom ou hexadécimal / RGB / xy | écriture, idempotent |
set_color_temperature |
blanc en Kelvin (2000 à 6500) | écriture, idempotent |
set_color_preset |
préréglage nommé : warm, cool, daylight, concentration, relax, reading, energize, red, green, blue, purple, orange |
écriture, idempotent |
set_light_effect |
effet dynamique : none, candle, fire, prism, sparkle, opal, glisten, underwater, cosmos, sunbeam, enchant |
écriture, idempotent |
alert_light |
clignotement d'identification | écriture |
turn_on_group, turn_off_group |
allumer / éteindre une pièce ou zone | écriture, idempotent |
set_group_brightness, set_group_color, set_group_color_rgb, set_group_color_temperature, set_group_color_preset |
idem pour un groupe | écriture, idempotent |
activate_scene_by_name |
active une scène par nom dans sa pièce (group_name pour départager) |
écriture, idempotent |
set_scene |
active une scène par identifiant | écriture, idempotent |
hue_beat_start, hue_beat_stop, hue_beat_status, hue_beat_set |
extension optionnelle | voir ci-dessous |
Aucun outil n'est destructif : les changements d'état sont réversibles et rien n'est supprimé sur le pont.
Exemples de résolution de noms
light_name="cafe"trouve « Lampe Café » (accents et casse ignorés).light_name="salon"avec « Salon Plafond » et « Salon Lampadaire » renvoie une erreur qui liste les deux.scene_name="relax"existant dans deux pièces renvoieRelax (Salon), Relax (Chambre): ajoutezgroup_name="chambre".
Extension optionnelle hue_beat
Les outils hue_beat_* pilotent un script externe de synchronisation lumière / musique (par exemple via l'Entertainment API). Ce script n'est pas fourni ici. Indiquez son chemin :
export HUE_BEAT_PATH=/chemin/vers/hue_beat.py
Contrat attendu du script :
- lancé en arrière-plan avec
python <script> --palette=P [--mode=M] [--bass-only]; - écrit son PID dans
HUE_BEAT_PID_FILEet un état JSON (mode,palette,bpm...) dansHUE_BEAT_STATE_FILE; - lit des commandes JSON (
palette,mode,brightness,floor,sensitivity) dansHUE_BEAT_CTRL_FILE; - s'arrête proprement sur
SIGTERM.
Les trois fichiers sont par défaut dans le dossier temporaire du système (hue_beat.pid, hue_beat.state.json, hue_beat.ctrl) ; adaptez les variables aux chemins réels du script. Sans HUE_BEAT_PATH, ces outils répondent par une erreur claire et le reste du serveur fonctionne normalement. HUE_BEAT_PYTHON (facultatif) désigne l'interpréteur qui lance le script, utile quand celui-ci a besoin de paquets (numpy, audio) absents de l'environnement du serveur ; sinon c'est l'interpréteur du serveur. Pendant la synchronisation, le pont peut ignorer les commandes sur les lumières de la zone de divertissement.
Brancher Lyra
Le script ironman-hue (hue_beat.py) de Lyra utilise des chemins fixes, définis par les constantes PID_FILE, STATE_FILE et CTRL_FILE en tête du script. Pour que les outils hue_beat_* les retrouvent, posez ces variables dans l'environnement du serveur avec les mêmes valeurs :
export HUE_BEAT_PATH=<chemin du script hue_beat.py>
export HUE_BEAT_PID_FILE=<valeur de PID_FILE>
export HUE_BEAT_STATE_FILE=<valeur de STATE_FILE>
export HUE_BEAT_CTRL_FILE=<valeur de CTRL_FILE>
Les valeurs par défaut du serveur (hue_beat.pid, etc.) ne correspondent pas à celles du script : sans ces variables, le statut et les réglages ne l'atteignent pas.
La synchronisation en streaming (DTLS) demande en plus un utilisateur « entertainment », sa clé client et la zone de divertissement. Plutôt que de les écrire dans la configuration du client MCP, ajoutez une section beat au fichier ~/.config/halo-light/config.json (mode 0600) ; le serveur les transmet au script sous les noms HUE_USER, HUE_CLIENTKEY et HUE_AREA_ID, sans jamais les afficher :
{
"bridge_ip": "<adresse-du-pont>",
"app_key": "<cle>",
"beat": { "username": "<utilisateur>", "clientkey": "<cle-client>", "area_id": "<zone>" }
}
Sans section beat, HUE_USER reprend la clé d'application. Une variable d'environnement déjà définie l'emporte toujours.
Développement
uv sync
uv run ruff check . && uv run ruff format --check .
uv run pytest
Les tests s'exécutent contre un faux pont en mémoire (httpx.MockTransport, voir tests/fake_bridge.py) et ne touchent jamais un vrai pont. Voir CONTRIBUTING.md.
Inspiration et remerciements
Ce projet est une réécriture indépendante, inspirée par l'interface du serveur ThomasRohde/hue-mcp (licence MIT, © Thomas Rohde), lui-même construit sur la bibliothèque phue de Nathanael Lecaude. Les noms de la plupart des outils sont conservés pour rester compatibles avec les assistants qui les appellent déjà.
Aucune ligne de code d'implémentation n'est reprise de ces projets : tout est écrit à partir de la documentation officielle de l'API Hue (CLIP v2). Merci à Thomas Rohde pour le point de départ. Contrairement à ces projets, qui reposent sur l'API v1, celui-ci utilise l'API v2 (identifiants UUID, scènes rattachées à leur pièce).
Différences avec hue-mcp
- API v2 au lieu de v1 (
phuen'est plus nécessaire) ;httpxasynchrone. - Pas de groupe par défaut codé en dur (l'ancien groupe 81) : un groupe ou une pièce doit être désigné, sauf pour les scènes qui portent leur propre pièce.
- Pas de cache à rafraîchir : l'état est lu en direct (
refresh_lightsn'existe plus). - Non repris pour l'instant :
create_group,quick_scene, les préréglages de couleur et les effets (set_light_effect).set_colorremplace les préréglages. - Nouveautés :
set_color,set_color_xy, groupes par nom, appairage et découverte en ligne de commande.
Licence
MIT. Les projets dont ce serveur s'inspire sont cités dans NOTICE.
Metadata
Release files for halo-light 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| halo_light-0.1.1.tar.gz | 125.3 kB | With provenance | Details for halo_light-0.1.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| halo_light-0.1.1-py3-none-any.whl | Python 3 | none | any | Details for halo_light-0.1.1-py3-none-any.whl |
Total release size: 153.3 kB
Release files / halo_light-0.1.1.tar.gz
| Download URL | halo_light-0.1.1.tar.gz |
|---|---|
| Size | 125.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b05d1b58cf5564d673f735edbebeb85c2d20a88e3bf29f90f6a0ae37d9c61bfc
|
|
BLAKE2b-256 checksum How to use checksums |
01d7a8799f96e13ed8e5341b89a0751a1e975de4837f5d9509d420145e544ff5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 4, 2026.
Transparency logRelease files / halo_light-0.1.1-py3-none-any.whl
| Download URL | halo_light-0.1.1-py3-none-any.whl |
|---|---|
| Size | 28.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
08b076427f975689afb4c0669166770a22f34f98b28ccbf48853bd0f3f690ac2
|
|
BLAKE2b-256 checksum How to use checksums |
cdf61fc4fa666499ee0eebc5d7f163c81f08b109d2cd16500d6a56e399c3c374
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 4, 2026.
Transparency logSecurity for halo-light 0.1.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for halo_light-0.1.1.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 4, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.