Arcus MCP Server
No description available
Ask AI about Arcus MCP Server
Powered by Claude Β· Grounded in docs
I know everything about Arcus MCP Server. Ask me about installation, configuration, usage, or troubleshooting.
0/500
Reviews
Documentation
Arcus MCP Server
MCP (Model Context Protocol) server that connects AI agents to the Arcus Smart Home platform via the client-bridge WebSocket API.
Architecture
Claude Code <--stdio--> MCP Server <--WebSocket--> Client Bridge <--Kafka--> Arcus Smart Home Platform
- Transport: stdio for MCP, WebSocket for Arcus bridge
- Language: TypeScript (ES2022, Node16 modules)
- Dependencies:
@modelcontextprotocol/sdk,ws,zod
Configuration
| Env Var | Required | Description |
|---|---|---|
ARCUS_BRIDGE_URL | Yes | Bridge URL (e.g. https://client-bridge.example.com) |
ARCUS_USERNAME | Yes* | Login username |
ARCUS_PASSWORD | Yes* | Login password |
ARCUS_API_KEY | No | API key for direct API server connection (replaces username/password) |
ARCUS_AUTH_TOKEN | No | Skip login, use existing auth token directly |
ARCUS_ENABLE_WRITE | No | Set to 1 to enable device commands, alarm control, pairing, etc. |
ARCUS_DEBUG | No | Set to 1 to log all WebSocket traffic to stderr |
*Not required if ARCUS_AUTH_TOKEN is set.
Setup
npm install
npm run build
Claude Code integration
claude mcp add arcus -s user \
-e ARCUS_BRIDGE_URL=https://client-bridge.example.com \
-e ARCUS_USERNAME=user@example.com \
-e ARCUS_PASSWORD=password \
-e ARCUS_ENABLE_WRITE=1 \
-- node /path/to/arcus-mcp-server/dist/index.js
Or with an API key (skips login, auto-selects place):
claude mcp add arcus -s user \
-e ARCUS_BRIDGE_URL=https://client-bridge.example.com \
-e ARCUS_API_KEY=your-api-key \
-e ARCUS_ENABLE_WRITE=1 \
-- node /path/to/arcus-mcp-server/dist/index.js
To remove:
claude mcp remove arcus
Source Files
| File | Description |
|---|---|
src/index.ts | Entry point. Creates MCP server on stdio, lazy bridge connection via ensureConnected() |
src/bridge-client.ts | WebSocket/REST client. Login, correlation-based request/response, event buffering, auto-reconnect |
src/capabilities.ts | Auto-generated capability constants from Arcus Smart Home platform definitions |
src/tools.ts | All 38 MCP tool definitions (+6 admin), response summarizers, write guard, place guard, blocklist |
docs/arcus-protocol.md | Protocol reference gathered from real client traffic |
MCP Tools (38 + 6 admin)
Session & Places
| Tool | Description |
|---|---|
list_places | List all places (homes) accessible to the user |
set_active_place | Activate a place β required before any device/scene/alarm operations |
Devices
| Tool | Description |
|---|---|
list_devices | List all devices at active place (summarized) |
get_device | Get full attributes of a single device |
get_devices | Batch get β fetches multiple devices in parallel |
device_command | Send command to a device (switch, lock, dimmer, thermostat, shade, etc.) |
identify_device | Flash LED or play sound on a device to physically identify it |
search_devices | Put hub into pairing/search mode for new or reconnecting devices |
Door Locks
| Tool | Description |
|---|---|
doorlock_buzz_in | Temporarily unlock a door lock (auto-relocks in 30 seconds) |
doorlock_authorize_person | Authorize a person's PIN on a door lock |
doorlock_deauthorize_person | Deauthorize a person's PIN from a door lock |
Scenes & Rules
| Tool | Description |
|---|---|
list_scenes | List scenes at active place |
fire_scene | Execute a scene |
list_rules | List automation rules |
delete_rule | Delete a rule |
enable_rule | Enable a rule |
disable_rule | Disable a rule |
list_rule_templates | List rule template categories, or templates in a category |
resolve_rule_template | Resolve a template's variables to valid device/person options |
create_rule | Create a rule from a template with variable mappings |
Alarm
| Tool | Description |
|---|---|
arm_alarm | Arm alarm (ON=full, PARTIAL=perimeter). Supports bypass for triggered devices |
disarm_alarm | Disarm alarm |
list_incidents | List alarm incidents |
Infrastructure
| Tool | Description |
|---|---|
get_hub | Get hub status (model, firmware, connection state, battery, Z-Wave/Zigbee info) |
reboot_hub | Reboot the hub |
list_subsystems | List subsystems (alarm, safety, care, etc.) |
zwave_network_info | Get Z-Wave network info including node metrics, neighbors, routing, and zombies |
zwave_heal | Start a Z-Wave network heal |
zwave_cancel_heal | Cancel a Z-Wave network heal in progress |
zwave_remove_zombie | Remove a zombie node from the Z-Wave network |
zigbee_network_info | Get Zigbee network information |
zigbee_get_stats | Get Zigbee radio statistics |
zigbee_scan | Scan the Zigbee network for devices and channel information |
Events & Monitoring
| Tool | Description |
|---|---|
list_events | Drain buffered platform events. Filters out subcare/subsafety noise, groups consecutive duplicates |
list_care_status | Peek at care/safety events without draining. Shows latest unique per type |
list_history | List recent history entries from the platform |
list_persons | List persons at the active place |
Advanced
| Tool | Description |
|---|---|
send_message | Escape hatch β send any message type to any destination |
Admin (ARCUS_ENABLE_ADMIN=1)
| Tool | Description |
|---|---|
hub_syslog | Get hub system log |
hub_bootlog | Get hub boot log |
hub_processes | Get running processes on the hub |
hub_load | Get system load on the hub |
hub_agent_db | Get hub agent database |
hub_files | Get file listing from the hub |
Safety Guards
Write Guard
All mutating operations require ARCUS_ENABLE_WRITE=1. Without it, device commands, alarm control, scene firing, rule creation/deletion, hub reboot, and pairing are blocked.
Place Guard
Tools that operate on a place (list_devices, get_device, get_devices, device_command, list_history, list_persons, delete_rule, fire_scene, get_hub, reboot_hub) check that a place is set before making any bridge requests. This prevents "Tsk Tsk, you are not authorized" errors that trigger security alerts on the backend.
Blocklist
18 destructive message types are blocked in both device_command and send_message:
- Account/place/person deletion and removal
- Hub deregistration and factory reset
- Device removal (normal and forced)
- Scene/rule deletion (via
send_messageβ dedicateddelete_ruletool exists) - Password/PIN changes
Key Design Decisions
- Lazy connection: Bridge connects on first tool call, not at startup. This avoids blocking MCP stdio transport during login/WebSocket handshake.
- Response summarizers: Every list tool extracts only the useful fields from raw platform responses to minimize token usage. For example,
list_devicesreturns name, address, type, vendor, model, connection state, and capability-specific state (switch, lock, temperature, etc.) instead of 50+ raw attributes per device. - Compact JSON: All tool responses use
JSON.stringify(x)(no pretty-print) except where readability matters (set_active_place,get_device). - Event buffer: Unsolicited WebSocket messages are buffered (max 100).
list_eventsdrains and groups them.subcare:/subsafety:events are filtered to a separatelist_care_statustool since they fire constantly. - Auto-reconnect: WebSocket reconnects with exponential backoff (1s, 2s, 5s, 10s, 30s). On reconnect, the active place is automatically restored.
- Parallel requests:
set_active_placeruns the two-phase connection flow (SetActivePlace + GetAttributes in parallel, then GetHub + ListSubsystems in parallel).get_devicesfetches all requested devices in parallel.
Device Command Examples
All device commands use base:SetAttributes:
# Turn on a switch
device_command(addr, "base:SetAttributes", {"swit:state": "ON"})
# Lock a door
device_command(addr, "base:SetAttributes", {"doorlock:lockstate": "LOCKED"})
# Set thermostat
device_command(addr, "base:SetAttributes", {"therm:heatsetpoint": 72})
# Dim a light to 50%
device_command(addr, "base:SetAttributes", {"dim:brightness": 50})
# Set shade position (0=closed, 100=open)
device_command(addr, "base:SetAttributes", {"shade:level": 75})
Protocol Notes
See docs/arcus-protocol.md for the full protocol reference. Key gotchas:
SessionCreatedmessage type has nosess:prefix- Place field is
placeName(notname) in SessionCreated - Outgoing messages need a top-level
typefield mirroringpayload.messageType - No
sourcefield in outgoing headers - Hub address format:
SERV:<hubId>:hub(e.g.SERV:LWH-7138:hub) - Scenes/rules use service destinations (
SERV:scene:,SERV:rule:) withplaceIdin attributes - To arm alarm with triggered sensors, use
subalarm:ArmBypassedinstead ofsubalarm:Arm - Pairing:
subpairing:StartPairingthensubpairing:SearchtoSERV:subpairing:<placeId>
