WLED MCP
An unofficial MCP server that lets an AI agent read and control WLED LED controllers by name: power, brightness, segments, effects, palettes, presets, groups and scenes. It talks to each controller's JSON API on your network, validates every change before sending it and reads it back afterwards. It runs as a subprocess of your MCP host (stdio) or as a separate HTTP service. It is not affiliated with, endorsed by or supported by the WLED project or MCPHub.
Status: early software with 0.x versions that may break between releases
(CHANGELOG.md). Releases are distributed on PyPI as
wled-mcp; a release that is not listed there yet
installs from its Git tag instead. The container image is not published to GHCR.
Hardware acceptance is partial: one controller on WLED 16.0.1. No support is promised
(Support).
What it does
- Self-hosted: no cloud service, account, MQTT broker or public endpoint is needed.
- Named inventory of controllers in a TOML file. The server and its tools discover
nothing;
wled-mcp discoveris an opt-in command. - Normalized state, capabilities and each device's own effect and palette catalogs.
- Typed changes: master power and brightness, a patch of selected segments, or a replacement of the complete layout. Advanced segment fields (CCT, 2D) are written only where the device reports them.
- Persistent presets with snapshots, restore, portable bundles and playlists; named device groups and multi-device scenes with a dry-run plan.
- Server-enforced profiles (
read-only,control,full) and, for the HTTP service, a bearer credential with Host and Origin allowlists.
Every tool, with its read-only, write or destructive hint, is listed in the tool contract.
WLED feature coverage: 58 % of the planned scope, 47 % of WLED overall (method and list).
Try it
You need uv, an MCP host that can start a stdio server and
a WLED controller reachable over HTTP; the optional HTTP service also needs Docker with
Docker Compose. Replace <version> with the version of the
latest release (its tag is
v<version>). The commands install that release from
PyPI. If the version is not listed there yet, use the
Git route instead: replace wled-mcp==<version> with
git+https://github.com/descipar/wled-mcp@v<version>, which builds the package from the tag
on your machine; without a tag, uvx takes the current main, which can change at any
time. The commands are for a POSIX shell; Windows is experimental
(docs/DEVELOPMENT.md).
-
Check the installation (no device, no configuration):
uvx --isolated --python 3.13 --from wled-mcp==<version> wled-mcp --version
-
Create a data directory and an inventory with one controller (contacts nothing):
mkdir -p "$HOME/wled-mcp" uvx --isolated --python 3.13 --from wled-mcp==<version> wled-mcp config init --config "$HOME/wled-mcp/devices.toml" --device-id desk --device-name "Desk strip" --base-url http://<controller-address>
-
Register the server in your MCP host with the command
uvxand these arguments, each one separate, using absolute paths:--isolated --python 3.13 --from wled-mcp==<version> wled-mcp --transport stdio --config <absolute path>/wled-mcp/devices.toml --data-dir <absolute path>/wled-mcp
Ask the agent to list your WLED devices (
wled_list_devices). Every write tool acceptsdry_run=trueto preview a change without touching the lights.
Both routes need network access (the Git route to GitHub as well as PyPI). The dependencies
are resolved within the ranges the package declares when uvx first creates the tool
environment, so they can be newer than the set the release was tested with; for that tested
set add the release constraints (dependency policy). For a
checksum-verified wheel, more devices, the
inventory format and the HTTP service, follow the
quickstarts; updates, rollback and removal are in
docs/DEPLOYMENT.md.
Safety model
- Validate first. A complete request is checked against the current device state before the first write; unknown fields and out-of-range values are rejected. Omitted fields mean "unchanged", never "reset".
- Patch versus replace.
wled_patch_segmentschanges only the named segments; onlywled_replace_layoutremoves segments that are not listed. - Dry run and verification.
dry_run=truereturns the plan without writing. Writes are read back; a write that timed out is reported as possibly applied and is never retried blindly. - Snapshots. Overwriting or deleting a preset first stores a durable snapshot in the
data directory. Restores, imports, supplied-state stores (
wled_store_preset) and playlist saves change the live output before they store, and the previous lighting is not restored. - No hidden reach. No discovery by the server or its tools, no arbitrary endpoints or
caller-supplied hosts, no silent preset overwrite (
overwrite=trueis required). - Authorization. Whether a person may run a tool is the MCP host's job; tool annotations are hints only. The HTTP service also requires its own bearer credential and Host allowlist and must not be exposed to the internet.
Compatibility
What the checks cover; the evidence for each row and the firmware tiers are in docs/contract/compatibility.md. This is not a support commitment (see Support).
| Area | Status |
|---|---|
| Python 3.13 | supported |
| Linux amd64 | supported |
| Linux arm64 | supported |
| HTTP container image, amd64 and arm64 | supported |
| stdio via uvx on Linux | supported |
| Windows | experimental |
| macOS | experimental |
| WLED 16.0.1 | tested |
| WLED 16.x other than 16.0.1 | unknown |
| WLED below 16.0.0, including 0.15.x | unsupported |
Unsupported or unrecognized firmware is served with a warning and never refused;
wled_get_state reports the tier in diagnostics.firmware_support.
Limitations
Automated tests use mocks and synthetic loopback devices. Hardware acceptance covers the
first feature set on one RGB controller, and a live check with an offline controller is
still pending. A short live check of release 0.1.1 over HTTP and stdio covered state
reads, power, brightness and effect changes on that controller
(record). A later run on the same controller
exercised a one-device group and scene, preset store, export, import and restore, and a
playlist, with the controller restored afterwards
(record). Multi-device scenes, profiles, discover, restore
onto an occupied slot, playlist import, restoring a playlist preset and CCT, RGBW and 2D controllers have no hardware run.
Other limits:
- No tool deletes a snapshot on request; snapshots are only removed by retention pruning (20 per controller by default).
- Storing, restoring or importing a preset without changing the live output is not possible on WLED 16, and saving a playlist starts it.
- One writer per controller: locks are per process, so a second process or service against the same devices is not coordinated.
- No inventory reload; changes need
wled-mcp config validateand a restart. - No device authentication: WLED has none for its light API ("Anyone with your IP and port can control the lights", WLED docs). The server sends no device credentials and rejects credentials in a device URL, so a controller behind HTTP authentication or a credentialed proxy is not supported. Behavior with a settings PIN or OTA lock is untested; a test is planned (#128).
- No image on GHCR, no registry entry. A live update of a deployed HTTP service was checked once, from an earlier build to release 0.1.1; a rollback has not been checked.
The complete list and the evidence are in docs/VALIDATION.md.
Documentation
| Document | Contents |
|---|---|
| Quickstarts | Release directory, stdio and HTTP setup, inventory format |
| Deployment | Both transports in detail: staging, verification, update, rollback, removal |
| Tool contract | Tools, parameters, results, errors and mutation semantics |
| WLED feature coverage | WLED features with support status, owning issue or decision, and coverage figures |
| Inventory and client | Inventory schema, limits and HTTP client behavior |
| Development | Local checks, build and launch, including PowerShell |
| Validation | Automated checks, opt-in hardware checks, recorded evidence, known limitations |
| Architecture | Components, runtime and design decisions |
| Contract examples | Synthetic request, result and snapshot examples |
Support
There is no support commitment. Questions and problems go to GitHub issues, which are answered best effort, without any commitment to respond or fix. There is no security support; see SECURITY.md.
Project and contributing
Project status, roadmap and the maintainer document index are in docs/PROJECT.md. How to report problems and propose changes is in CONTRIBUTING.md.
How this project is developed
The maintainer develops this project with coding agents that follow a documented
workflow: AGENTS.md holds the project rules,
docs/AGENT-WORKFLOW.md describes the requirements,
implementation, review and completion roles, and the agents/ directory holds the
role definitions. Human contributions do not need this workflow. Design decisions and
their rationale are recorded in docs/DECISIONS.md and, per issue, in
docs/decisions/.
License
Licensed under the Apache License 2.0. Redistributions, including modified versions, must retain the copyright and attribution notice in NOTICE. The project is provided as is, without security support; see SECURITY.md.
Metadata
Release files for wled-mcp 0.1.2
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 |
|---|---|---|---|---|
| wled_mcp-0.1.2.tar.gz | 911.0 kB | With provenance | Details for wled_mcp-0.1.2.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| wled_mcp-0.1.2-py3-none-any.whl | Python 3 | none | any | Details for wled_mcp-0.1.2-py3-none-any.whl |
Total release size: 1.1 MB
Release files / wled_mcp-0.1.2.tar.gz
| Download URL | wled_mcp-0.1.2.tar.gz |
|---|---|
| Size | 911.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0db94687f9de49b56dd50ce97fe415b7d892cae3785b16e24c27acee7cce4ce4
|
|
BLAKE2b-256 checksum How to use checksums |
ae9aa9c052e6a6746532794c2ca6a97059a6e52fc727422f82580002115ee223
|
| 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 9, 2026.
Transparency logRelease files / wled_mcp-0.1.2-py3-none-any.whl
| Download URL | wled_mcp-0.1.2-py3-none-any.whl |
|---|---|
| Size | 194.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3177df4bd68f1e4362f16b6519b72c2748847bbd58713cc2e8e41e02d5940c3e
|
|
BLAKE2b-256 checksum How to use checksums |
754aacf83da1fd92e1d5a6f39373934f0ebfd1333559bc54484b3810e6975c0e
|
| 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 9, 2026.
Transparency logSecurity for wled-mcp 0.1.2
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
Both files in this release have been uploaded with provenance metadata.
Attestation for wled_mcp-0.1.2.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 9, 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.