Skip to content

v3.0.0

Choose a tag to compare

@mp-consulting mp-consulting released this 04 Oct 23:58
· 7 commits to main since this release
43494c0

Breaking

  • set_accessory refuses lock, garage door and security system targets; use the new destructive set_security_accessory tool, which asks for confirmation.
  • get_config's includeSecrets is opt-in (HOMEBRIDGE_ALLOW_SECRETS, or the allowSecrets option for createServer / runHttpServer) and never available in read-only mode.
  • RegisterTools takes a third options argument, and write tools declare a token scope.
  • The default OpenAI model is gpt-6.1-sol (over the Responses API) and the default Gemini model gemini-3.8-flash.

Added

  • OpenAI through the Responses API (from ai-core): the openai provider calls /responses with store: false, which newer OpenAI models need for tool calling, and replays their encrypted reasoning in agent loops. The new openaiApi setting (responses | chat, in config.schema.json) switches back to Chat Completions for proxies or local servers that only speak it (openai-compatible keeps Chat Completions by default). The effort setting now also applies to OpenAI (reasoning.effort).
  • Assistant requests are retried when the provider is busy, rate limits them or can't be reached (from ai-core): new maxRetries setting (default 2, 0 turns it off) in config.schema.json and the README.
  • Claude prompt caching and effort (from ai-core): agent loops reuse the cached tools, system prompt and conversation, and the new effort setting (config.schema.json, Claude only) controls how much Claude thinks. Costs now price cache reads and writes correctly.
  • Usage tracking that survives restarts, with daily / monthly totals and optional token or USD budgets (UsageTracker, JsonFileUsageStore, trackUsage, from ai-core).
  • ./mcp also exports normalizeFingerprint and pemFingerprints, next to createTrustedFetch, so apps can pin the Homebridge UI certificate without their own copy.
  • Server helpers from ai-core, re-exported from .: SlidingWindowRateLimiter, TtlCache, withConfirmTimeout, ConfirmationBroker, redactPairing, readLogTail, tailLines, stripAnsi. The homebridge://logs/recent resource uses ai-core's ANSI stripping, which also removes cursor and erase codes.
  • Config safety. update_config and patch_config take dryRun: true, which returns what would change without writing: a list of changed JSON paths and a unified diff of the pretty-printed file, both with secrets redacted. Every real write now names the config.json backup the Homebridge UI made of the previous file (both Homebridge UI and Glass UI copy config.json to backups/config-backups before each save, so no local store is needed), with the restore_config call that undoes it.
  • New MCP tools list_config_backups (read-only, GET /api/config-editor/backups) and restore_config (destructive; reads GET /api/config-editor/backups/:id and saves it, so the replaced file is itself backed up; supports dryRun).
  • New MCP tools create_backup and list_backups: create a full instance backup in the UI's backup directory (POST /api/backup) and list those backups (GET /api/backup/scheduled-backups). A UI without these routes gets a clear "requires Homebridge Glass UI" error.
  • New MCP tool set_accessories: set one characteristic on many accessories at once, picked by uniqueIds or by the list_accessories filters (room, type, name, manufacturer, excludeManufacturer). Each value is checked per accessory like set_accessory; dryRun previews current → new value per target; the result lists each target's outcome and the skipped ones with the reason. At most 25 targets unless maxTargets (up to 200) is raised. Lock, garage door and security system targets (LockTargetState, TargetDoorState, SecuritySystemTargetState) are refused and pointed to set_accessory.
  • Scenes (Homebridge Glass UI): list_scenes, run_scene, save_scene. run_scene takes a scene id or name (POST /api/scenes/:id/run) and returns the result per action; a scene that changes a lock, garage door or security system is refused (apply those actions with set_security_accessory, which asks the user, or run the scene in Glass UI). save_scene captures the current writable values of the chosen accessories (optionally only some characteristics; never lock/door/alarm states, Identify or names) and creates the scene with POST /api/scenes, with a dryRun preview.
  • New MCP tool get_child_bridge_health (Glass UI, GET /api/status/homebridge/child-bridges/health): status, uptime, restart and crash counts and crash-loop detection per child bridge, optionally for one deviceId.
  • New MCP tool send_test_notification (Glass UI, POST /api/notifications/test): send a test message to one notification channel or every enabled one.
  • search_logs filters: since / until (ISO, or a duration back from now such as 30m, 1h, 2d), a minimum level (error, warn, info, debug, read from the colours Homebridge's logger writes, so the log is fetched with colour=yes when it is used; falls back to the words in the line), plugin (the [Prefix] after the timestamp) and context (lines around each match, grep -C style). Lines without a timestamp, such as stack traces, belong to the entry above. pattern is now optional when a filter is given.
  • MCP resource templates homebridge://accessory/{uniqueId}, homebridge://plugin/{name} and homebridge://child-bridge/{id}, each listed in resources/list (a Homebridge error lists nothing rather than failing the list) and with completion for its variable. Child bridges never include pairing codes.
  • MCP prompts troubleshoot-device, nightly-health-check and scene-builder: guided workflows over the tools (device state → plugin → child bridge health → logs; a read-only health report; a scene proposed, confirmed, applied with set_accessories and saved with save_scene).
  • Structured tool output. list_accessories, get_accessory, list_plugins, list_child_bridges, get_child_bridge_health, get_homebridge_status, get_server_status, search_logs and list_scenes declare an outputSchema and return structuredContent (lists wrapped as { accessories: [...] }, { plugins: [...] }, …; search_logs gives { total, shown, truncated, matches: [{ line, time, level, plugin, text }] }). The text block keeps the JSON these tools always returned. Schemas are loose so extra fields from newer Homebridge UIs pass.
  • Server-side confirmation through MCP elicitation. When the connected client advertises form elicitation, every destructive tool (destructiveHint: true) asks the user to confirm before it runs, showing its arguments with secrets redacted. Declined, cancelled or failed confirmations return an error and nothing runs; dryRun calls are not asked. Clients without elicitation (including runAgent, which keeps its confirm callback) behave as before. On by default; HOMEBRIDGE_ELICITATION=false or createServer(client, { elicitation: false }) turns it off.
  • HomebridgeClient throws a HomebridgeApiError (with status, method, path, body and missingRoute) for non-2xx answers, same message as before; requireGlassUi() turns a missing route into a readable error.
  • Scoped client tokens. Besides the main client token (still full access), the HTTP MCP server takes more tokens, each read (read-only tools), control (plus set_accessory / set_security_accessory) or admin (everything): clients option, mcp.http.clients ({ name, token, scope }), or HOMEBRIDGE_AI_MCP_TOKENS=read:abc,control:def for the CLI. A session belongs to the token that opened it (403 for another token). Tools declare the scope they need with a new scope field in their config (write tools default to admin); createServer takes scope.
  • Read-only HTTP from the plugin. mcp.http.readOnly caps every client token at read; the plugin passed no read-only setting before.
  • Audit log of write tool calls: one JSON object per line with time, tool, arguments (secrets redacted with redactSecrets), result (ok / error), MCP session, client name, token name and scope. The plugin writes it to <Homebridge storage>/homebridge-ai-kit-audit.jsonl by default (mcp.http.auditLog, mcp.http.auditLogPath); the CLI with HOMEBRIDGE_AI_AUDIT_LOG=<path>. It rotates at 5 MB, keeping three old files. ./mcp exports createAuditLog(), and createServer / runHttpServer take any audit sink.
  • The plugin's settings page has switches for read-only and the audit log, the audit log path and the allowed browser origins (scoped tokens are edited in the JSON config).

Changed

  • The settings page uses @mp-consulting/homebridge-ui-kit 1.3: lib/theme-boot.js applies the theme before first paint and MpKit.Theme.init() follows the Homebridge setting (its own theme script is gone), and only the minified kit files are copied (mp-ui-kit-copy --only).
  • Depends on @mp-consulting/homebridge-ai-core ^2.2.0.
  • The default OpenAI model is gpt-6.1-sol (was gpt-5, whose snapshot OpenAI shuts down on 2026-12-11), in ai-core, the settings page, config.schema.json and the README.
  • The default Gemini model is gemini-3.8-flash (was gemini-2.5-pro, which Google now limits to projects that already used it), in ai-core, the settings page and config.schema.json.
  • update_config no longer echoes the Homebridge UI's answer, which is the saved file with its secrets; it returns a short confirmation instead.
  • HTTP sessions expire. A session with no request for 30 minutes is closed (sessionIdleMs, HOMEBRIDGE_AI_MCP_SESSION_IDLE_MINUTES), and at most 32 stay open (maxSessions, HOMEBRIDGE_AI_MCP_MAX_SESSIONS); the least recently used idle session makes room for a new one. Sessions with an open stream are never idle.
  • One change feed for all HTTP sessions. Sessions subscribed to the same resource now share a single socket.io connection (or poller) to Homebridge instead of opening one each. ./mcp exports shareLiveSource().
  • Behaviour changes for clients: set_accessory now refuses locks, garage doors and security systems (use set_security_accessory), and get_config only offers includeSecrets with HOMEBRIDGE_ALLOW_SECRETS. Library callers of createServer / runHttpServer must pass allowSecrets: true to keep returning secrets.
  • Needs the unreleased @mp-consulting/homebridge-ai-core changes in this workspace (new mcp.http settings and the base prompt rule); release ai-core first and raise the dependency.
  • Log text is cleaned with ai-core's stripAnsi (all escape codes, not just colours).
  • Tests cover the MCP prompts, the CLI's env parsing (stdio.ts) and the custom UI server (homebridge-ui/server.js).

Fixed

  • The settings page follows your Homebridge theme. It applied the system's light/dark preference (after hard-coding dark in the markup) and ignored the Homebridge user setting; it now applies the user's light, dark or auto setting (homebridge.getUserSettings() where available, else userCurrentLightingMode()), following the system in auto mode and when it changes.
  • The settings page no longer loads lib/ai.css on top of lib/kit.css, which already contains the Assistant components, and its theme script and styles moved from inline blocks into same-origin files (js/theme.js, css/app.css) so they work under the Homebridge UI's content-security policy.

Security

  • One rule for locks, garage doors and alarms. set_accessory, set_accessories, run_scene and save_scene share one check (isSecurityWrite(): the lock / door / alarm characteristics, or any characteristic of a LockMechanism, LockManagement, GarageDoorOpener or SecuritySystem accessory) and point to set_security_accessory, the only tool that writes them; it is destructive, so MCP clients, server-side elicitation and runAgent all ask the user. run_scene no longer takes confirm: true for such scenes: a flag the model sets is not the user's consent.
  • Token scopes cover the new tools: set_accessories and run_scene need control; save_scene, restore_config, create_backup, send_test_notification and the config writes (dry runs included) need admin.
  • The audit log records declined confirmations (notConfirmed: true, from MCP elicitation or runAgent's confirm), and runAgent takes an audit sink (principal agent).
  • The homebridge://logs/recent resource and search_logs' text are marked as untrusted data; structuredContent stays raw.
  • Unlocking a door now needs the user's consent. set_accessory is non-destructive, so MCP clients and runAgent never asked before it unlocked a lock, opened a garage door or disarmed an alarm. Those writes (LockTargetState, TargetDoorState, SecuritySystemTargetState, and any characteristic of a LockMechanism, LockManagement, GarageDoorOpener or SecuritySystem service) now go through the new set_security_accessory tool, annotated destructiveHint: true, and set_accessory refuses them with a pointer to it. A separate tool rather than a per-call check keeps the MCP annotations truthful for every client, not just runAgent; light and switch writes still don't prompt. 43 tools in all, with the other tools added in this release.
  • Read-only mode no longer hands out secrets. get_config's includeSecrets returned real passwords and tokens even with HOMEBRIDGE_READ_ONLY. It now only exists when the server opts in with HOMEBRIDGE_ALLOW_SECRETS=true (allowSecrets for createServer / runHttpServer), and never in read-only mode; otherwise the parameter is gone and secrets stay redacted. runAgent never allows it.
  • Prompt-injection hardening. Homebridge-sourced free text (get_recent_logs, search_logs, get_plugin_changelog) is wrapped in <untrusted-data source="…"> delimiters, and runAgent wraps every tool result it sends to the model the same way (the toolCalls it returns keep the raw text). A delimiter inside the data is defused so it can't close the block early. The shared base system prompt (PROMPTS.base, from ai-core) now says tool output is untrusted data, never to follow instructions in it, and to change devices, config or plugins only when the user asked.
  • The HTTP MCP server checks the Origin header, as the MCP Streamable HTTP spec requires, so a web page can't reach it through DNS rebinding. Requests without Origin (desktop clients) are unaffected; browser requests must come from a loopback origin, the server's own IP address, or an origin listed in the new allowedOrigins option (HOMEBRIDGE_AI_MCP_ALLOWED_ORIGINS, plugin: mcp.http.allowedOrigins). Others get 403.
  • Repeated bad tokens are slowed down. After 5 failed attempts from one address, the server answers 429 with Retry-After, doubling the wait up to 5 minutes; a correct token resets the count.

Also publishes @mp-consulting/homebridge-ai-core 2.2.0 (see packages/ai-core/CHANGELOG.md).