Skip to main content

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

  1. Matter Bridge — Runs python-matter-server as a background process and connects via WebSocket. Device states are cached locally for fast, non-blocking API responses.
  2. Logical Bridges — Integrates third-party systems over HTTP. Brightness scale mismatches (0–1 vs 0–254) are auto-normalized.
  3. Event-Driven Cache — Subscribes to Matter attribute changes and persists state to devices_cache.txt, bridge_cache.json, etc. Caches are loaded on startup.
  4. 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: sudo is 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 canonical dev_* ID. Aliases set via /api/name are 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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

matter_web_controller-0.24.0.tar.gz (19.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

matter_web_controller-0.24.0-py3-none-any.whl (19.3 kB view details)

Uploaded Python 3

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

Hashes for matter_web_controller-0.24.0.tar.gz
Algorithm Hash digest
SHA256 8b13df3787c393d63409b2beb130111b9b6a65952820dc92d8acfcb6e272f5cc
MD5 40d003e0642beab564477bd1a5bb1556
BLAKE2b-256 b19c7732763e7abfcb6b39c735fa8a9ee43507f12ac9075dc27f2437eeb4e3d7

See more details on using hashes here.

Provenance

The following attestation bundles were made for matter_web_controller-0.24.0.tar.gz:

Publisher: python-publish.yml on dongnh/matter_webcontrol

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file matter_web_controller-0.24.0-py3-none-any.whl.

File metadata

File hashes

Hashes for matter_web_controller-0.24.0-py3-none-any.whl
Algorithm Hash digest
SHA256 af2240146a3f9f6a5ecb3122969362b126d72d977777386e05e8bceae7948032
MD5 434c39802c5ae50d09993a06eb7be208
BLAKE2b-256 144f7fdeffaf51fea32023645d460a929b95c00ba6fbb9395a5376de0ff1d34e

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page