Using websocket matter server to query/control matter-enabled lights/sensors via a HTTP GET interface.
Project description
Matter Web Controller
A Python server that bridges Matter smart home devices and external logical bridges (e.g., Casambi) into a unified REST + MCP interface.
Architecture
- Matter Bridge — Runs
python-matter-serveras a background process and connects via WebSocket. Device states are cached locally for fast, non-blocking API responses. - Logical Bridges — Integrates third-party systems over HTTP. Brightness scale mismatches (0–1 vs 0–254) are auto-normalized.
- Event-Driven Cache — Subscribes to Matter attribute changes and persists state to
devices_cache.txt,bridge_cache.json, etc. Caches are loaded on startup. - Unified API — All WebSocket/protocol complexity is abstracted into simple HTTP endpoints and SSE streams. Commands are routed to physical or logical devices based on ID resolution.
Limitations
- Only Matter devices already on the LAN are supported. See device docs for network provisioning.
- Native support: bridges, lights, motion sensors, presence sensors.
- Non-Matter hardware (Casambi, Yeelight, etc.) requires integration via Logical Bridge.
Requirements
Python 3.12+
Installation
From PyPI
pip install matter-web-controller
From source
git clone https://github.com/phatdat-dev/matter_webcontrol.git
cd matter_webcontrol
pip install .
All dependencies (aiohttp, fastapi, home-assistant-chip-core, mcp, etc.) are resolved automatically.
Usage
HTTP Server
sudo matter-srv # starts on port 8080
sudo matter-srv --port 9090 # custom port
sudo matter-srv --fabric "Home Lab" # set Matter fabric label
MCP Server
The MCP server connects to a running matter-srv instance via HTTP.
matter-mcp # connects to localhost:8080
matter-mcp --host 192.168.1.10 # remote server
matter-mcp --port 9090 # custom port
Note:
sudois recommended because Matter uses BLE and low-level network interfaces that require root privileges for device commissioning and discovery.
HTTP server options:
| Option | Default | Description |
|---|---|---|
--port |
8080 | Web server port |
--fabric |
(none) | Matter fabric label |
MCP server options:
| Option | Default | Description |
|---|---|---|
--host |
localhost |
HTTP server host |
--port |
8080 | HTTP server port |
The Matter server process binds to port + 1 automatically.
API Reference
Device IDs: Devices use stable hash-based IDs derived from hardware UniqueID (e.g.
dev_a3f7c1b2). All endpoints require the canonicaldev_*ID. Aliases set via/api/nameare for display purposes only.
GET /api/bridge — Register a logical bridge
| Param | Type | Required | Description |
|---|---|---|---|
ip |
string | yes | Bridge IPv4 address |
port |
int | yes | Bridge port |
GET /api/bridge?ip=192.168.1.220&port=8000
GET /api/devices — List all devices
Returns all physical and logical devices with their raw states and aliases.
GET /api/devices
GET /api/lights — List lighting devices
Returns lights with normalized brightness (0.0–1.0) and color temperature (Kelvin).
GET /api/lights
GET /api/sensors — List sensor devices
Returns sensors with their metrics and occupancy timestamps.
GET /api/sensors
GET /api/sensor — Get a single sensor
| Param | Type | Required | Description |
|---|---|---|---|
id |
string | yes | Device ID |
GET /api/sensor?id=Motion_Entry
GET|POST /api/name — Assign a device alias
| Param | Type | Required | Description |
|---|---|---|---|
id |
string | yes | Device ID |
name |
string | yes | New unique alias |
curl -X POST -H "Content-Type: application/json" \
-d '{"id": "dev_1_8", "name": "Main Hall"}' \
http://localhost:8080/api/name
GET /api/name/remove — Remove a device alias
| Param | Type | Required | Description |
|---|---|---|---|
id |
string | yes | Device ID |
name |
string | yes | Alias to remove |
GET /api/name/remove?id=dev_a3f7c1b2&name=Main Hall
GET /api/status — Quick device summary
Returns counts: lights on/off, active sensors, connected bridges, total devices.
GET /api/status
GET /api/toggle — Toggle a device on/off
| Param | Type | Required | Description |
|---|---|---|---|
id |
string | yes | Device ID |
GET /api/toggle?id=Main Hall
GET /api/bridge/remove — Remove a logical bridge
| Param | Type | Required | Description |
|---|---|---|---|
ip |
string | yes | Bridge IPv4 address |
port |
int | yes | Bridge port |
GET /api/bridge/remove?ip=192.168.1.220&port=8000
POST /api/batch — Control multiple devices
curl -X POST -H "Content-Type: application/json" \
-d '{"actions": [{"id": "dev_a1b2", "brightness": 0.5}, {"id": "dev_c3d4", "brightness": 0}]}' \
http://localhost:8080/api/batch
GET /api/register — Commission a Matter device
| Param | Type | Required | Description |
|---|---|---|---|
code |
string | yes | Manual pairing code |
ip |
string | no | Target IP for commissioning |
name |
string | no | Alias to assign after join |
GET /api/register?code=11223344556&name=Kitchen
GET|POST /api/set — Control a device
| Param | Type | Required | Description |
|---|---|---|---|
id |
string | yes | Device ID or alias |
brightness |
float | no | Target brightness (0.0–1.0) |
temperature |
int | no | Target color temperature (K) |
curl -X POST -H "Content-Type: application/json" \
-d '{"id": "Sofa and Painting", "brightness": 0.8}' \
http://localhost:8080/api/set
GET|POST /api/level — Get/set raw brightness (0–254)
| Param | Type | Required | Description |
|---|---|---|---|
id |
str | yes | Device ID or alias |
level |
int | no | Raw level (0–254). Omit to read. |
GET /api/level?id=dev_1_8
GET /api/level?id=dev_1_8&level=200
GET|POST /api/mired — Get/set color temperature (mireds)
| Param | Type | Required | Description |
|---|---|---|---|
id |
str | yes | Device ID or alias |
mireds |
int | no | Color temp in mireds. Omit to read. |
GET /api/mired?id=dev_1_8
GET /api/mired?id=dev_1_8&mireds=250
GET /api/subscribe — SSE stream for occupancy events
| Param | Type | Required | Description |
|---|---|---|---|
id |
string | yes | Device ID |
curl -N -H "Accept: text/event-stream" \
"http://localhost:8080/api/subscribe?id=Motion_Entry"
Each event: {"id": "...", "occupancy": 0|1, "timestamp": "ISO 8601"}
GET /api/refresh — Force refresh all device states
Refreshes both the Matter cache and all logical bridge metadata.
GET /api/refresh
GET /api/metadata — Bridge metadata for federation
Returns this server's device list with executable Python scripts for each event, allowing other instances to integrate as a logical bridge.
Example response
{
"bridge": {
"id": "matter_bridge_http",
"type": "lighting_controller",
"network_host": "192.168.1.220",
"network_port": 8080
},
"devices": [
{
"node_id": "dev_1_8",
"name": "Tunable Desk Light",
"hardware_type": "color_temperature_light",
"events": {
"turn_on": {
"trigger": "on_off_cluster",
"script": "import urllib.request\nurllib.request.urlopen('http://192.168.1.220:8080/api/set?id=dev_1_8&brightness=1.0')"
},
"turn_off": {
"trigger": "on_off_cluster",
"script": "import urllib.request\nurllib.request.urlopen('http://192.168.1.220:8080/api/set?id=dev_1_8&brightness=0.0')"
},
"set_level": {
"trigger": "level_control_cluster",
"script": "import sys, urllib.request\nlevel = int(sys.argv[1]) if len(sys.argv) > 1 else 254\nurllib.request.urlopen(f'http://192.168.1.220:8080/api/level?id=dev_1_8&level={level}')"
},
"read_level": {
"trigger": "level_control_cluster",
"script": "import urllib.request, json\nresponse = urllib.request.urlopen('http://192.168.1.220:8080/api/level?id=dev_1_8')\ndata = json.loads(response.read().decode('utf-8'))\nprint(data.get('level', 0))"
},
"set_color_temperature": {
"trigger": "color_control_cluster",
"script": "import sys, urllib.request\nmireds = int(sys.argv[1]) if len(sys.argv) > 1 else 250\nurllib.request.urlopen(f'http://192.168.1.220:8080/api/mired?id=dev_1_8&mireds={mireds}')"
},
"read_color_temperature": {
"trigger": "color_control_cluster",
"script": "import urllib.request, json\nresponse = urllib.request.urlopen('http://192.168.1.220:8080/api/mired?id=dev_1_8')\ndata = json.loads(response.read().decode('utf-8'))\nprint(data.get('mireds', 0))"
}
}
},
{
"node_id": "dev_2_1",
"name": "Motion Sensor",
"hardware_type": "occupancy_sensor",
"events": {
"read_occupancy": {
"trigger": "occupancy_sensing_cluster",
"script": "import urllib.request, json\nresponse = urllib.request.urlopen('http://192.168.1.220:8080/api/sensor?id=dev_2_1')\ndata = json.loads(response.read().decode('utf-8'))\nprint(data.get('occupancy', 0))"
},
"subscribe_occupancy": {
"trigger": "occupancy_sse_stream",
"script": "import urllib.request\nresponse = urllib.request.urlopen('http://192.168.1.220:8080/api/subscribe?id=dev_2_1')\nfor line in response:\n print(line.decode('utf-8').strip())"
}
}
}
]
}
MCP Integration
The matter-mcp command connects to a running matter-srv and exposes its operations as MCP tools, allowing LLMs to control Matter devices directly. Start the HTTP server first, then run the MCP server.
Available Tools
| Tool | Description |
|---|---|
get_devices |
List all devices with states and aliases |
get_lights |
List lights with brightness and temperature |
get_sensors |
List sensors with metrics |
get_sensor |
Get a single sensor by ID/alias |
get_status |
Quick summary (lights on/off, sensors, bridges) |
set_device |
Control brightness and/or color temperature |
toggle |
Toggle device on/off |
set_level |
Set raw brightness (0–254) |
set_mired |
Set color temperature (mireds) |
batch_control |
Control multiple devices at once |
set_name |
Assign alias to device |
remove_name |
Remove alias from device |
add_bridge |
Register logical bridge |
remove_bridge |
Remove logical bridge |
register_device |
Commission new Matter device |
refresh |
Force refresh all states |
Claude Desktop Configuration
{
"mcpServers": {
"matter": {
"command": "matter-mcp",
"args": ["--host", "localhost", "--port", "8080"]
}
}
}
Project details
Release history Release notifications | RSS feed
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 matter_web_controller-0.24.0.tar.gz.
File metadata
- Download URL: matter_web_controller-0.24.0.tar.gz
- Upload date:
- Size: 19.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8b13df3787c393d63409b2beb130111b9b6a65952820dc92d8acfcb6e272f5cc
|
|
| MD5 |
40d003e0642beab564477bd1a5bb1556
|
|
| BLAKE2b-256 |
b19c7732763e7abfcb6b39c735fa8a9ee43507f12ac9075dc27f2437eeb4e3d7
|
Provenance
The following attestation bundles were made for matter_web_controller-0.24.0.tar.gz:
Publisher:
python-publish.yml on dongnh/matter_webcontrol
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
matter_web_controller-0.24.0.tar.gz -
Subject digest:
8b13df3787c393d63409b2beb130111b9b6a65952820dc92d8acfcb6e272f5cc - Sigstore transparency entry: 1155013537
- Sigstore integration time:
-
Permalink:
dongnh/matter_webcontrol@3d011ad538fa20e6199f0e7760209043ca8b4e94 -
Branch / Tag:
refs/tags/v0.24.0 - Owner: https://github.com/dongnh
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@3d011ad538fa20e6199f0e7760209043ca8b4e94 -
Trigger Event:
release
-
Statement type:
File details
Details for the file matter_web_controller-0.24.0-py3-none-any.whl.
File metadata
- Download URL: matter_web_controller-0.24.0-py3-none-any.whl
- Upload date:
- Size: 19.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
af2240146a3f9f6a5ecb3122969362b126d72d977777386e05e8bceae7948032
|
|
| MD5 |
434c39802c5ae50d09993a06eb7be208
|
|
| BLAKE2b-256 |
144f7fdeffaf51fea32023645d460a929b95c00ba6fbb9395a5376de0ff1d34e
|
Provenance
The following attestation bundles were made for matter_web_controller-0.24.0-py3-none-any.whl:
Publisher:
python-publish.yml on dongnh/matter_webcontrol
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
matter_web_controller-0.24.0-py3-none-any.whl -
Subject digest:
af2240146a3f9f6a5ecb3122969362b126d72d977777386e05e8bceae7948032 - Sigstore transparency entry: 1155013539
- Sigstore integration time:
-
Permalink:
dongnh/matter_webcontrol@3d011ad538fa20e6199f0e7760209043ca8b4e94 -
Branch / Tag:
refs/tags/v0.24.0 - Owner: https://github.com/dongnh
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@3d011ad538fa20e6199f0e7760209043ca8b4e94 -
Trigger Event:
release
-
Statement type: