Skip to main content

Myro:Home Helper MCP server

Lets an AI assistant (Claude Desktop, Claude Code, ChatGPT desktop, anything that speaks MCP) read and control an HAI / Leviton Omni controller, a NESS / ELK M1 panel, a Savant system (preview), or a Control4 system through Control4 Link (preview, Helper 5.50), through Myro:Home Helper, using the Helper's HTTP API. The assistant sees typed tools with descriptions instead of guessing URL shapes.

What you need

  • Myro:Home Helper (Mac App Store) 4.06 or later on a Mac on your network (4.07 or later for the read tools: list_objects, get_object, helper_log).
  • An API key for your controller: Helper → API tab → Generate.
  • uv on the machine running the assistant (brew install uv or the one-line installer). uvx fetches and runs this server on demand and keeps it updated.

NESS / ELK

Helper 5.0 adds NESS / ELK M1 panels alongside HAI / Leviton Omni. The tools and their parameters are the same for both; controller_status reports controllerFamily ("HAI / Leviton" or "NESS / ELK", derived from the controller's protocol), and the live scripting_reference is scoped to that family, so the assistant should read it before writing scripts. On ELK, user codes may be 4 or 6 digits (security-code set accepts either), there is no energy-cost level, and audio is a legacy M1XEP integration.

Savant and Control4 are room and activity systems, not alarm panels. They have no zones, units, arming or panel messages, so the panel tools (set_unit, arm, set_thermostat and the rest) do not apply to them.

  • controller_status reports controllerFamily "Savant" or "Control4", plus backend, rooms, roomStates, inventory, homeKit, objectCounts and capabilities. Unknown room fields are omitted rather than guessed.
  • Automate them through scripts. Read scripting_reference first (it is scoped to the selected controller and lists the real rooms, activities and services), then validate_script and save_script (saved disabled). Savant scripts use MyroSavant; Control4 scripts use MyroControl4. Saving and enabling need an API key with remote script management.
  • Sign-in credentials for either system live only in Helper's Connection pane, never in MCP or a conversation.

Compatibility

Adapter Needs Helper
0.8.0 timeline, timeline_note, timeline_moment 5.50 or later
0.7.0 list_favorites, list_doorbells, web_capabilities, suggestions 5.50 or later (other tools keep their own minimums above)
0.6.0 Pro 2.51 message, beeper, scene and lock tools 5.01 or later
0.5.0 typed /control tools 4.07 or later (relative controls: 4.50)
0.4.0 history and panel events 4.50 or later

A tool that needs a newer Helper than the one running answers with requiredHelper instead of failing silently.

Configure

Claude Desktop (claude_desktop_config.json) or any client that takes the standard MCP config:

{
  "mcpServers": {
    "myrohome-helper": {
      "command": "uvx",
      "args": ["myrohome-helper-mcp"],
      "env": {
        "MHH_URL": "http://192.168.1.76:9393",
        "MHH_API_KEY": "your-api-key"
      }
    }
  }
}

Claude Code:

claude mcp add myrohome-helper -e MHH_URL=http://192.168.1.76:9393 -e MHH_API_KEY=your-api-key -- uvx myrohome-helper-mcp

The controller ID is fetched from the Helper automatically. Set MHH_CONTROLLER_ID only if you want to pin it.

Tools

Read:

Tool What it returns
helper_info Helper version and identity, and which controller the key is for
controller_status Name, model, firmware, connection, power, battery, phone line, energy cost, troubles, controllerFamily
controller_property(name) One controller property
list_objects(type?) Every object with decoded state; filter by Zone, Unit, Flag, Output, Thermostat, Auxiliary Sensor, …
get_object(type, number) One object; for a door lock, its locked state and the reader's last access
helper_log(lines) The Helper's recent log lines
ethernet_quality(since?) The controller connection's health record
list_favorites(resolve?) Helper 5.50+: the objects starred in Helper's web control (shared by every signed-in browser), matched to their names and current state
list_doorbells Helper 5.50+: the zones, flags and outputs marked "Treat as doorbell" in the web control, with their current state
web_capabilities Helper 5.50+: which web-control and Apple TV features (favorites, doorbells, history, Timeline, Apple TV pairing, UniFi Protect cameras and camera events, Savant activities) Helper offers for this controller, and the Helper version
suggestions(kind?, home?, at?, limit?, compose?) Helper 5.50+: the household's "Right now" list, the shared favorites first and then the things people in this home usually do at about this time on a day like today, ranked from the taps Myro:Home Pro and the Apple TV share with Helper, with object, name, room, suggested action, score, favorite, state, reasons, why and last use; limit 1 to 24, compose: false for the plain ranking (up to 12). Read-only; a confirm: true entry is a security action and only a suggestion
timeline(hours?, kind?) Helper 5.50+: the home Timeline for the last 1 to 24 hours (default 8) as the browser control, Myro:Home Pro and the Apple TV show it: headline, moments (arrivals, departures, doorbell rings, alarms, scenes, music, busy rooms, named moments), events with their source (and approximate: true on a light the panel changed quietly), flags, gaps and the current security, lights and open doors; kind keeps only events of those kinds. Never pictures; the per-room drawing data is left out. Read-only
connection_status Helper 4.07+: live connected/reconnecting state and the panel messages showing now
list_logged_sensors Which sensors record history, with the type and number
sensor_history(type, number, points) Logged readings for one sensor or thermostat
history_window(type, number, start, end, points, remove_outliers, runtime_bucket, time_zone) Helper 4.50+: bounded live/archived samples, statistics before display reduction, and hourly/daily/weekly reported HVAC intervals with unknown coverage and archive warnings
panel_events(...) Helper 4.50+: cached panel history with zone/area/type/month/day filters and user attribution
refresh_panel_events(scope) Helper 4.50+: recent history by default; explicit all reads up to 2000 available panel records. Poll panel_events while refreshing is true; check panelEndReached and refreshError before claiming completeness

Door access (HAI / Leviton)

An access-control reader and the lock it releases share one number. list_objects("Access Control Lock") and get_object("Access Control Lock", n) return locked and, once the reader has reported, the last access:

Field Meaning
lastAccessGranted true granted, false denied
lastAccessUser Omni user number: 0 none, 251 Duress, 252 Keyswitch, 253 Quick Arm, 254 PC Access, 255 Programming
lastAccessBy Added by this server: that number in words ("user 7", "Duress", "none")
lastAccessAt When Helper received the reader status (ISO 8601)

Access Control Reader objects carry the same result as granted, lastUser and lastAccessAt. The panel does not timestamp accesses, so lastAccessAt is "last reported", not necessarily the moment of the swipe. Helper 5.01 and later read reader status at startup and on every status refresh; older Helpers report it only after the next badge or keypad code. User codes are never exposed. Reading door access is a read: it adds no write tool, and unlocking stays behind the owner opt-in below.

The new history/activity tools require adapter 0.4.0 and Helper 4.50. Panel event dates contain no year; receivedAt is download time, not event time. History indexing is incremental: retry when indexing is true. HVAC intervals are estimates from reported action, and unknownSeconds must not be interpreted as equipment being off. These additions do not change the existing security tools. Recent event refreshes are limited to once every 30 seconds per controller; full downloads to once every 10 minutes. A 429 means wait and use the cached panel_events result, not repeat the download immediately.

Write (each changes the physical home; tool descriptions tell the assistant to confirm first):

Tool Effect
set_unit(number, value, timer?) 0 off, 1 or 100 on, 2–99 dimmer level; optional timer 1–99 s for on/off
set_blind(number, value, timer?) Blind/shade 0–100
set_flag(number, value, timer?) Flag to 0–255; optional timer 1–99 s for 0/1
increment_flag(number) / decrement_flag(number) Updated Helper 4.50+: one native counter step, without cached read/modify/write
dim_unit(number, steps?) / brighten_unit(number, steps?) Updated Helper 4.50+: 1-9 native lighting steps (default 1), not percentage points
set_output(number, on, timer?) Output relay on or off; optional timer 1–99 s
set_thermostat(number, mode?, heat_setpoint?, cool_setpoint?, humidify_setpoint?, dehumidify_setpoint?, fan?, hold?) Mode off/heat/cool/auto/emergency, setpoints, fan auto/on, hold
set_area_lights(on, area) All lights in an area on or off (area 0 = all)
run_button(number) Run a controller button (macro)
set_upb_link(number, state) UPB link on / off / store
blink_upb_unit(number, stop?) Helper 5.01+: blink a UPB light for 30 s at 1 s to find it, or stop it (UPB units only, HAI / Leviton)
say_panel_message(number) / log_panel_message(number) Helper 5.01+: speak a programmed message, or write it to the event log (HAI / Leviton)
set_keypad_beepers(operation) Helper 5.01+: keypad beepers on / off, or stop (silence now)
press_radiora2_phantom(number) Helper 5.01+: press a RadioRA 2 phantom button by number
set_leviton_scene(number, state) Helper 5.01+: Leviton scene on / off / set
lock_all_doors() Helper 5.01+: lock every door (there is no unlock-all tool)
show_panel_message(number, presentation) Show a programmed message on the keypads: beep_led / led / silent
clear_panel_message(number) Clear one message, or 0 for all
lock_door(number) Lock an access-control lock (unlocking is opt-in, below)
set_user_setting(number, value) User setting 1–255 to a raw value 0–65535
set_energy_cost(level) low / medium / high / critical (HAI / Leviton only)
send_notification(message) Push to the Myro:Home apps
send_test_notification The Helper's test push, to check delivery
speak(message) Speak on the Mac
log_message(message) Write to the Helper log
log_to_file(filename, message) Append to a file in the Helper's Logs folder
sync_now Re-sync from the controller

Adapter 0.5.0 adds typed /control tools for blinds, thermostats, area lights, buttons, UPB links, messages, locks, user settings and audio transport, plus timers on units, flags and outputs (Helper 4.07 or later). Existing untimed unit/flag/output, audio, energy, notification, speech, log and sync tools retain their existing routes. Timed dim levels, intermediate blind positions and flag counters are rejected because the panel ignores their timer. Thermostat setpoints use the controller's temperature format; Helper enforces that format's range. A controller ACK means acceptance, not physical completion. After an error or timeout, read the state before considering another write; commands are never automatically retried.

Timeline notes (Helper 5.50+; a note is a line in the home Timeline, not a physical action: it never notifies, never takes a picture and never sends a command):

Tool Effect
timeline_note(title, kind?, object?, room?, at?, importance?, detail?) One note in the Timeline with source: "api": a title of up to 80 characters, filed under an event kind (note by default), optionally about one object (an id such as Unit:12 or a name that matches one object), in a room, at an ISO 8601 time within the last 72 hours, with importance 0, 1 or 2 and up to 200 characters of detail
timeline_moment(title, symbol?, tone?, objects?, start?, end?, detail?) A named moment card with exactly this title, an SF Symbol (sparkles by default), a tone (info, good, warn, alert), the objects it covers and an optional start and end (default now and open)

Helper allows 120 notes and moments an hour per API key (429 past that) and refuses a bad value with one sentence (400). The tool descriptions tell the assistant to say what it wrote. Notes cannot be changed or deleted through MCP, and the scripting rules that quiet or rename automatic Timeline events (MyroTimeline.mute, rename, mode) have no MCP form; a script saved with save_script can set them.

Scripts (save, enable and reload need a key with remote script management enabled; listing, reading and validating do not):

Tool What it does
list_scripts Every script: name, id, enabled, schedule
get_script(identifier) One script's full source
scripting_reference(compact) The live scripting API, with your real device names
validate_script(code) Syntax and warnings, without running it
save_script(name, code, script_id, enabled) Create or replace; disabled by default
set_script_enabled(identifier, enabled) Enabling runs the script immediately
reload_scripts Re-runs every enabled script

Helper 4.50 relative controls

Adapter 0.5.0 adds the four relative tools above, requiring an updated Helper 4.50 build with these actions. Earlier 4.50 builds may not support them. Discover the exact Flag or Unit number first. They validate input locally and use the authenticated typed control endpoint; the Helper also checks that the object has the right type. Each counter call requests one step. Lighting steps are not percentage points; device support and resulting levels depend on the panel and lighting technology. The panel defines behavior at counter endpoints 0/255. Flags can trigger panel programs, so confirm intent before changing them.

No automatic retries: an ACK timeout may mean the command already applied. accepted means the panel acknowledged it, not that a particular final value was observed. Check reported state after uncertainty. These additions do not expand security permissions. Older Helpers return explicit failure with an updated 4.50 build requirement; the adapter never substitutes a cached-value write.

Helper 4.50 scripting features

The live scripting_reference exposes MyroLibraries, MyroControllers, and MyroSystem.speakQueued / cancelSpeech / cancelAllSpeech. MCP can generate, validate and save scripts using these APIs through the existing script tools; it does not need a separate tool for every JavaScript method.

Library files must be installed locally in Helper's Scripts/Libraries folder. Cross-controller access requires local Send To and Accept From grants at the respective controllers. MCP cannot upload library files, change grants, or silently switch its controller API key. A grant extends the origin scripts' authority, including remotely managed scripts, so enable it only deliberately. Validation checks the script body without loading dependencies or proving permissions, device state or speech playback. Save disabled and review before enabling. Script-owned speech cancellation does not cancel the separate HTTP speech queue used by MCP's speak tool.

Browser login, themes, live page navigation, Apple TV pairing, doorbell marking, the home history, the Timeline (and its kept doorbell and camera pictures) and UniFi Protect camera setup and events are UI and browser-session features, not MCP tools: they are served under /helper/web/* for a signed-in browser, or under /helper/timeline for a paired app's session token, and the MCP API key cannot use them. MCP reads only the results an API key can reach: list_favorites, the doorbell field that list_objects and get_object carry on marked zones, flags and outputs (list_doorbells filters to them), web_capabilities, which reads the public controller list the web control and Myro:Home Pro for Apple TV use (no sign-in; only this controller's entry is returned), suggestions, the household's usage-ranked "Right now" list (GET /helper/{controllerID}/suggestions; the usage events themselves, their upload and their deletion stay with the paired apps and the browser's Clear usage history), and since 0.8.0 the Timeline itself through its keyed routes: timeline reads GET /helper/{controllerID}/timeline (moments and events, never the pictures) and timeline_note and timeline_moment write through POST /helper/{controllerID}/timeline/notes. UniFi Protect sign-ins never pass through MCP. History queries include archived data automatically; archive deletion policy remains local configuration, not an MCP write capability.

Audio, Lutron and displays:

Tool What it does
list_audio_sources Sources and their cached metadata
audio_source_metadata(source, refresh) What one source is playing
set_audio_zone(zone, power, volume, mute, source) Control a zone
audio_zone_key(zone, transport or key) Russound transport (play, pause, next, …) or a raw audio key 1–40
list_lutron Bridges, devices and Picos
set_lutron_level(bridge_id, level, ...) Set a Lutron device 0-100
activate_lutron_scene(bridge_id, scene_href) Activate a scene
press_lutron_button(bridge_id, integration_id, component) Press a keypad or Pico button
list_displays Vestaboards and LaMetric clocks
`send_to_vestaboard(text lines
send_to_lametric(text, ...) Show a notification on a LaMetric
sync_clock Set the controller's clock from this Mac

Helper Mac:

Tool What it does
beep System beep on the Helper Mac
show_mac_alert(message) Alert dialog on the Helper Mac
set_speech_delays(start_delay_ms, between_delay_ms) Tune the speech queue
play_sound(filename, queue_with_speech) Play a sound from the Helper's Scripts folder
stop_sound(filename) Stop it

Security (all three need an API key with arm/disarm enabled; arm also needs a panel code stored locally):

Tool Effect
arm(mode, area) day, night, away, vacation, day_instant, night_delayed
bypass_zone(zone, bypassed, area) Bypass or restore one zone
restore_all_zones(area) Restore every bypassed zone

arm stays disabled until the owner stores a panel code on the machine running this server. bypass_zone and restore_all_zones work without one on Helper 4.13 or later, running as the panel's Programmed user; with a stored code they run as that user instead. To store or remove the code:

uvx myrohome-helper-mcp security-code set      # prompts; nothing is echoed
uvx myrohome-helper-mcp security-code delete

The code goes into the operating system credential store (macOS Keychain, Windows Credential Locker, Linux Secret Service) under the controller's identity. It is never placed in the MCP config, an environment variable, or a conversation, and it is read only when a security tool is actually called. Helper validates it against the panel itself.

Disarming and unlocking (off by default)

An assistant cannot turn the alarm off or unlock a door unless you allow it, on the computer running this server:

uvx myrohome-helper-mcp allow disarm        # adds the disarm tool
uvx myrohome-helper-mcp allow unlock        # adds the unlock_door tool
uvx myrohome-helper-mcp disallow disarm     # takes it away again

Each asks you to type the word to confirm, and applies only to the controller that API key belongs to. Restart your MCP client afterwards. Until you allow them, the tools are not registered at all, so an instruction hidden in an email, web page or document the assistant reads has nothing to call. Disarm still also needs an API key with arm/disarm enabled and a stored panel code. Revoking takes effect on the next call, without a restart.

AI assistants can be misled by text they read. Allow these only if you understand that, and prefer the Myro:Home app for disarming.

Security

This server runs on your LAN like every other Myro:Home client and holds one controller's API key. Anyone who can run the assistant with this config can do what the key allows. Keep it on trusted machines. The Helper's HTTP API is plain HTTP on the local network; do not expose port 9393 to the internet.

Developing

uv sync
MHH_URL=http://192.168.1.76:9393 MHH_API_KEY=... uv run myrohome-helper-mcp   # stdio server
uv run mcp dev src/myrohome_helper_mcp/server.py                             # MCP inspector

Releasing

Bump version in pyproject.toml and __init__.py, commit, then tag and push: git tag v0.1.0 && git push origin v0.1.0. The GitLab CI job builds and publishes to PyPI through trusted publishing (one-time setup: PyPI project -> Publishing -> add GitLab publisher MyroControl/myrohome-helper-mcp, environment pypi).

MIT licensed. Myro Control, LLC.

Metadata

Release files for myrohome-helper-mcp 0.8.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for myrohome-helper-mcp 0.8.0
File Size Uploaded Provenance Actions
myrohome_helper_mcp-0.8.0.tar.gz 111.9 kB Without provenance Details for myrohome_helper_mcp-0.8.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for myrohome-helper-mcp 0.8.0
File Interpreter ABI Platform Actions
myrohome_helper_mcp-0.8.0-py3-none-any.whl Python 3 none any Details for myrohome_helper_mcp-0.8.0-py3-none-any.whl

Total release size: 150.6 kB

Release files / myrohome_helper_mcp-0.8.0.tar.gz

Download URL myrohome_helper_mcp-0.8.0.tar.gz
Size 111.9 kB
Tags Source
SHA-256 checksum
How to use checksums
066b62fb6bd9394701ce44dc5f2497bb10cb23921a58222e314fab2e2e6c73a2
BLAKE2b-256 checksum
How to use checksums
bc0e3d66de941cb4945afd89c97f1a692ebcd41fad2447fa0d72cea3e9bf2f8a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.9.30 {"installer":{"name":"uv","version":"0.9.30","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / myrohome_helper_mcp-0.8.0-py3-none-any.whl

Download URL myrohome_helper_mcp-0.8.0-py3-none-any.whl
Size 38.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c1b7e32eebb5ff7d706e9d3f7fa17d4ced5abd98e4a19c38c6049d61d394957d
BLAKE2b-256 checksum
How to use checksums
4810a966e1471970a6866e3234b1b9e3f9dd04cd0400bac2dfa826309fb096b5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.9.30 {"installer":{"name":"uv","version":"0.9.30","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for myrohome-helper-mcp 0.8.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page