Loxone Proxy
БесплатноНе проверенA zero-dependency local proxy that provides a stable, headless connection to a Loxone Miniserver's MCP Server, enabling control and monitoring of Loxone smart h
Описание
A zero-dependency local proxy that provides a stable, headless connection to a Loxone Miniserver's MCP Server, enabling control and monitoring of Loxone smart home via natural language.
README
A tiny, zero-dependency local proxy that gives Claude Desktop (or any stdio-based MCP client) a stable connection to a Loxone Miniserver's native MCP Server — with a fully headless, credential-based login (no browser, no manual OAuth click).
Loxone Gen 2 Miniservers (firmware 17.1+) can run a built-in MCP Server plugin. Connecting a local MCP client to it normally has two pain points that this proxy solves for you.
Why this exists
- The Miniserver's MCP URL is not stable. Loxone publishes the endpoint
through a Cloud "connect" service that redirects to a relay address that
rotates over time (it changes on Miniserver restarts and relay reshuffles).
If you hard-code the redirected
…dyndns.loxonecloud.com:PORT/mcpURL into a client, it breaks a while later. - Auth is interactive by default. The MCP endpoint speaks OAuth 2.1 and the official flow pops a browser login. That's awkward for an always-on client and impossible for a headless setup.
This proxy exposes a normal local stdio MCP server to Claude, and on the other side it:
- resolves the stable
connect.loxonecloud.com/<serial>/mcpentry point to the current relay, and re-resolves automatically whenever the relay moves or dies (so your Claude connection just keeps working); - performs the OAuth login headlessly using a Loxone username/password from a
local
.env(it drives the Miniserver's HTML login form directly — no browser), then caches and refreshes the token; - proxies the MCP protocol (streamable HTTP ⇄ stdio) transparently.
Features
- 🔌 Stable — hides the rotating relay address behind automatic re-resolution.
- 🤖 Headless — logs in from
.envcredentials, no browser, no clicking. - ♻️ Self-healing — re-resolves the relay and refreshes/re-issues tokens on failure, and transparently re-initializes a dropped session.
- 🪶 Zero runtime dependencies — plain Node.js (≥ 20). Nothing to build.
- 🔒 Least-privilege friendly — log in as a dedicated, restricted Loxone user;
tokens are cached with
0600permissions.
How it works
Claude Desktop ──stdio(JSON-RPC)──▶ loxone-mcp-proxy ──HTTPS(streamable MCP)──▶ Loxone relay ──▶ Miniserver
│
1) GET connect.loxonecloud.com/<serial>/mcp → 307 → current relay "entry"
2) headless OAuth on the entry:
register client → GET authorize (HTML login form)
→ POST username+password (+hidden fields) → ?code=…
→ exchange code (PKCE) → access + refresh token
3) speak MCP to the entry with the Bearer token
4) on relay death / 401 / lost session → re-resolve / refresh / re-init
A subtle but important detail: the OAuth resource advertised by the server
is only the token audience identifier — it frequently points at a different,
sometimes unreachable relay. MCP traffic is therefore sent to the reachable
connect-resolved entry, not to resource. The proxy handles this for you.
Requirements
- Node.js ≥ 20 (uses the built-in
fetch, no packages to install). - A Loxone Gen 2 Miniserver, firmware 17.1+, with the MCP Server plugin added and running (Loxone Config → Network Periphery → MCP Server).
- A Loxone user account for the assistant. Create a dedicated one with the minimum rights it needs (ideally read-only to start).
Setup
1. Get the code
git clone https://github.com/ivantichy/loxone-mcp-proxy.git
cd loxone-mcp-proxy
# no "npm install" needed — there are no dependencies
2. Configure credentials
cp .env.example .env
Edit .env:
LOXONE_SERIAL=504F94A1AE7A # your Miniserver serial (MAC without colons)
LOXONE_USER=mcp # a DEDICATED, minimal-rights Loxone user
LOXONE_PASSWORD=your-password
Finding your serial: open http://<miniserver-ip>/jdev/cfg/api in a browser
and read the snr field (e.g. 50:4F:94:A1:AE:7A → 504F94A1AE7A), or read it
in Loxone Config.
3. Verify it works
npm run login-check
Expected:
OK Authenticated & connected. Server: MCP Server 1.0.0
OK 11 tools available: control_find, control_command, system_status, ...
All good - this configuration works in Claude Desktop.
If this fails, see Troubleshooting.
4. Add it to Claude Desktop
Open Settings → Developer → Edit Config and add a server that runs this proxy
over stdio. Point it at src/index.js with an absolute path:
{
"mcpServers": {
"loxone": {
"command": "node",
"args": ["/absolute/path/to/loxone-mcp-proxy/src/index.js"]
}
}
}
On Windows, escape the backslashes:
{
"mcpServers": {
"loxone": {
"command": "node",
"args": ["C:\\path\\to\\loxone-mcp-proxy\\src\\index.js"]
}
}
}
Credentials are read from the project's .env, so you don't put secrets in the
Claude config. Fully quit and reopen Claude Desktop, then ask it something
like "what's on in Loxone?".
What Claude can do
The tools come from your Miniserver's MCP plugin and act with your Loxone user's permissions. Typical set:
| Tool | Type | Purpose |
|---|---|---|
control_find, control_describe |
read | discover controls, rooms, categories |
control_state, system_status |
read | read current values / installation status |
control_history, control_statistics |
read | historical data & aggregates |
weather |
read | Loxone weather data |
control_command, control_secured_command |
write | operate controls (lights, blinds, scenes…) |
code_run, sdk_describe |
advanced | scripted access (use with care) |
To keep the assistant read-only, either restrict the Loxone user's rights or disable the write tools in your MCP client's connector settings.
State warm-up (optional)
The Miniserver's MCP plugin (tech preview) fills its control_state table only
from state-change deltas, and it only starts collecting them once the first
state query of a server-side session epoch arrives — there is no initial
snapshot. Practical symptom: in a fresh session, "what's the temperature at
home?" returns no data until each value physically changes.
Set LOXONE_STATE_WARMUP=1 and the proxy issues one tiny control_state nudge
right after every (re-)initialize, so the Miniserver starts accumulating values
immediately at connect time instead of at your first question. By the time you
ask, slow-moving states (room temperatures etc.) have usually re-broadcast and
are present. This cannot conjure a value that has not changed or re-broadcast
yet — that part only Loxone can fix server-side — but it removes the
"assistant starts blind" effect for a long-running Claude Desktop.
LOXONE_WARMUP_SWEEP=1 additionally touches every control individually after
the nudge (one control_state per control, spaced out). Under currently
observed firmware semantics the delta subscription is global, so the sweep is
redundant — it exists as belt-and-braces for future firmware.
Security
- Use a dedicated Loxone user with the least privilege necessary. The assistant can only see and do what that user can.
- Credentials live only in your local
.env(git-ignored). Tokens are cached at~/.loxone-mcp-proxy/cache.jsonwith0600permissions. Windows note: POSIX file modes are effectively ignored on Windows — the cache is only as private as your user profile directory (NTFS ACLs), so keep the machine account personal. - Nothing is sent to any third-party cloud — the proxy talks only to Loxone's own connect/relay infrastructure and your Miniserver.
Troubleshooting
Run with verbose logging (to stderr):
LOXONE_DEBUG=1 npm run login-check # macOS / Linux
$env:LOXONE_DEBUG='1'; npm run login-check # Windows PowerShell
login was rejected (form re-rendered)— wrongLOXONE_USER/LOXONE_PASSWORD, or that user may not access this Miniserver.connect is rate-limited (HTTP 429)— the connect endpoint allows only a handful of requests per window; wait a minute. Normal operation caches the endpoint and rarely hits it.could not authenticate after N attempts— check the MCP Server plugin is added and running in Loxone Config, and that the Miniserver has external access / Remote Connect enabled.- Claude shows the server but no tools — fully quit Claude Desktop (from the
tray) and relaunch; confirm
npm run login-checkpasses.
Configuration reference
All optional, via .env or environment:
| Variable | Default | Meaning |
|---|---|---|
LOXONE_SERIAL |
— | required — Miniserver serial (MAC, no colons) |
LOXONE_USER |
— | required — Loxone username |
LOXONE_PASSWORD |
— | required — Loxone password |
LOXONE_CONNECT_BASE |
https://connect.loxonecloud.com |
Loxone Cloud connect base |
LOXONE_CACHE_PATH |
~/.loxone-mcp-proxy/cache.json |
token cache location |
LOXONE_REDIRECT_PORT |
41678 |
loopback port used only as the OAuth redirect target |
LOXONE_REQUEST_TIMEOUT_MS |
120000 |
per-request deadline for MCP calls to the relay |
LOXONE_STATE_WARMUP |
0 |
set 1 to nudge state-delta collection after each (re-)initialize |
LOXONE_WARMUP_SWEEP |
0 |
with warm-up: also touch every control individually |
LOXONE_WARMUP_DELAY_MS |
1000 |
delay between session establishment and the warm-up |
LOXONE_WARMUP_SPACING_MS |
150 |
spacing between per-control sweep calls |
LOXONE_WARMUP_MAX_CONTROLS |
500 |
sweep enumeration cap |
LOXONE_MAX_ATTEMPTS |
6 |
max authentication attempts before giving up |
LOXONE_CONNECT_MIN_INTERVAL_MS |
2000 |
min. spacing between connect-endpoint calls |
LOXONE_ENV_FILE |
— | explicit path to the .env file to load |
LOXONE_NO_DOTENV |
0 |
set 1 to skip .env loading entirely |
LOXONE_DEBUG |
0 |
set 1 for verbose stderr logging |
LOXONE_LOG_LEVEL |
info |
error / warn / info / debug (ignored if LOXONE_DEBUG=1) |
Development
npm test # unit tests (node:test, no deps)
# live integration test (needs .env + a reachable Miniserver) — opt in via env:
LOXONE_INTEGRATION=1 npm run test:integration # macOS / Linux
$env:LOXONE_INTEGRATION='1'; npm run test:integration # Windows PowerShell
Layout:
src/
index.js entry point (loads config, starts the stdio proxy)
proxy.js stdio <-> Connection bridge (newline-delimited JSON-RPC)
connection.js endpoint resolution, token lifecycle, session, recovery
loxoneAuth.js headless OAuth (register, HTML-form login, token, refresh)
resolver.js connect.loxonecloud.com -> current relay, cached
cache.js on-disk token cache
config.js .env + environment config
logger.js stderr logging (stdout is reserved for MCP)
scripts/
login-check.js standalone connectivity/credentials check
License
MIT © Ivan Tichy
Acknowledgements
Built for connecting Claude to Loxone's native MCP Server. Not affiliated with or endorsed by Loxone.
Установка Loxone Proxy
У этого сервера нет опубликованного пакета — он собирается из исходников. Открой репозиторий и следуй инструкции в README.
▸ github.com/ivantichy/loxone-mcp-proxyFAQ
Loxone Proxy MCP бесплатный?
Да, Loxone Proxy MCP бесплатный — установка в пару кликов через Unyly без оплаты.
Нужен ли API-ключ для Loxone Proxy?
Нет, Loxone Proxy работает без API-ключей и переменных окружения.
Loxone Proxy — hosted или self-hosted?
Self-hosted: сервер запускается локально на твоей машине командой из раздела установки.
Как установить Loxone Proxy в Claude Desktop, Claude Code или Cursor?
Открой Loxone Proxy на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.
Похожие MCP
GitHub
PRs, issues, code search, CI status
автор: GitHubFilesystem
Secure file operations with configurable access controls.
Memory
Knowledge graph-based persistent memory system.
Template MCP Server
A CLI tool to create a new Model Context Protocol server project with TypeScript support, dual transport options, and an extensible structure
автор: mcpdotdirectCompare Loxone Proxy with
Не уверен что выбрать?
Найди свой стек за 60 секунд
Автор?
Embed-бейдж для README
Похожее
Все в категории development
