v2.3.0 — Tier 1 expansion: group + scene CRUD, blackout, identify, batch
Highlights
MCP tool catalog grows from 16 → 28. Twelve new tools across five categories close the biggest gaps from v2.2: agents can now manage groups and scenes (not just use them), pulse fixtures for physical identification, kill the rig instantly, and batch multiple actions into a single round trip.
No breaking changes. Every existing endpoint and MCP tool continues to work exactly as before. This is purely additive.
What's new
Group CRUD (5 tools / 5 endpoints)
The control server's groups system gained full lifecycle management. Previously agents could only consume groups defined out-of-band — now they can build and edit them in conversation.
| MCP tool | Flask endpoint |
|---|---|
| `create_group` | `POST /api/groups` |
| `update_group` | `PATCH /api/groups/` |
| `delete_group` | `DELETE /api/groups/` |
| `add_fixtures_to_group` | `POST /api/groups//fixtures` |
| `remove_fixtures_from_group` | `DELETE /api/groups//fixtures` |
Validates fixture IDs against the workspace and rejects unknown IDs with a structured 400.
Scene management (4 tools / 4 endpoints)
Save and snapshot existed in v2.2; the rest of the lifecycle is now covered.
| MCP tool | Flask endpoint |
|---|---|
| `describe_scene` | `GET /api/scenes/` |
| `rename_scene` | `PATCH /api/scenes/` |
| `delete_scene` | `DELETE /api/scenes/` |
| `duplicate_scene` | `POST /api/scenes//duplicate` |
`describe_scene` returns the full per-fixture channel breakdown (including channel name + role from the `.qxf` parser) so an agent can reason about a saved scene's contents before activating or duplicating it.
Safety + utility (3 tools / 2 endpoints)
| MCP tool | Flask endpoint | Notes |
|---|---|---|
| `blackout` | `POST /api/blackout` | Instant kill — zeroes every channel, clears strobe/macro state |
| `identify_fixture` | `POST /api/fixtures//identify` | Pulse a fixture on/off, then restore its previous state |
| `batch_action` | `POST /api/batch` | Ordered list of structured actions in one HTTP round trip |
`identify_fixture` is async-aware: the pulse runs on the persistent QLC+ WebSocket loop without blocking Flask's threads, with bounded duration (max 10s) and pulse count (max 10).
`batch_action` is the right primitive for compound moves like setting key/fill/back to different colors at once (3 actions → 1 round trip), and combines naturally with the new `create_group` — "group the three front pars as 'key-lights', then make them warm" becomes a single conversational turn.
What's also new (peripheral)
- Wiki: `MCP-Server` and `Control-Server` pages refreshed with the new tools/endpoints
- Marketing site (`lights.griffen.codes`): the homepage MCP tool catalog auto-updates to 28; CueSheet now demonstrates `identify_fixture`, `create_group`, `batch_action`, and `blackout`; AiConversation opens with a compound `batch_action` example; FAQ adds three new entries covering group authoring, the kill switch, and physical fixture identification
- Docs: `docs/MCP_SERVER.md`, `docs/CONTROL_SERVER_ARCHITECTURE.md`, `mcp-server/README.md`, and the root `README.md` all updated to reflect the expanded surface
Upgrade
git pull
./lightsctl.sh control-restart # picks up the new endpoints
./lightsctl.sh mcp-restart # picks up the new MCP toolsNo package dependency changes — the new code uses only what was already installed.
Compatibility
- No breaking changes. Every existing route + MCP tool continues to behave identically.
- New endpoints all sit under `/api/` paths that didn't previously exist.
- Group storage format (`~/.qlcplus/fixture_groups.json`) unchanged — `update_group` and `add_fixtures_to_group` preserve the canonical wrapped `{"groups": {...}}` format that v2.2 wrote.
- Workspace XML format unchanged — scene delete/rename/duplicate use the same `` element shape that v2.2's save/snapshot wrote.
Follow-ups (already tracked)
Tier 2 and Tier 3 features have GitHub issues: