Files
javis/homey-mcp
2026-09-21 21:44:00 +02:00
..
2026-09-21 21:44:00 +02:00
2026-09-21 21:44:00 +02:00
2026-09-21 21:44:00 +02:00
2026-09-21 21:44:00 +02:00
2026-09-21 21:44:00 +02:00
2026-09-21 21:44:00 +02:00
2026-09-21 21:44:00 +02:00
2026-09-21 21:44:00 +02:00
2026-09-21 21:44:00 +02:00
2026-09-21 21:44:00 +02:00

homey-mcp

An MCP (Model Context Protocol) server that exposes a local Homey Pro instance to LLM clients (Claude Desktop, VS Code / GitHub Copilot Chat, MCP Inspector, …).

It talks to Homey's local HTTP Web API (/api/manager/...) using a Personal Access Token, and optionally subscribes to Socket.IO realtime events.

Features

Tools:

  • ping — verify connectivity / return Homey system info
  • list_devices(zone_id?) — devices with current capability values
  • get_device(device_id) — full device object
  • list_zones — rooms / areas
  • set_capability(device_id, capability, value) — set onoff, dim, target_temperature, …
  • list_flows — all flows
  • trigger_flow(flow_id) — start a flow
  • list_recent_events(limit, kind?) — recent realtime events from the in-memory buffer

Resources:

  • homey://devices
  • homey://zones
  • homey://events/recent

Transport: stdio (default, for local LLM hosts like Javis) or streamable-http / sse (for remote MCP clients over the LAN, e.g. the Odysseus AI helper) — see Run on the LAN below.

Prerequisites

  • Python 3.10+
  • A Homey Pro on the local network
  • A Personal Access Token for the Homey Web API — create one at the Homey Developer Tools: https://tools.developer.homey.app/ (My Homey → API Keys / Personal Access Token).

Install

From this folder:

python -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install -e .

uv works equivalently:

uv venv
uv pip install -e .

Configure

Copy .env.example to .env and fill in:

HOMEY_HOST=192.168.1.10
HOMEY_TOKEN=eyJhbGciOi...your PAT...
HOMEY_SCHEME=http
HOMEY_PORT=4859
HOMEY_TIMEOUT=10
HOMEY_EVENT_BUFFER=200
HOMEY_REALTIME=true

Run

homey-mcp
# or
python -m homey_mcp
# or
.\run.bat

Inspect with the MCP Inspector

uv run mcp dev src/homey_mcp/server.py
# or
npx -y @modelcontextprotocol/inspector homey-mcp

Run on the LAN (remote MCP clients)

To let a remote MCP client on the same network (e.g. Odysseus) connect over HTTP instead of stdio, set the transport env vars and run run-lan.bat (or set them yourself and run homey-mcp / python -m homey_mcp):

HOMEY_MCP_TRANSPORT=streamable-http   # or: sse
HOMEY_MCP_HOST=0.0.0.0                # bind address (or specific LAN IP)
HOMEY_MCP_ADVERTISED_HOST=10.10.10.50 # advertised host for MCP validation (required for 0.0.0.0 bind)
HOMEY_MCP_PORT=8080
HOMEY_MCP_AUTH_MODE=none              # compatible trusted-LAN default
HOMEY_MCP_AUTH_TOKEN=<a long random secret>
.\run-lan.bat

The remote client connects to http://<this-machine-ip>:8080/mcp (streamable-http) or /sse. Streamable HTTP clients that only accept a base URL may use http://<this-machine-ip>:8080/; MCP traffic at / is forwarded to /mcp, while an ordinary browser GET returns service discovery.

Important for MCP transport over LAN: The MCP SDK validates that clients send the correct Host header. If you bind to 0.0.0.0, you must set HOMEY_MCP_ADVERTISED_HOST to your actual server IP (e.g., 10.10.10.50). If you instead bind to a specific IP, omit HOMEY_MCP_ADVERTISED_HOST and it will default to the bind address.

HOMEY_MCP_AUTH_MODE=none is the compatible mode for OAuth-negotiating MCP clients such as Odysseus, because this server is not an OAuth authorization server. Use it only on a trusted, firewall-restricted LAN. Set the mode to bearer only when the MCP client can be configured to send Authorization: Bearer <HOMEY_MCP_AUTH_TOKEN> directly; OAuth discovery and dynamic registration are not provided. Generate a token with python -c "import secrets; print(secrets.token_urlsafe(32))".

When HOMEY_MCP_AUTH_TOKEN is set, the OpenAPI REST routes always require it, regardless of the MCP auth mode.

This is independent of Javis's own connection: Javis keeps talking to homey-mcp over stdio via mcp_servers.json as before — run the LAN instance as a second, separate process for other clients.

Odysseus API integration

If Odysseus exposes integrations through its app_api tool rather than a native MCP client, import this server's OpenAPI document:

  • Schema URL: http://<this-machine-ip>:8080/openapi.json
  • Authentication: Bearer token
  • Token: the value of HOMEY_MCP_AUTH_TOKEN

The API provides reads at /api/system, /api/zones, and /api/devices, plus writes at /api/devices/{device_id}/capabilities/{capability} and /api/zones/control.

Odysseus must invoke its registered app_api tool as a structured tool call. It must not print or execute Python such as api_call(...); api_call is not a Python function and is not the registered tool name. Use this integration instruction in Odysseus:

For Homey requests, always call the app_api tool with integration="Homey".
Never write api_call(...) or place tool calls in Python/code blocks.
Use GET /api/system to check connectivity, GET /api/zones and GET /api/devices
to discover IDs, PUT /api/devices/{device_id}/capabilities/{capability} with
{"value": ...} for one device, and POST /api/zones/control with
{"zone": "...", "capability": "onoff", "value": true|false} for a room.
After the tool returns, summarize the actual result. Never claim success before
receiving a successful tool response.

Use from Claude Desktop / VS Code

Add to your MCP client config (path varies per client):

{
  "mcpServers": {
    "homey": {
      "command": "homey-mcp",
      "env": {
        "HOMEY_HOST": "192.168.1.10",
        "HOMEY_TOKEN": "your-personal-access-token"
      }
    }
  }
}

If homey-mcp is not on PATH, use the full venv path, e.g. C:\\local\\Code\\PRIVAT\\homey-mcp\\.venv\\Scripts\\homey-mcp.exe.

Notes & limitations

  • Local API only (no cloud OAuth).
  • LAN MCP transport authentication is controlled by HOMEY_MCP_AUTH_MODE. Never expose none mode beyond a trusted, firewall-restricted LAN.
  • Realtime events are best-effort — if the Socket.IO connection fails the REST tools still work. Set HOMEY_REALTIME=false to disable.
  • No admin operations (zone/user/app management) are exposed.
  • Capability values are typed as bool | int | float | str; the model picks based on the capability (onoff → bool, dim → 0..1 float, etc.).

Project layout

homey-mcp/
  pyproject.toml
  README.md
  .env.example
  run.bat
  src/homey_mcp/
    __init__.py
    __main__.py
    config.py
    homey_client.py
    server.py