fix: route addon and HA core log fetches directly to Supervisor on addon installs - #1126
Conversation
Addresses homeassistant-ai#1116. The HA Core proxy at /api/hassio/addons/{slug}/logs returns 403 against SUPERVISOR_TOKEN on current HA Core releases. Route around HA Core entirely on add-on installs by hitting the Supervisor REST API at http://supervisor/addons/{slug}/logs directly — same pattern tools_bug_report.py already uses for self-logs. The HA-Core-proxy path stays as the fallback for non-addon installs (Docker/pip with admin LLA). Branching gate is the existing is_running_in_addon() helper in _version.py — no fourth duplicate of the SUPERVISOR_TOKEN env-var check. Test coverage pins both branches plus the gate selection — see new TestGetAddonLogsViaSupervisor and TestGetAddonLogsBranchSelection classes in test_tools_utility_supervisor_logs.py.
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request resolves an issue where fetching add-on logs failed in Supervisor-equipped environments due to HA Core proxy restrictions. By introducing a direct communication path to the Supervisor API when running as an add-on, the fix ensures reliable log retrieval while maintaining backward compatibility for non-add-on installations. Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. Footnotes
|
Implementation SummaryChoices Made:
Problems Encountered:
Suggested Improvements:
|
There was a problem hiding this comment.
Code Review
This pull request implements a direct communication path with the Supervisor REST API for fetching add-on logs when running within a Home Assistant add-on environment, while maintaining the HA Core proxy as a fallback for other installation types. This change resolves issues where the proxy would reject certain token and path combinations. Feedback was provided to ensure that the newly introduced httpx.AsyncClient consistently applies the verify_ssl configuration used elsewhere in the HomeAssistantClient class.
Per Gemini review on PR homeassistant-ai#1126: mirrors the verify=self.verify_ssl pattern from rest_client.py:125 (class-level httpx_client). The http://supervisor URL is plain HTTP and TLS-irrelevant in practice, but the parameter keeps the constructor consistent with the established HomeAssistantClient shape. mock_client fixture extended with verify_ssl = True so the existing Supervisor-direct tests exercise the new attribute access path.
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request updates the get_addon_logs method in the REST client to support direct communication with the Supervisor API when running within a Home Assistant add-on environment. This change bypasses the HA Core proxy to avoid authentication issues and includes comprehensive unit tests for both the direct and fallback paths. Feedback was provided regarding the efficiency of instantiating a new httpx.AsyncClient for every request, suggesting the use of a persistent client instead.
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request updates the get_addon_logs method in the REST client to support direct communication with the Supervisor API when running as a Home Assistant add-on. This change bypasses the HA Core proxy, which previously caused authentication issues in certain environments. The update includes a new internal helper method, _get_addon_logs_via_supervisor, and comprehensive unit tests covering success scenarios, error mapping, and branch selection logic. Feedback was provided to ensure docstring consistency by using an action verb in the internal helper's documentation.
…verb Per Gemini review on PR homeassistant-ai#1126: aligns the internal helper's docstring with the action-verb shape of nearby Fetch*/Get* methods on HomeAssistantClient. The .gemini/styleguide.md MCP-Tool-Docstrings section technically scopes to public @tool functions, so this is a consistency-nit rather than a styleguide-mandated fix — but matches the local pattern.
…only, dev94 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
When I tested it locally it still isn't working till I bumped the hassio role. So requesting we bump hassio_role: default → manager in both homeassistant-addon/config.yaml and Also I just caught that the tool still doesn't access the actual director supervisor logs (system) like it is intended to do, that was part of the intent of issue #1116 to address that as well |
kingpanther13
left a comment
There was a problem hiding this comment.
In addition to the above comment, please address:
Critical
- Empty
SUPERVISOR_TOKENsilently produces blank Bearer.rest_client.py:482defaults to"". If the gate ever disagrees with reality (detection bug, dev sideload), Supervisor 401s and the user sees"Invalid Supervisor token"— wrong diagnosis. Fail-fast with a config-error message, or fall through to the proxy branch with alogger.warning. - 403 not mapped distinctly.
rest_client.py:498-505lumps the actual #1116 symptom into the generic>= 400path. Add a 403 branch with a remediation hint (role / addon manifest), since that's the failure mode this PR is most likely to surface during the role rollout. - Stale tool docstring.
tools_utility.py:622-628still describes the HA-Core-proxy path and references #950. Boy-Scout — update to describe the new branch-on-is_running_in_addon()behavior. - Misleading "mirrors
_fetch_addon_logs" framing.rest_client.py:475. That helper is hardcoded toslug=selfand works ondefaultrole; this helper takes arbitrary slugs and (will) needmanager. The docstring should call out the scope/role difference instead of claiming mirroring.
Important
5. verify=self.verify_ssl is a no-op for http://supervisor (rest_client.py:481). Drop it, or add a one-liner comment that it's there for symmetry only.
6. Error envelope not parsed. Supervisor returns {"result":"error","message":"..."} JSON on some 4xx paths. Currently the raw JSON string lands in the user-facing message. Try json.loads(text_body).get("message") first, then fall back to text/reason_phrase.
7. Catch-order split with no observable difference. TimeoutException and HTTPError both raise HomeAssistantConnectionError with near-identical messages. Differentiate ("Timeout..." vs "Transport error...") or collapse to one clause.
8. level param still applies to source="supervisor" (tools_utility.py:139). Meaningless for raw container stdout — now that slug paths actually return content, users will pass level="ERROR" and get nonsense filtering. Drop supervisor from the tuple or warn when both level and slug are set.
9. No logger.warning on the >= 400 raise path in _get_addon_logs_via_supervisor. Operators have to enable debug to diagnose. Log status + slug at warning level on the raise side.
Test gaps
10. Missing/empty SUPERVISOR_TOKEN path untested. Pin behavior either way (fail-fast or "blank Bearer → 401").
11. Generic non-timeout httpx.HTTPError (e.g. RemoteProtocolError) untested. The except httpx.HTTPError clause can be silently narrowed by a future refactor.
12. Tier-3 reason-phrase fallback untested — empty body + empty reason_phrase → "<empty body>". TestRawRequestEmptyBodyFallback covers this for the proxy branch; parity gap for the supervisor branch.
13. verify_ssl + timeout ctor-kwargs propagation untested. mock_async_client_class exposes client_class but no test asserts on client_class.call_args.kwargs. Cheap to add to the happy-path test — a regression that hard-codes verify=True or drops the timeout would currently keep CI green.
14. TestGetAddonLogsBranchSelection::test_addon_install_uses_supervisor_direct is mock-the-mock. Duplicates the URL+auth assertions in the dedicated class without re-asserting them, so the test would pass for any implementation that calls httpx.AsyncClient(...).get(...). Either tighten it to assert URL + Authorization on this path too, or shrink to a one-liner that only verifies the gate was consulted (and explicitly delegates contract to the dedicated class).
15. Patch path brittleness. patch("ha_mcp.client.rest_client.httpx.AsyncClient", ...) works only because httpx is imported as a module. A future from httpx import AsyncClient silently breaks it. Prefer patch("httpx.AsyncClient", ...).
Comment / docstring trims
16. Inaccurate gate description. rest_client.py:441 says "On add-on installs (SUPERVISOR_TOKEN env present)". The gate is is_running_in_addon(), not the env var (token is read separately at line 481 with a "" default). If is_running_in_addon ever stops keying off that env var the docstring lies.
17. Drop redundant narration:
- _force_non_addon fixture docstring restates the decorator.
- mock_async_client_class docstring narrates the `async with` mocking pattern (implementation detail).
- Per-test docstrings ("The fix's primary contract...", "401 from Supervisor maps to...") restate test names — drop or trim.
- TestGetAddonLogsViaSupervisor class docstring duplicates the _get_addon_logs_via_supervisor production-code #1116 narrative — keep one copy in the production code.
Critical (review items 1-4):
- Empty SUPERVISOR_TOKEN now fail-fast HomeAssistantAuthError with distinct
message ("absent at call time"), so detection/config mismatches don't
read as "token rejected" (item 1).
- 403 carved out as distinct branch with role-hint suggestion + warning log
before raise — most-likely cause for homeassistant-ai#1116-class failures is now hassio_role
too low (item 2).
- _get_supervisor_log docstring updated to describe the branch-on-
is_running_in_addon() behavior, drop homeassistant-ai#950-only framing (item 3).
- _get_addon_logs_via_supervisor docstring rewritten to enumerate
scope/role differences vs _fetch_addon_logs instead of claiming mirror (item 4).
Important (items 5-9):
- verify=self.verify_ssl kept with explicit symmetry comment citing homeassistant-ai#1128's
three-site convention (item 5, KP13's option B).
- Supervisor's {"result":"error","message":"..."} JSON envelope now parsed
before the raw-text fallback (item 6).
- Distinct timeout vs transport error messages (item 7).
- logger.warning fires before every 4xx raise so operators see status+path
without enabling debug (item 9).
Test gaps (items 10-15):
- New: test_raises_auth_error_on_empty_supervisor_token (item 10).
- New: test_raises_connection_error_on_remote_protocol_error (item 11).
- New: test_empty_body_no_reason_phrase_uses_placeholder for tier-3 fallback
parity with the proxy branch (item 12).
- ctor-kwargs (verify + timeout) asserted on the URL+auth happy path so a
regression that hard-codes either keeps CI red (item 13).
- TestGetAddonLogsBranchSelection::test_addon_install_uses_supervisor_direct
shrunk to gate-only — URL/auth contract delegated to dedicated class (item 14).
- patch path migrated from "ha_mcp.client.rest_client.httpx.AsyncClient" to
"httpx.AsyncClient" — robust to both \`import httpx\` and a future
\`from httpx import AsyncClient\` (item 15).
Comment trims (items 16-17):
- get_addon_logs docstring gate description corrected to is_running_in_addon()
rather than "SUPERVISOR_TOKEN env present" (item 16).
- Per-test/fixture/class-level redundant narration trimmed (item 17).
Decline:
- Item 8 (level applies to source="supervisor"): warning is already emitted
at tools_utility.py:139 — \`supervisor\` is in the level-not-applicable
warning tuple, pinned by test_level_param_emits_warning_for_supervisor_source.
This PR adds \`system_service\` to the same tuple plus a parallel test for
parity.
Scope additions per KP13's PR-comment 12:42:
- hassio_role: default → manager in both addon config.yamls, with comment
citing the live test result.
- New source="system_service" with slug enum {supervisor, host, core, dns,
audio, multicast, observer}. Hits http://supervisor/<service>/logs via the
same direct-Supervisor pattern (extracted to shared _supervisor_logs_get
helper). Caller-layer slug-enum validation gives users the allowed-set
before the request fires.
Implementation SummaryRound 2 of CR addressing — full 17-item disposition table is in the PR body (just refreshed). Choices Made:
Problems Encountered:
Suggested Improvements (post-merge):
Live-test plan (post-merge dev-channel deploy):
|
…only, dev96 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
TL;DR for
Full 17-item disposition: PR body table. |
kingpanther13
left a comment
There was a problem hiding this comment.
Round 2 looks clean — 16 of 17 items addressed, item 8 decline is valid (the level warning is emitted from the tuple at tools_utility.py:160-167, now extended to system_service). Role bump + system_service source verified live against my test instance.
In addition to the above, please address:
Critical
source="error_log"is also broken on Supervisor installs — same shape as #1116. HA Core'sbootstrap.py(current dev) setserr_log_path = NonewhenSUPERVISORenv is present, which meanshass.data[DATA_LOGGING]is never set, and theAPIErrorLogview registration is gated onif DATA_LOGGING in hass.data:— so/api/error_logis not registered at all on HA OS / Supervised, returning 404 by-design. Verified empirically and againsthome-assistant/coresource. Fix shape parallels what you already built: whenis_running_in_addon(), routeerror_logto_supervisor_logs_get("core")(HA Core's container log via Supervisor — same content, different transport). On non-addon installs keep the current/api/error_logpath. Helper is already in place; this is a one-branch addition inclient.get_error_log()plus a tool-layer note. Worth landing in this PR since it's the same root cause and same fix shape — closes the "log fetch doesn't work on Supervisor installs" class of bugs in one go.
While you're in there (nits, address inline)
2. slug param is silently ignored on non-supervisor/non-system_service sources. tools_utility.py:154-167 warns when entity_id/end_time are passed to non-logbook sources, and warns when level is passed to non-system/error_log sources. slug has no equivalent — passing slug="x" with source="logbook" is silently dropped. Add a third warning: if source not in ("supervisor", "system_service") and slug is not None:.
3. Role escalation is undocumented. hassio_role: default → manager is a meaningful permission bump (the addon can now start/stop/install/update other addons, read all their info, etc.). The addon-config comment is good for code reviewers but users updating the addon won't see it. One-line note in homeassistant-addon/DOCS.md (and the dev sibling per the dev-first translation rule) calling out the new role + why would close the doc gap.
… addon installs HA Core's `bootstrap.py` sets `err_log_path = None` when the `SUPERVISOR` env var is present (line 641-651 in current dev), so `hass.data[DATA_LOGGING]` is never populated and the `APIErrorLog` view is not registered — meaning `/api/error_log` returns 404 by-design on HA OS / Supervised installs. Mirror the `get_addon_logs` fix shape (homeassistant-ai#1116): branch `HomeAssistantClient.get_error_log()` on `is_running_in_addon()`. On the addon branch route to `_supervisor_logs_get("core")` (HA Core's container log via Supervisor — same content, different transport). Non-addon installs keep the existing `/api/error_log` proxy path. Also: - Add the missing `slug` parameter incompatibility warning in `tools_utility.ha_get_logs`: parallels the existing `level` / `entity_id`/`end_time` warnings; previously `slug="x"` with a non-supervisor source was silently dropped. - Document the addon's `hassio_role: manager` requirement in `homeassistant-addon/DOCS.md` (under Security) and the dev sibling `homeassistant-addon-dev/DOCS.md` (under Configuration → Permissions) so users updating the addon see the role bump rationale. Tests: - `TestGetErrorLogBranchSelection` — pins both branches of the gate. - `TestSlugParameterIncompatibilityWarning` — parametrized over four non-supervisor sources (warn) and two supervisor sources (no warn). Addresses kingpanther13's round-2 review on homeassistant-ai#1126. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Round-2 → Round-3 follow-up — addressed in Critical 1 (error_log Supervisor branch) — Nit 2 (slug warning) — third warning branch in Nit 3 (role docs) — Local: 1711 unit tests pass, ruff clean. PR description updated to reflect the extended scope. |
…only, dev97 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
kingpanther13
left a comment
There was a problem hiding this comment.
Round-3 verified: error_log routes via Supervisor on addon installs, slug warning fires for non-supervisor sources, role-bump documented. All 17+3 review items addressed, tests added, live-confirmed on Fork-Dev. LGTM.
🧪 Your changes are now in the dev channel!Your PR has been merged to master and is available for testing in the dev channel. Test your changes before the next stable release (biweekly Wednesday): Quick start# Run dev version
uvx ha-mcp-dev
# Check version
uvx ha-mcp-dev --versionDocker: docker pull ghcr.io/homeassistant-ai/ha-mcp:dev
docker run --rm -i \
-e HOMEASSISTANT_URL=http://your-ha:8123 \
-e HOMEASSISTANT_TOKEN=your_token \
ghcr.io/homeassistant-ai/ha-mcp:devFound an issue? Please open a new bug report and mention this PR for context. |
Merge brings in homeassistant-ai#1126, homeassistant-ai#1135, homeassistant-ai#1136, homeassistant-ai#1138 and the dev-addon publish chain since the branch's previous head `147ad5f`. Conflict in `tests/src/unit/test_settings_ui.py` resolved by keeping both adjacent additions: master's `test_returns_500_when_save_fails` (read-only-fs 500-surfacing test from homeassistant-ai#1138) inside `TestSaveToolsValidation`, plus this PR's new `TestRestartAddon` class right after. KP13 round-1 review asks (CHANGES_REQUESTED 2026-05-06 20:38 UTC) all addressed: 1. **Narrow connection-drop catch** — the `except` tuple in `_restart_addon` (in `settings_ui.py`) is now `(httpx.ReadError, httpx.RemoteProtocolError)`. `httpx.ConnectError` is no longer treated as a successful restart; it falls through to the `httpx.HTTPError` handler returning 502 + `CONNECTION_FAILED`. Inline comment documents the deliberate exclusion (DNS / TCP-refused / supervisor-socket-misconfigured all mean Supervisor was unreachable, not that a restart was initiated). 2. **Parametrize connection-drop test** + separate `ConnectError` → 502 case. `test_treats_connection_drop_as_success` now parametrizes over `(httpx.ReadError, httpx.RemoteProtocolError)`. New `test_connect_error_returns_502` locks the contract that a connection-failure-before-handshake surfaces as 502. 3. **Boy-Scout: pin remaining `_restart_addon` branches.** Two new tests: `test_generic_http_error_returns_502` (uses `httpx.PoolTimeout` to exercise the `httpx.HTTPError` fall-through) and `test_supervisor_4xx_returns_502` (Supervisor returns 401 → handler maps to 502). 4. **Symbol-based test docstrings** — class-docstring + method docstrings now reference "the `if not token:` guard", "the catch on `(ReadError, RemoteProtocolError)`", "the `httpx.HTTPError` handler", "the `status_code >= 400` branch" instead of line numbers that shift with every kwarg-split / refactor. 5. **Top-level `import httpx`** in `tests/src/unit/test_settings_ui.py` replaces the inline `__import__("httpx").ReadError(...)` workaround. 6. **Trim "post-G1 state"** from the `verify_ssl = True` fixture comment. Kept the substantive part ("must resolve to a real bool, not a MagicMock, because httpx accepts only bool/SSLContext for `verify=`") that pays off in 6 months. 7. **Move homeassistant-ai#960 cross-reference** out of the `TestRestartAddon` class docstring. Closed-PR review history rots fast in source; the PR body is the right place for it. Local: 1762 unit tests pass, ruff lint + format clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
#1128) * refactor: pass verify_ssl to remaining direct-Supervisor httpx callers Closes #1127. Mirrors the verify=self.verify_ssl propagation pattern established in #1126 (rest_client.py:_get_addon_logs_via_supervisor) at the two other direct-Supervisor httpx call sites: - tools_bug_report.py:_fetch_addon_logs uses get_global_settings().verify_ssl (module-level helper, no self/closure context). - settings_ui.py:_restart_addon uses server.client.verify_ssl (closure has access to server: HomeAssistantSmartMCPServer). Both paths effectively propagate Settings.verify_ssl via the access route appropriate to each call site's scope. The http://supervisor URL is plain HTTP and TLS-irrelevant in practice — the parameter keeps all three constructor sites consistent with the established HomeAssistantClient pattern. * refactor: read verify_ssl from server.settings instead of server.client Per Gemini review on PR #1128: server.client is a lazy @Property (server.py) — accessing it for a single config bool would instantiate the full HomeAssistantClient (httpx pool, settings re-read, log line) on first access. server.settings is eager-initialized in the HomeAssistantSmartMCPServer constructor and is the canonical source of truth for verify_ssl. Additional benefit: in OAuth deployment mode (__main__.py:868), HomeAssistantSmartMCPServer is constructed with an OAuthProxyClient whose __getattr__ proxies to a per-request OAuth client requiring an authenticated request context. _restart_addon is a plain admin POST without that context, so server.client.verify_ssl could have surfaced as an auth error in OAuth mode. server.settings.verify_ssl sidesteps it without depending on OAuthProxyClient's attribute-forwarding semantics. * test: pin _restart_addon untested branches per Boy-Scout Adds unit-test coverage for the two previously-untested branches in settings_ui.py:_restart_addon: - Missing SUPERVISOR_TOKEN (settings_ui.py:780-789) — non-addon installs hit this when the user clicks Restart against a Docker/pyinstaller setup; the structured 400 must surface rather than ever reaching the Supervisor URL. - Connection-drop-as-success (settings_ui.py:798-801) — the Supervisor kills our process mid-request during a restart, so a ReadError / RemoteProtocolError / ConnectError from the POST is the documented success signal. Mirrors the _capture_handler pattern from TestSaveToolsValidation. The fixture-level server.settings.verify_ssl = True is required by this PR's post-G1 access path (httpx accepts only bool/SSLContext for verify=). Boy-Scout fix while already touching _restart_addon for the verify_ssl-propagation refactor — closes the test-coverage gap I'd flagged in #960's approve-body but never followed up on at the time. --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* refactor: extract shared Supervisor httpx client helper (#1130) Three direct-Supervisor httpx call sites all built fresh AsyncClients with the same boilerplate (base URL http://supervisor, Authorization: Bearer $SUPERVISOR_TOKEN). Move that into a single factory in client/supervisor_client.py and have the call sites pass relative paths instead of full URLs: - client/rest_client.py:_supervisor_logs_get - tools/tools_bug_report.py:_fetch_addon_logs - settings_ui.py:_restart_addon Per-call clients (vs. a singleton) preserved — these endpoints are low-frequency, connection-pool reuse is negligible, and singleton lifecycle adds shutdown/reload coupling that the issue's #1126 G2 review already declined for the same reason. verify and timeout stay caller-supplied so each site keeps its existing settings-source choice (instance snapshot vs. live read). Token is read from env in the helper at construction time, matching the original sites; the absent-token policy stays at the call site (rich exception, silent empty string, or 400 JSONResponse — these don't share a common shape and the helper shouldn't dictate one). Tests: new tests/src/unit/test_supervisor_client.py covers the factory contract (base_url, env override, Bearer header, timeout/verify forwarding, absent-token graceful degradation). Two existing tests in test_tools_utility_supervisor_logs.py updated to the new contract: URL passed to .get() is now relative; Authorization header asserted on the constructor kwargs instead of the per-call kwargs. Closes #1130. * fix: address round-2 review findings on #1130 - Raise RuntimeError on absent/empty SUPERVISOR_TOKEN at the factory so the malformed Bearer header never reaches Supervisor. - Add wire-shape unit tests for _fetch_addon_logs and _restart_addon asserting relative URLs, ctor-set Authorization, and no per-call Authorization kwarg. - Add a header-layering test pinning per-call Accept overlay on the ctor-set Authorization. - Drop ephemeral PR/issue refs from code and test comments per AGENTS.md. - Broaden the verify parameter type to httpx's full surface, add an env-read-at-construction Note to the docstring, dedup the token-handling paragraph. - Sibling: test_config_toggles_section_renders_in_templates now delenv's SUPERVISOR_TOKEN so the SimpleNamespace fake (missing verify_ssl) doesn't hit the addon-logs path on containers with the env var set. --------- Co-authored-by: Patch76 <mkglasmoor@gmail.com>
…→ 7.5.0) (#455) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [ghcr.io/homeassistant-ai/ha-mcp](https://github.com/homeassistant-ai/ha-mcp) | minor | `7.4.0` → `7.5.0` | --- >⚠️ **Warning** > > Some dependencies could not be looked up. Check the [Dependency Dashboard](issues/3) for more information. --- ### Release Notes <details> <summary>homeassistant-ai/ha-mcp (ghcr.io/homeassistant-ai/ha-mcp)</summary> ### [`v7.5.0`](https://github.com/homeassistant-ai/ha-mcp/blob/HEAD/CHANGELOG.md#v750-2026-05-13) [Compare Source](homeassistant-ai/ha-mcp@v7.4.0...v7.5.0) ##### Added - Add ENABLE\_LITE\_DOCSTRINGS beta toggle ([#​1259](homeassistant-ai/ha-mcp#1259)) - Add ha\_call\_event tool for publishing events on the HA event bus ([#​996](homeassistant-ai/ha-mcp#996)) ([#​1239](homeassistant-ai/ha-mcp#1239)) - Pinpoint backslash-escape mistake in python\_sandbox errors ([#​1204](homeassistant-ai/ha-mcp#1204)) - Reject empty-trigger automations targeting scene.create ([#​1187](homeassistant-ai/ha-mcp#1187)) - Add scene config tools — ha\_config\_get/set/remove\_scene ([#​1168](homeassistant-ai/ha-mcp#1168)) - **addon**: Optional OAuth 2.1 mode for webhook proxy (beta) ([#​1184](homeassistant-ai/ha-mcp#1184)) - Surface helper schema inline in ha\_config\_set\_helper validation errors ([#​1149](homeassistant-ai/ha-mcp#1149)) ([#​1179](homeassistant-ai/ha-mcp#1179)) - Emit progress via FastMCP Context in long-running tools ([#​1124](homeassistant-ai/ha-mcp#1124)) - Broaden python\_transform AST allowlist + improve error UX ([#​1163](homeassistant-ai/ha-mcp#1163)) - Add ha\_manage\_custom\_tool — sandboxed code execution escape hatch ([#​854](homeassistant-ai/ha-mcp#854)) - Always-on skills; rename list/read resource tools with ha\_ prefix ([#​1136](homeassistant-ai/ha-mcp#1136)) - Expose device\_class + options on ha\_set\_entity / ha\_get\_entity (Show As) ([#​1135](homeassistant-ai/ha-mcp#1135)) - **site**: Inline wizard data into setup.astro, migrate setup nuggets, drop content collections ([#​1120](homeassistant-ai/ha-mcp#1120)) - Add "Advanced debug logging" toggle for kill-signal diagnostics ([#​1117](homeassistant-ai/ha-mcp#1117)) - **yaml**: Scoped lovelace.dashboards.\<url\_path> support (issue [#​1034](homeassistant-ai/ha-mcp#1034)) ([#​1103](homeassistant-ai/ha-mcp#1103)) - Add HA\_VERIFY\_SSL toggle to disable TLS verification ([#​1104](homeassistant-ai/ha-mcp#1104)) - Per-top-level-key config\_hash for ha\_manage\_energy\_prefs ([#​1049](homeassistant-ai/ha-mcp#1049)) ([#​1098](homeassistant-ai/ha-mcp#1098)) - **site**: Add gemini-cli setup notes + compose hardening to wizard ([#​1027](homeassistant-ai/ha-mcp#1027)) ([#​1087](homeassistant-ai/ha-mcp#1087)) - Add convenience modes to ha\_manage\_energy\_prefs ([#​1050](homeassistant-ai/ha-mcp#1050)) ([#​1073](homeassistant-ai/ha-mcp#1073)) - Surface integration log levels in ha\_get\_logs/integration/addon ([#​956](homeassistant-ai/ha-mcp#956)) ([#​1003](homeassistant-ai/ha-mcp#1003)) - Expose allowlist\_external\_dirs in ha\_get\_overview full system\_info ([#​1053](homeassistant-ai/ha-mcp#1053)) - **dashboards**: Unify identifier handling in ha\_config\_\*\_dashboard tools ([#​981](homeassistant-ai/ha-mcp#981)) ([#​1075](homeassistant-ai/ha-mcp#1075)) - Include addon container logs in bug reports ([#​934](homeassistant-ai/ha-mcp#934)) - Add WebSocket response-shaping controls to ha\_manage\_addon ([#​1009](homeassistant-ai/ha-mcp#1009)) - Web-based settings UI for per-tool enable/disable/pin ([#​960](homeassistant-ai/ha-mcp#960)) - **site**: Add OpenCode support to setup wizard ([#​1080](homeassistant-ai/ha-mcp#1080)) ##### Changed - Clarify standard-mode HTTP deployment guidance ([#​1185](homeassistant-ai/ha-mcp#1185)) - Add Cloudflared add-on hostname alternative for tunnel service ([#​1183](homeassistant-ai/ha-mcp#1183)) - Align tool naming convention between AGENTS.md and styleguide ([#​943](homeassistant-ai/ha-mcp#943)) ([#​1174](homeassistant-ai/ha-mcp#1174)) - **addon**: Note tool-list ([#​985](homeassistant-ai/ha-mcp#985 divergence; fix [#​1139](https://github.com/homeassistant-ai/ha-mcp/issues/1139)/[#​1162](https://github.com/homeassistant-ai/ha-mcp/issues/1162) test conflict ([#​1172](homeassistant-ai/ha-mcp#1172)) - Add brew install option for mcp-proxy on macOS ([#​1171](homeassistant-ai/ha-mcp#1171)) - Update contributors list \[contributors-updated] ([`aba01a1`](homeassistant-ai/ha-mcp@aba01a1)) - Warn against enable\_tool\_search on Claude Sonnet/Opus ([#​1088](homeassistant-ai/ha-mcp#1088)) ([#​1140](homeassistant-ai/ha-mcp#1140)) - Address [#​1094](homeassistant-ai/ha-mcp#1094) review nits on OpenCode mirror comments ([#​1105](homeassistant-ai/ha-mcp#1105)) ##### Fixed - **integrations**: Surface ConfigEntry.options via OptionsFlow probe ([#​1245](homeassistant-ai/ha-mcp#1245)) - **backup**: Discover local agent at call time instead of hardcoding hassio.local ([#​1244](homeassistant-ai/ha-mcp#1244)) - Triage all 10 ha\_search\_entities behaviors from [#​1170](homeassistant-ai/ha-mcp#1170) ([#​1195](homeassistant-ai/ha-mcp#1195)) - Replace cron with systemd for demo server (prevents process leak) ([#​1110](homeassistant-ai/ha-mcp#1110)) - Improve ha\_manage\_addon discoverability (BM25 keywords + slug examples) ([#​1200](homeassistant-ai/ha-mcp#1200)) - Route Supervisor 401s to structured tool errors + add E2E coverage ([#​1129](homeassistant-ai/ha-mcp#1129)) ([#​1192](homeassistant-ai/ha-mcp#1192)) - Harden \_validate\_category\_id gate to cover dict-promoted category ([#​1190](homeassistant-ai/ha-mcp#1190)) - Broaden template anti-pattern detection + skill discoverability ([#​1011](homeassistant-ai/ha-mcp#1011)) ([#​1181](homeassistant-ai/ha-mcp#1181)) - Return newest automation traces, add offset+order pagination ([#​1177](homeassistant-ai/ha-mcp#1177)) ([#​1178](homeassistant-ai/ha-mcp#1178)) - **security**: Write YAML backups outside www/ (GHSA-g39v-cvjh-8fpf) ([#​1180](homeassistant-ai/ha-mcp#1180)) - **search**: Apply domain\_filter when area\_filter is set ([#​1162](homeassistant-ai/ha-mcp#1162)) ([#​1165](homeassistant-ai/ha-mcp#1165)) - **resources**: Reject HA-config YAML in dashboard resource content ([#​1160](homeassistant-ai/ha-mcp#1160)) - Close 19 bugs in ha\_config\_set\_helper (issue [#​1150](homeassistant-ai/ha-mcp#1150)) ([#​1151](homeassistant-ai/ha-mcp#1151)) - Route addon log fetches directly to supervisor on addon installs ([#​1126](homeassistant-ai/ha-mcp#1126)) - Survive read-only filesystems at startup ([#​1138](homeassistant-ai/ha-mcp#1138)) - **helpers**: Clarify name-required-on-create for ha\_config\_set\_helper ([#​1143](homeassistant-ai/ha-mcp#1143)) - Resolve disabled entities via entity\_registry in helper deletion ([#​1119](homeassistant-ai/ha-mcp#1119)) - Allow unary operators in python\_transform sandbox ([#​1118](homeassistant-ai/ha-mcp#1118)) - **site**: Add github-copilot-agents wizard branch + delete unreferenced data/clients.ts ([#​1108](homeassistant-ai/ha-mcp#1108)) - **addons**: Route addon API calls through HA Core ingress proxy ([#​1069](homeassistant-ai/ha-mcp#1069)) - **webhook-proxy**: Surface webhook registration failures instead of silently loading ([#​1101](homeassistant-ai/ha-mcp#1101)) - **site**: Resolve client display-order collisions and anchor OpenCode shape ([#​1094](homeassistant-ai/ha-mcp#1094)) ##### Performance Improvements - Dedupe lovelace/dashboards/list in ha\_config\_set\_dashboard ([#​1085](homeassistant-ai/ha-mcp#1085)) ([#​1191](homeassistant-ai/ha-mcp#1191)) ##### Refactoring - Drop obsolete ha\_mcp\_tools defensive ruamel.yaml imports ([post-#​1268](https://github.com/post-/ha-mcp/issues/1268)) ([#​1269](homeassistant-ai/ha-mcp#1269)) - Extract shared Supervisor httpx client helper ([#​1130](homeassistant-ai/ha-mcp#1130)) ([#​1203](homeassistant-ai/ha-mcp#1203)) - Surface client identity, AI model, config toggles, and prompt context in ha\_report\_issue ([#​1189](homeassistant-ai/ha-mcp#1189)) - Harden Context injection with safe-emit + branch coverage ([#​1173](homeassistant-ai/ha-mcp#1173)) - Consolidate area/floor set+remove tools (revisit of [#​813](homeassistant-ai/ha-mcp#813)) ([#​1139](homeassistant-ai/ha-mcp#1139)) - Pass verify\_ssl to remaining direct-Supervisor httpx callers ([#​1128](homeassistant-ai/ha-mcp#1128)) - Validate only new entries on convenience-mode writes ([#​1086](homeassistant-ai/ha-mcp#1086)) ([#​1100](homeassistant-ai/ha-mcp#1100)) *** <details> <summary>Internal Changes</summary> ##### Fixed - **ci**: Align pr.yml E2E with --dist loadscope ([#​1206](homeassistant-ai/ha-mcp#1206)) ([#​1247](homeassistant-ai/ha-mcp#1247)) - **ci**: Switch Renovate to a GitHub App token to allow workflow-file pushes ([#​1229](homeassistant-ai/ha-mcp#1229)) - **ci**: Break gemini-triage retrigger loop and bump turn budget ([#​1131](homeassistant-ai/ha-mcp#1131)) - **ci**: Harden gemini-triage so failures stop spamming user issues ([#​1122](homeassistant-ai/ha-mcp#1122)) - **ci**: Unbreak hotfix-release semantic-release run ([#​1091](homeassistant-ai/ha-mcp#1091)) ##### Chores - **addon**: Publish dev addon version 7.4.1.dev299 \[skip ci] ([`397aa6d`](homeassistant-ai/ha-mcp@397aa6d)) - **addon**: Publish dev addon version 7.4.1.dev298 \[skip ci] ([`942b7e0`](homeassistant-ai/ha-mcp@942b7e0)) - Sync tool docs after merge \[skip ci] ([`6823c47`](homeassistant-ai/ha-mcp@6823c47)) - **addon**: Publish dev addon version 7.4.1.dev297 \[skip ci] ([`6eac062`](homeassistant-ai/ha-mcp@6eac062)) - **addon**: Publish dev addon version 7.4.1.dev296 \[skip ci] ([`b2afe93`](homeassistant-ai/ha-mcp@b2afe93)) - **addon**: Publish dev addon version 7.4.1.dev295 \[skip ci] ([`4f4c4f3`](homeassistant-ai/ha-mcp@4f4c4f3)) - **deps**: Update ghcr.io/home-assistant/home-assistant docker tag to v2026.5.1 ([#​1236](homeassistant-ai/ha-mcp#1236)) - **addon**: Publish dev addon version 7.4.1.dev294 \[skip ci] ([`fd24991`](homeassistant-ai/ha-mcp@fd24991)) - **deps**: Update ghcr.io/astral-sh/uv docker tag to v0.11.13 ([#​1233](homeassistant-ai/ha-mcp#1233)) - **addon**: Publish dev addon version 7.4.1.dev293 \[skip ci] ([`fcc6496`](homeassistant-ai/ha-mcp@fcc6496)) - **addon**: Publish dev addon version 7.4.1.dev292 \[skip ci] ([`2961650`](homeassistant-ai/ha-mcp@2961650)) - **addon**: Publish dev addon version 7.4.1.dev291 \[skip ci] ([`5703112`](homeassistant-ai/ha-mcp@5703112)) - **addon**: Publish dev addon version 7.4.1.dev290 \[skip ci] ([`19b2f65`](homeassistant-ai/ha-mcp@19b2f65)) - **addon**: Publish dev addon version 7.4.1.dev289 \[skip ci] ([`e5a1365`](homeassistant-ai/ha-mcp@e5a1365)) - Sync tool docs after merge \[skip ci] ([`d2ff93b`](homeassistant-ai/ha-mcp@d2ff93b)) - **addon**: Publish dev addon version 7.4.1.dev288 \[skip ci] ([`0f62400`](homeassistant-ai/ha-mcp@0f62400)) - Sync tool docs after merge \[skip ci] ([`c7e2066`](homeassistant-ai/ha-mcp@c7e2066)) - **addon**: Publish dev addon version 7.4.1.dev287 \[skip ci] ([`c1133d4`](homeassistant-ai/ha-mcp@c1133d4)) - **addon**: Publish dev addon version 7.4.1.dev286 \[skip ci] ([`1ae790e`](homeassistant-ai/ha-mcp@1ae790e)) - **addon**: Publish dev addon version 7.4.1.dev285 \[skip ci] ([`2387d0c`](homeassistant-ai/ha-mcp@2387d0c)) - **addon**: Publish dev addon version 7.4.1.dev284 \[skip ci] ([`dd3a4a5`](homeassistant-ai/ha-mcp@dd3a4a5)) - **addon**: Publish dev addon version 7.4.1.dev283 \[skip ci] ([`78af8eb`](homeassistant-ai/ha-mcp@78af8eb)) - Sync tool docs after merge \[skip ci] ([`093fd74`](homeassistant-ai/ha-mcp@093fd74)) - **addon**: Publish dev addon version 7.4.1.dev282 \[skip ci] ([`2141e15`](homeassistant-ai/ha-mcp@2141e15)) - Sync tool docs after merge \[skip ci] ([`7810c95`](homeassistant-ai/ha-mcp@7810c95)) - **addon**: Publish dev addon version 7.4.1.dev281 \[skip ci] ([`7d79ec2`](homeassistant-ai/ha-mcp@7d79ec2)) - Sync tool docs after merge \[skip ci] ([`a73dc81`](homeassistant-ai/ha-mcp@a73dc81)) - **addon**: Publish dev addon version 7.4.1.dev280 \[skip ci] ([`c858ce3`](homeassistant-ai/ha-mcp@c858ce3)) - Sync tool docs after merge \[skip ci] ([`a587be0`](homeassistant-ai/ha-mcp@a587be0)) - **addon**: Publish dev addon version 7.4.1.dev279 \[skip ci] ([`b78ddb2`](homeassistant-ai/ha-mcp@b78ddb2)) - Sync tool docs after merge \[skip ci] ([`1210725`](homeassistant-ai/ha-mcp@1210725)) - **addon**: Publish dev addon version 7.4.1.dev278 \[skip ci] ([`a282c17`](homeassistant-ai/ha-mcp@a282c17)) - **addon**: Publish dev addon version 7.4.1.dev277 \[skip ci] ([`1081768`](homeassistant-ai/ha-mcp@1081768)) - Sync tool docs after merge \[skip ci] ([`e03f5d2`](homeassistant-ai/ha-mcp@e03f5d2)) - **addon**: Publish dev addon version 7.4.1.dev276 \[skip ci] ([`c4ef680`](homeassistant-ai/ha-mcp@c4ef680)) - **addon**: Publish dev addon version 7.4.1.dev275 \[skip ci] ([`780422d`](homeassistant-ai/ha-mcp@780422d)) - Sync tool docs after merge \[skip ci] ([`8a2bd1a`](homeassistant-ai/ha-mcp@8a2bd1a)) - **addon**: Publish dev addon version 7.4.1.dev274 \[skip ci] ([`f0f09de`](homeassistant-ai/ha-mcp@f0f09de)) - **addon**: Publish dev addon version 7.4.1.dev273 \[skip ci] ([`cb49f68`](homeassistant-ai/ha-mcp@cb49f68)) - **addon**: Publish dev addon version 7.4.1.dev272 \[skip ci] ([`5097186`](homeassistant-ai/ha-mcp@5097186)) - **addon**: Publish dev addon version 7.4.1.dev271 \[skip ci] ([`4714342`](homeassistant-ai/ha-mcp@4714342)) - **addon**: Publish dev addon version 7.4.1.dev270 \[skip ci] ([`217982a`](homeassistant-ai/ha-mcp@217982a)) - **addon**: Publish dev addon version 7.4.1.dev269 \[skip ci] ([`a65dd5f`](homeassistant-ai/ha-mcp@a65dd5f)) - Sync tool docs after merge \[skip ci] ([`0e6b54f`](homeassistant-ai/ha-mcp@0e6b54f)) - **addon**: Publish dev addon version 7.4.1.dev268 \[skip ci] ([`60ba1f2`](homeassistant-ai/ha-mcp@60ba1f2)) - **addon**: Publish dev addon version 7.4.1.dev267 \[skip ci] ([`13412aa`](homeassistant-ai/ha-mcp@13412aa)) - Sync tool docs after merge \[skip ci] ([`2702a0f`](homeassistant-ai/ha-mcp@2702a0f)) - **addon**: Publish dev addon version 7.4.1.dev266 \[skip ci] ([`77abe0b`](homeassistant-ai/ha-mcp@77abe0b)) - **addon**: Publish dev addon version 7.4.1.dev265 \[skip ci] ([`08b69db`](homeassistant-ai/ha-mcp@08b69db)) - Sync tool docs after merge \[skip ci] ([`c1f24b5`](homeassistant-ai/ha-mcp@c1f24b5)) - **addon**: Publish dev addon version 7.4.1.dev264 \[skip ci] ([`f2583f6`](homeassistant-ai/ha-mcp@f2583f6)) - Sync tool docs after merge \[skip ci] ([`c2ed2d3`](homeassistant-ai/ha-mcp@c2ed2d3)) - **addon**: Publish dev addon version 7.4.1.dev263 \[skip ci] ([`9d43e54`](homeassistant-ai/ha-mcp@9d43e54)) - **addon**: Publish dev addon version 7.4.1.dev262 \[skip ci] ([`a7355c8`](homeassistant-ai/ha-mcp@a7355c8)) - Sync tool docs after merge \[skip ci] ([`085bd8a`](homeassistant-ai/ha-mcp@085bd8a)) - Convert agents to skills ([#​1084](homeassistant-ai/ha-mcp#1084)) - **addon**: Publish dev addon version 7.4.1.dev261 \[skip ci] ([`0d1af36`](homeassistant-ai/ha-mcp@0d1af36)) - **addon**: Publish dev addon version 7.4.1.dev260 \[skip ci] ([`29397dc`](homeassistant-ai/ha-mcp@29397dc)) - **addon**: Publish dev addon version 7.4.1.dev259 \[skip ci] ([`4bbc74b`](homeassistant-ai/ha-mcp@4bbc74b)) - Sync tool docs after merge \[skip ci] ([`0f6d41e`](homeassistant-ai/ha-mcp@0f6d41e)) - **addon**: Publish dev addon version 7.4.1.dev258 \[skip ci] ([`6751d08`](homeassistant-ai/ha-mcp@6751d08)) - **addon**: Publish dev addon version 7.4.1.dev257 \[skip ci] ([`2213c89`](homeassistant-ai/ha-mcp@2213c89)) - **addon**: Publish dev addon version 7.4.1.dev256 \[skip ci] ([`18a366e`](homeassistant-ai/ha-mcp@18a366e)) - **addon**: Publish dev addon version 7.4.1.dev255 \[skip ci] ([`0e9b18d`](homeassistant-ai/ha-mcp@0e9b18d)) - **addon**: Publish dev addon version 7.4.1.dev254 \[skip ci] ([`39fc65b`](homeassistant-ai/ha-mcp@39fc65b)) - Sync tool docs after merge \[skip ci] ([`9fa0aea`](homeassistant-ai/ha-mcp@9fa0aea)) - **addon**: Publish dev addon version 7.4.1.dev253 \[skip ci] ([`0dcc59e`](homeassistant-ai/ha-mcp@0dcc59e)) - Sync tool docs after merge \[skip ci] ([`ec7413f`](homeassistant-ai/ha-mcp@ec7413f)) - **addon**: Publish dev addon version 7.4.1.dev252 \[skip ci] ([`345640c`](homeassistant-ai/ha-mcp@345640c)) - **addon**: Publish dev addon version 7.4.1.dev251 \[skip ci] ([`bab9d49`](homeassistant-ai/ha-mcp@bab9d49)) - Sync tool docs after merge \[skip ci] ([`726f0a5`](homeassistant-ai/ha-mcp@726f0a5)) - **addon**: Publish dev addon version 7.4.1.dev250 \[skip ci] ([`ded04ea`](homeassistant-ai/ha-mcp@ded04ea)) - **addon**: Publish dev addon version 7.4.1.dev249 \[skip ci] ([`37d5628`](homeassistant-ai/ha-mcp@37d5628)) - **addon**: Publish dev addon version 7.4.1.dev248 \[skip ci] ([`530786a`](homeassistant-ai/ha-mcp@530786a)) - Sync tool docs after merge \[skip ci] ([`36719c3`](homeassistant-ai/ha-mcp@36719c3)) - **addon**: Publish dev addon version 7.4.1.dev247 \[skip ci] ([`4dc47b5`](homeassistant-ai/ha-mcp@4dc47b5)) - **addon**: Publish dev addon version 7.4.1.dev246 \[skip ci] ([`6ffbd6a`](homeassistant-ai/ha-mcp@6ffbd6a)) - Sync tool docs after merge \[skip ci] ([`add66e3`](homeassistant-ai/ha-mcp@add66e3)) - **addon**: Publish dev addon version 7.4.1.dev245 \[skip ci] ([`d0114af`](homeassistant-ai/ha-mcp@d0114af)) - Sync tool docs after merge \[skip ci] ([`0ca41af`](homeassistant-ai/ha-mcp@0ca41af)) - **addon**: Publish dev addon version 7.4.1.dev244 \[skip ci] ([`d052dd0`](homeassistant-ai/ha-mcp@d052dd0)) - **addon**: Publish dev addon version 7.4.0.dev243 \[skip ci] ([`827bc65`](homeassistant-ai/ha-mcp@827bc65)) - Bump package version to 7.4.1 to match released addon ([`4f65497`](homeassistant-ai/ha-mcp@4f65497)) - **addon**: Publish dev addon version 7.4.0.dev242 \[skip ci] ([`8ba80ae`](homeassistant-ai/ha-mcp@8ba80ae)) - **addon**: Publish hotfix version 7.4.1 ([`bda75e6`](homeassistant-ai/ha-mcp@bda75e6)) - **addon**: Publish dev addon version 7.4.0.dev241 \[skip ci] ([`2126428`](homeassistant-ai/ha-mcp@2126428)) ##### Continuous Integration - **deps**: Bump renovatebot/github-action in the github-actions group ([#​1218](homeassistant-ai/ha-mcp#1218)) - **deps**: Bump renovatebot/github-action in the github-actions group ([#​1111](homeassistant-ai/ha-mcp#1111)) ##### Refactoring - Extract \_fetch\_dashboards\_list helper ([#​1193](homeassistant-ai/ha-mcp#1193)) ([#​1207](homeassistant-ai/ha-mcp#1207)) ##### Testing - **e2e**: Module-scope bulk\_automations + bulk\_scripts fixtures (refs [#​366](homeassistant-ai/ha-mcp#366)) ([#​1275](homeassistant-ai/ha-mcp#1275)) - **e2e**: Lower INPUT\_BOOLEAN\_WAIT from 30s to 10s (refs [#​366](homeassistant-ai/ha-mcp#366)) ([#​1273](homeassistant-ai/ha-mcp#1273)) - **e2e**: Generalize readiness-gate diagnostics helper (closes [#​1267](homeassistant-ai/ha-mcp#1267)) ([#​1271](homeassistant-ai/ha-mcp#1271)) - **e2e**: Narrow except clauses in e2e polling helpers (closes [#​1266](homeassistant-ai/ha-mcp#1266)) ([#​1270](homeassistant-ai/ha-mcp#1270)) - **e2e**: Drop ha\_mcp\_tools retry-path + pre-install manifest requirements ([#​1268](homeassistant-ai/ha-mcp#1268)) - **e2e**: Instrument and retry ha\_mcp\_tools readiness wait ([#​1262](homeassistant-ai/ha-mcp#1262)) - Use time.monotonic() in UAT runner and test\_env\_manager ([#​1254](homeassistant-ai/ha-mcp#1254)) - **e2e**: Detect partial/corrupt hacs\_frontend dir in fast-path guard ([#​1253](homeassistant-ai/ha-mcp#1253)) - **e2e**: Remove unused wait/assert helpers ([post-#​1249](https://github.com/post-/ha-mcp/issues/1249) audit) ([#​1256](homeassistant-ai/ha-mcp#1256)) - **e2e**: Clear stale .hacs\_frontend.lock from prior crashed runs ([#​1252](homeassistant-ai/ha-mcp#1252)) - **e2e**: Use time.monotonic() in workflow polling loops ([#​1258](homeassistant-ai/ha-mcp#1258)) - **e2e**: Use time.monotonic() for duration polling ([#​1234](homeassistant-ai/ha-mcp#1234)) ([#​1249](homeassistant-ai/ha-mcp#1249)) - **e2e**: Close ARM ha\_mcp\_tools readiness race under loadscope ([#​1208](homeassistant-ai/ha-mcp#1208)) - **hacs**: Tighten is\_hacs\_unavailable to not match legitimate "Repository not found" ([#​1246](homeassistant-ai/ha-mcp#1246)) - **seed**: Unblock 3 silent-skip pagination/state tests via baked recorder DB ([#​1240](homeassistant-ai/ha-mcp#1240)) - **seed**: Register a writable local\_calendar to unblock event-creation test ([#​1243](homeassistant-ai/ha-mcp#1243)) - **addon**: Fix base64 padding-bit flake in token tamper tests ([#​1238](homeassistant-ai/ha-mcp#1238)) ([#​1241](homeassistant-ai/ha-mcp#1241)) - **seed**: Add a writable scene for test\_call\_service\_scene\_turn\_on ([#​1231](homeassistant-ai/ha-mcp#1231)) - **seed**: Assign demo device to living\_room area for filter test ([#​1230](homeassistant-ai/ha-mcp#1230)) - **e2e**: Drop nonexistent sun service from session readiness wait ([#​1227](homeassistant-ai/ha-mcp#1227)) - **e2e**: Self-contain dashboard register/remove to fix ARM xdist race ([#​1196](homeassistant-ai/ha-mcp#1196)) ([#​1201](homeassistant-ai/ha-mcp#1201)) - Fix EN dash in docstring causing RUF002 lint failure ([`eac5916`](homeassistant-ai/ha-mcp@eac5916)) - Address Gemini review feedback on host detection and port allocation ([`960305e`](homeassistant-ai/ha-mcp@960305e)) - Fix three categories of E2E test flakiness ([`39417ff`](homeassistant-ai/ha-mcp@39417ff)) - **e2e**: Pin config\_hash stability for dashboards ([#​1132](homeassistant-ai/ha-mcp#1132)) </details> </details> --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about these updates again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xMDEuMSIsInVwZGF0ZWRJblZlciI6IjQzLjEwMS4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJyZW5vdmF0ZS9jb250YWluZXIiLCJ0eXBlL21pbm9yIl19--> Reviewed-on: https://git.erwanleboucher.dev/eleboucher/homelab/pulls/455
….0 ) (#26) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [ghcr.io/homeassistant-ai/ha-mcp](https://github.com/homeassistant-ai/ha-mcp) | minor | `7.4.0` → `7.5.0` | --- ### Release Notes <details> <summary>homeassistant-ai/ha-mcp (ghcr.io/homeassistant-ai/ha-mcp)</summary> ### [`v7.5.0`](https://github.com/homeassistant-ai/ha-mcp/blob/HEAD/CHANGELOG.md#v750-2026-05-13) [Compare Source](homeassistant-ai/ha-mcp@v7.4.0...v7.5.0) ##### Added - Add ENABLE\_LITE\_DOCSTRINGS beta toggle ([#​1259](homeassistant-ai/ha-mcp#1259)) - Add ha\_call\_event tool for publishing events on the HA event bus ([#​996](homeassistant-ai/ha-mcp#996)) ([#​1239](homeassistant-ai/ha-mcp#1239)) - Pinpoint backslash-escape mistake in python\_sandbox errors ([#​1204](homeassistant-ai/ha-mcp#1204)) - Reject empty-trigger automations targeting scene.create ([#​1187](homeassistant-ai/ha-mcp#1187)) - Add scene config tools — ha\_config\_get/set/remove\_scene ([#​1168](homeassistant-ai/ha-mcp#1168)) - **addon**: Optional OAuth 2.1 mode for webhook proxy (beta) ([#​1184](homeassistant-ai/ha-mcp#1184)) - Surface helper schema inline in ha\_config\_set\_helper validation errors ([#​1149](homeassistant-ai/ha-mcp#1149)) ([#​1179](homeassistant-ai/ha-mcp#1179)) - Emit progress via FastMCP Context in long-running tools ([#​1124](homeassistant-ai/ha-mcp#1124)) - Broaden python\_transform AST allowlist + improve error UX ([#​1163](homeassistant-ai/ha-mcp#1163)) - Add ha\_manage\_custom\_tool — sandboxed code execution escape hatch ([#​854](homeassistant-ai/ha-mcp#854)) - Always-on skills; rename list/read resource tools with ha\_ prefix ([#​1136](homeassistant-ai/ha-mcp#1136)) - Expose device\_class + options on ha\_set\_entity / ha\_get\_entity (Show As) ([#​1135](homeassistant-ai/ha-mcp#1135)) - **site**: Inline wizard data into setup.astro, migrate setup nuggets, drop content collections ([#​1120](homeassistant-ai/ha-mcp#1120)) - Add "Advanced debug logging" toggle for kill-signal diagnostics ([#​1117](homeassistant-ai/ha-mcp#1117)) - **yaml**: Scoped lovelace.dashboards.\<url\_path> support (issue [#​1034](homeassistant-ai/ha-mcp#1034)) ([#​1103](homeassistant-ai/ha-mcp#1103)) - Add HA\_VERIFY\_SSL toggle to disable TLS verification ([#​1104](homeassistant-ai/ha-mcp#1104)) - Per-top-level-key config\_hash for ha\_manage\_energy\_prefs ([#​1049](homeassistant-ai/ha-mcp#1049)) ([#​1098](homeassistant-ai/ha-mcp#1098)) - **site**: Add gemini-cli setup notes + compose hardening to wizard ([#​1027](homeassistant-ai/ha-mcp#1027)) ([#​1087](homeassistant-ai/ha-mcp#1087)) - Add convenience modes to ha\_manage\_energy\_prefs ([#​1050](homeassistant-ai/ha-mcp#1050)) ([#​1073](homeassistant-ai/ha-mcp#1073)) - Surface integration log levels in ha\_get\_logs/integration/addon ([#​956](homeassistant-ai/ha-mcp#956)) ([#​1003](homeassistant-ai/ha-mcp#1003)) - Expose allowlist\_external\_dirs in ha\_get\_overview full system\_info ([#​1053](homeassistant-ai/ha-mcp#1053)) - **dashboards**: Unify identifier handling in ha\_config\_\*\_dashboard tools ([#​981](homeassistant-ai/ha-mcp#981)) ([#​1075](homeassistant-ai/ha-mcp#1075)) - Include addon container logs in bug reports ([#​934](homeassistant-ai/ha-mcp#934)) - Add WebSocket response-shaping controls to ha\_manage\_addon ([#​1009](homeassistant-ai/ha-mcp#1009)) - Web-based settings UI for per-tool enable/disable/pin ([#​960](homeassistant-ai/ha-mcp#960)) - **site**: Add OpenCode support to setup wizard ([#​1080](homeassistant-ai/ha-mcp#1080)) ##### Changed - Clarify standard-mode HTTP deployment guidance ([#​1185](homeassistant-ai/ha-mcp#1185)) - Add Cloudflared add-on hostname alternative for tunnel service ([#​1183](homeassistant-ai/ha-mcp#1183)) - Align tool naming convention between AGENTS.md and styleguide ([#​943](homeassistant-ai/ha-mcp#943)) ([#​1174](homeassistant-ai/ha-mcp#1174)) - **addon**: Note tool-list ([#​985](homeassistant-ai/ha-mcp#985 divergence; fix [#​1139](https://github.com/homeassistant-ai/ha-mcp/issues/1139)/[#​1162](https://github.com/homeassistant-ai/ha-mcp/issues/1162) test conflict ([#​1172](homeassistant-ai/ha-mcp#1172)) - Add brew install option for mcp-proxy on macOS ([#​1171](homeassistant-ai/ha-mcp#1171)) - Update contributors list \[contributors-updated] ([`aba01a1`](homeassistant-ai/ha-mcp@aba01a1)) - Warn against enable\_tool\_search on Claude Sonnet/Opus ([#​1088](homeassistant-ai/ha-mcp#1088)) ([#​1140](homeassistant-ai/ha-mcp#1140)) - Address [#​1094](homeassistant-ai/ha-mcp#1094) review nits on OpenCode mirror comments ([#​1105](homeassistant-ai/ha-mcp#1105)) ##### Fixed - **integrations**: Surface ConfigEntry.options via OptionsFlow probe ([#​1245](homeassistant-ai/ha-mcp#1245)) - **backup**: Discover local agent at call time instead of hardcoding hassio.local ([#​1244](homeassistant-ai/ha-mcp#1244)) - Triage all 10 ha\_search\_entities behaviors from [#​1170](homeassistant-ai/ha-mcp#1170) ([#​1195](homeassistant-ai/ha-mcp#1195)) - Replace cron with systemd for demo server (prevents process leak) ([#​1110](homeassistant-ai/ha-mcp#1110)) - Improve ha\_manage\_addon discoverability (BM25 keywords + slug examples) ([#​1200](homeassistant-ai/ha-mcp#1200)) - Route Supervisor 401s to structured tool errors + add E2E coverage ([#​1129](homeassistant-ai/ha-mcp#1129)) ([#​1192](homeassistant-ai/ha-mcp#1192)) - Harden \_validate\_category\_id gate to cover dict-promoted category ([#​1190](homeassistant-ai/ha-mcp#1190)) - Broaden template anti-pattern detection + skill discoverability ([#​1011](homeassistant-ai/ha-mcp#1011)) ([#​1181](homeassistant-ai/ha-mcp#1181)) - Return newest automation traces, add offset+order pagination ([#​1177](homeassistant-ai/ha-mcp#1177)) ([#​1178](homeassistant-ai/ha-mcp#1178)) - **security**: Write YAML backups outside www/ (GHSA-g39v-cvjh-8fpf) ([#​1180](homeassistant-ai/ha-mcp#1180)) - **search**: Apply domain\_filter when area\_filter is set ([#​1162](homeassistant-ai/ha-mcp#1162)) ([#​1165](homeassistant-ai/ha-mcp#1165)) - **resources**: Reject HA-config YAML in dashboard resource content ([#​1160](homeassistant-ai/ha-mcp#1160)) - Close 19 bugs in ha\_config\_set\_helper (issue [#​1150](homeassistant-ai/ha-mcp#1150)) ([#​1151](homeassistant-ai/ha-mcp#1151)) - Route addon log fetches directly to supervisor on addon installs ([#​1126](homeassistant-ai/ha-mcp#1126)) - Survive read-only filesystems at startup ([#​1138](homeassistant-ai/ha-mcp#1138)) - **helpers**: Clarify name-required-on-create for ha\_config\_set\_helper ([#​1143](homeassistant-ai/ha-mcp#1143)) - Resolve disabled entities via entity\_registry in helper deletion ([#​1119](homeassistant-ai/ha-mcp#1119)) - Allow unary operators in python\_transform sandbox ([#​1118](homeassistant-ai/ha-mcp#1118)) - **site**: Add github-copilot-agents wizard branch + delete unreferenced data/clients.ts ([#​1108](homeassistant-ai/ha-mcp#1108)) - **addons**: Route addon API calls through HA Core ingress proxy ([#​1069](homeassistant-ai/ha-mcp#1069)) - **webhook-proxy**: Surface webhook registration failures instead of silently loading ([#​1101](homeassistant-ai/ha-mcp#1101)) - **site**: Resolve client display-order collisions and anchor OpenCode shape ([#​1094](homeassistant-ai/ha-mcp#1094)) ##### Performance Improvements - Dedupe lovelace/dashboards/list in ha\_config\_set\_dashboard ([#​1085](homeassistant-ai/ha-mcp#1085)) ([#​1191](homeassistant-ai/ha-mcp#1191)) ##### Refactoring - Drop obsolete ha\_mcp\_tools defensive ruamel.yaml imports ([post-#​1268](https://github.com/post-/ha-mcp/issues/1268)) ([#​1269](homeassistant-ai/ha-mcp#1269)) - Extract shared Supervisor httpx client helper ([#​1130](homeassistant-ai/ha-mcp#1130)) ([#​1203](homeassistant-ai/ha-mcp#1203)) - Surface client identity, AI model, config toggles, and prompt context in ha\_report\_issue ([#​1189](homeassistant-ai/ha-mcp#1189)) - Harden Context injection with safe-emit + branch coverage ([#​1173](homeassistant-ai/ha-mcp#1173)) - Consolidate area/floor set+remove tools (revisit of [#​813](homeassistant-ai/ha-mcp#813)) ([#​1139](homeassistant-ai/ha-mcp#1139)) - Pass verify\_ssl to remaining direct-Supervisor httpx callers ([#​1128](homeassistant-ai/ha-mcp#1128)) - Validate only new entries on convenience-mode writes ([#​1086](homeassistant-ai/ha-mcp#1086)) ([#​1100](homeassistant-ai/ha-mcp#1100)) *** <details> <summary>Internal Changes</summary> ##### Fixed - **ci**: Align pr.yml E2E with --dist loadscope ([#​1206](homeassistant-ai/ha-mcp#1206)) ([#​1247](homeassistant-ai/ha-mcp#1247)) - **ci**: Switch Renovate to a GitHub App token to allow workflow-file pushes ([#​1229](homeassistant-ai/ha-mcp#1229)) - **ci**: Break gemini-triage retrigger loop and bump turn budget ([#​1131](homeassistant-ai/ha-mcp#1131)) - **ci**: Harden gemini-triage so failures stop spamming user issues ([#​1122](homeassistant-ai/ha-mcp#1122)) - **ci**: Unbreak hotfix-release semantic-release run ([#​1091](homeassistant-ai/ha-mcp#1091)) ##### Chores - **addon**: Publish dev addon version 7.4.1.dev299 \[skip ci] ([`397aa6d`](homeassistant-ai/ha-mcp@397aa6d)) - **addon**: Publish dev addon version 7.4.1.dev298 \[skip ci] ([`942b7e0`](homeassistant-ai/ha-mcp@942b7e0)) - Sync tool docs after merge \[skip ci] ([`6823c47`](homeassistant-ai/ha-mcp@6823c47)) - **addon**: Publish dev addon version 7.4.1.dev297 \[skip ci] ([`6eac062`](homeassistant-ai/ha-mcp@6eac062)) - **addon**: Publish dev addon version 7.4.1.dev296 \[skip ci] ([`b2afe93`](homeassistant-ai/ha-mcp@b2afe93)) - **addon**: Publish dev addon version 7.4.1.dev295 \[skip ci] ([`4f4c4f3`](homeassistant-ai/ha-mcp@4f4c4f3)) - **deps**: Update ghcr.io/home-assistant/home-assistant docker tag to v2026.5.1 ([#​1236](homeassistant-ai/ha-mcp#1236)) - **addon**: Publish dev addon version 7.4.1.dev294 \[skip ci] ([`fd24991`](homeassistant-ai/ha-mcp@fd24991)) - **deps**: Update ghcr.io/astral-sh/uv docker tag to v0.11.13 ([#​1233](homeassistant-ai/ha-mcp#1233)) - **addon**: Publish dev addon version 7.4.1.dev293 \[skip ci] ([`fcc6496`](homeassistant-ai/ha-mcp@fcc6496)) - **addon**: Publish dev addon version 7.4.1.dev292 \[skip ci] ([`2961650`](homeassistant-ai/ha-mcp@2961650)) - **addon**: Publish dev addon version 7.4.1.dev291 \[skip ci] ([`5703112`](homeassistant-ai/ha-mcp@5703112)) - **addon**: Publish dev addon version 7.4.1.dev290 \[skip ci] ([`19b2f65`](homeassistant-ai/ha-mcp@19b2f65)) - **addon**: Publish dev addon version 7.4.1.dev289 \[skip ci] ([`e5a1365`](homeassistant-ai/ha-mcp@e5a1365)) - Sync tool docs after merge \[skip ci] ([`d2ff93b`](homeassistant-ai/ha-mcp@d2ff93b)) - **addon**: Publish dev addon version 7.4.1.dev288 \[skip ci] ([`0f62400`](homeassistant-ai/ha-mcp@0f62400)) - Sync tool docs after merge \[skip ci] ([`c7e2066`](homeassistant-ai/ha-mcp@c7e2066)) - **addon**: Publish dev addon version 7.4.1.dev287 \[skip ci] ([`c1133d4`](homeassistant-ai/ha-mcp@c1133d4)) - **addon**: Publish dev addon version 7.4.1.dev286 \[skip ci] ([`1ae790e`](homeassistant-ai/ha-mcp@1ae790e)) - **addon**: Publish dev addon version 7.4.1.dev285 \[skip ci] ([`2387d0c`](homeassistant-ai/ha-mcp@2387d0c)) - **addon**: Publish dev addon version 7.4.1.dev284 \[skip ci] ([`dd3a4a5`](homeassistant-ai/ha-mcp@dd3a4a5)) - **addon**: Publish dev addon version 7.4.1.dev283 \[skip ci] ([`78af8eb`](homeassistant-ai/ha-mcp@78af8eb)) - Sync tool docs after merge \[skip ci] ([`093fd74`](homeassistant-ai/ha-mcp@093fd74)) - **addon**: Publish dev addon version 7.4.1.dev282 \[skip ci] ([`2141e15`](homeassistant-ai/ha-mcp@2141e15)) - Sync tool docs after merge \[skip ci] ([`7810c95`](homeassistant-ai/ha-mcp@7810c95)) - **addon**: Publish dev addon version 7.4.1.dev281 \[skip ci] ([`7d79ec2`](homeassistant-ai/ha-mcp@7d79ec2)) - Sync tool docs after merge \[skip ci] ([`a73dc81`](homeassistant-ai/ha-mcp@a73dc81)) - **addon**: Publish dev addon version 7.4.1.dev280 \[skip ci] ([`c858ce3`](homeassistant-ai/ha-mcp@c858ce3)) - Sync tool docs after merge \[skip ci] ([`a587be0`](homeassistant-ai/ha-mcp@a587be0)) - **addon**: Publish dev addon version 7.4.1.dev279 \[skip ci] ([`b78ddb2`](homeassistant-ai/ha-mcp@b78ddb2)) - Sync tool docs after merge \[skip ci] ([`1210725`](homeassistant-ai/ha-mcp@1210725)) - **addon**: Publish dev addon version 7.4.1.dev278 \[skip ci] ([`a282c17`](homeassistant-ai/ha-mcp@a282c17)) - **addon**: Publish dev addon version 7.4.1.dev277 \[skip ci] ([`1081768`](homeassistant-ai/ha-mcp@1081768)) - Sync tool docs after merge \[skip ci] ([`e03f5d2`](homeassistant-ai/ha-mcp@e03f5d2)) - **addon**: Publish dev addon version 7.4.1.dev276 \[skip ci] ([`c4ef680`](homeassistant-ai/ha-mcp@c4ef680)) - **addon**: Publish dev addon version 7.4.1.dev275 \[skip ci] ([`780422d`](homeassistant-ai/ha-mcp@780422d)) - Sync tool docs after merge \[skip ci] ([`8a2bd1a`](homeassistant-ai/ha-mcp@8a2bd1a)) - **addon**: Publish dev addon version 7.4.1.dev274 \[skip ci] ([`f0f09de`](homeassistant-ai/ha-mcp@f0f09de)) - **addon**: Publish dev addon version 7.4.1.dev273 \[skip ci] ([`cb49f68`](homeassistant-ai/ha-mcp@cb49f68)) - **addon**: Publish dev addon version 7.4.1.dev272 \[skip ci] ([`5097186`](homeassistant-ai/ha-mcp@5097186)) - **addon**: Publish dev addon version 7.4.1.dev271 \[skip ci] ([`4714342`](homeassistant-ai/ha-mcp@4714342)) - **addon**: Publish dev addon version 7.4.1.dev270 \[skip ci] ([`217982a`](homeassistant-ai/ha-mcp@217982a)) - **addon**: Publish dev addon version 7.4.1.dev269 \[skip ci] ([`a65dd5f`](homeassistant-ai/ha-mcp@a65dd5f)) - Sync tool docs after merge \[skip ci] ([`0e6b54f`](homeassistant-ai/ha-mcp@0e6b54f)) - **addon**: Publish dev addon version 7.4.1.dev268 \[skip ci] ([`60ba1f2`](homeassistant-ai/ha-mcp@60ba1f2)) - **addon**: Publish dev addon version 7.4.1.dev267 \[skip ci] ([`13412aa`](homeassistant-ai/ha-mcp@13412aa)) - Sync tool docs after merge \[skip ci] ([`2702a0f`](homeassistant-ai/ha-mcp@2702a0f)) - **addon**: Publish dev addon version 7.4.1.dev266 \[skip ci] ([`77abe0b`](homeassistant-ai/ha-mcp@77abe0b)) - **addon**: Publish dev addon version 7.4.1.dev265 \[skip ci] ([`08b69db`](homeassistant-ai/ha-mcp@08b69db)) - Sync tool docs after merge \[skip ci] ([`c1f24b5`](homeassistant-ai/ha-mcp@c1f24b5)) - **addon**: Publish dev addon version 7.4.1.dev264 \[skip ci] ([`f2583f6`](homeassistant-ai/ha-mcp@f2583f6)) - Sync tool docs after merge \[skip ci] ([`c2ed2d3`](homeassistant-ai/ha-mcp@c2ed2d3)) - **addon**: Publish dev addon version 7.4.1.dev263 \[skip ci] ([`9d43e54`](homeassistant-ai/ha-mcp@9d43e54)) - **addon**: Publish dev addon version 7.4.1.dev262 \[skip ci] ([`a7355c8`](homeassistant-ai/ha-mcp@a7355c8)) - Sync tool docs after merge \[skip ci] ([`085bd8a`](homeassistant-ai/ha-mcp@085bd8a)) - Convert agents to skills ([#​1084](homeassistant-ai/ha-mcp#1084)) - **addon**: Publish dev addon version 7.4.1.dev261 \[skip ci] ([`0d1af36`](homeassistant-ai/ha-mcp@0d1af36)) - **addon**: Publish dev addon version 7.4.1.dev260 \[skip ci] ([`29397dc`](homeassistant-ai/ha-mcp@29397dc)) - **addon**: Publish dev addon version 7.4.1.dev259 \[skip ci] ([`4bbc74b`](homeassistant-ai/ha-mcp@4bbc74b)) - Sync tool docs after merge \[skip ci] ([`0f6d41e`](homeassistant-ai/ha-mcp@0f6d41e)) - **addon**: Publish dev addon version 7.4.1.dev258 \[skip ci] ([`6751d08`](homeassistant-ai/ha-mcp@6751d08)) - **addon**: Publish dev addon version 7.4.1.dev257 \[skip ci] ([`2213c89`](homeassistant-ai/ha-mcp@2213c89)) - **addon**: Publish dev addon version 7.4.1.dev256 \[skip ci] ([`18a366e`](homeassistant-ai/ha-mcp@18a366e)) - **addon**: Publish dev addon version 7.4.1.dev255 \[skip ci] ([`0e9b18d`](homeassistant-ai/ha-mcp@0e9b18d)) - **addon**: Publish dev addon version 7.4.1.dev254 \[skip ci] ([`39fc65b`](homeassistant-ai/ha-mcp@39fc65b)) - Sync tool docs after merge \[skip ci] ([`9fa0aea`](homeassistant-ai/ha-mcp@9fa0aea)) - **addon**: Publish dev addon version 7.4.1.dev253 \[skip ci] ([`0dcc59e`](homeassistant-ai/ha-mcp@0dcc59e)) - Sync tool docs after merge \[skip ci] ([`ec7413f`](homeassistant-ai/ha-mcp@ec7413f)) - **addon**: Publish dev addon version 7.4.1.dev252 \[skip ci] ([`345640c`](homeassistant-ai/ha-mcp@345640c)) - **addon**: Publish dev addon version 7.4.1.dev251 \[skip ci] ([`bab9d49`](homeassistant-ai/ha-mcp@bab9d49)) - Sync tool docs after merge \[skip ci] ([`726f0a5`](homeassistant-ai/ha-mcp@726f0a5)) - **addon**: Publish dev addon version 7.4.1.dev250 \[skip ci] ([`ded04ea`](homeassistant-ai/ha-mcp@ded04ea)) - **addon**: Publish dev addon version 7.4.1.dev249 \[skip ci] ([`37d5628`](homeassistant-ai/ha-mcp@37d5628)) - **addon**: Publish dev addon version 7.4.1.dev248 \[skip ci] ([`530786a`](homeassistant-ai/ha-mcp@530786a)) - Sync tool docs after merge \[skip ci] ([`36719c3`](homeassistant-ai/ha-mcp@36719c3)) - **addon**: Publish dev addon version 7.4.1.dev247 \[skip ci] ([`4dc47b5`](homeassistant-ai/ha-mcp@4dc47b5)) - **addon**: Publish dev addon version 7.4.1.dev246 \[skip ci] ([`6ffbd6a`](homeassistant-ai/ha-mcp@6ffbd6a)) - Sync tool docs after merge \[skip ci] ([`add66e3`](homeassistant-ai/ha-mcp@add66e3)) - **addon**: Publish dev addon version 7.4.1.dev245 \[skip ci] ([`d0114af`](homeassistant-ai/ha-mcp@d0114af)) - Sync tool docs after merge \[skip ci] ([`0ca41af`](homeassistant-ai/ha-mcp@0ca41af)) - **addon**: Publish dev addon version 7.4.1.dev244 \[skip ci] ([`d052dd0`](homeassistant-ai/ha-mcp@d052dd0)) - **addon**: Publish dev addon version 7.4.0.dev243 \[skip ci] ([`827bc65`](homeassistant-ai/ha-mcp@827bc65)) - Bump package version to 7.4.1 to match released addon ([`4f65497`](homeassistant-ai/ha-mcp@4f65497)) - **addon**: Publish dev addon version 7.4.0.dev242 \[skip ci] ([`8ba80ae`](homeassistant-ai/ha-mcp@8ba80ae)) - **addon**: Publish hotfix version 7.4.1 ([`bda75e6`](homeassistant-ai/ha-mcp@bda75e6)) - **addon**: Publish dev addon version 7.4.0.dev241 \[skip ci] ([`2126428`](homeassistant-ai/ha-mcp@2126428)) ##### Continuous Integration - **deps**: Bump renovatebot/github-action in the github-actions group ([#​1218](homeassistant-ai/ha-mcp#1218)) - **deps**: Bump renovatebot/github-action in the github-actions group ([#​1111](homeassistant-ai/ha-mcp#1111)) ##### Refactoring - Extract \_fetch\_dashboards\_list helper ([#​1193](homeassistant-ai/ha-mcp#1193)) ([#​1207](homeassistant-ai/ha-mcp#1207)) ##### Testing - **e2e**: Module-scope bulk\_automations + bulk\_scripts fixtures (refs [#​366](homeassistant-ai/ha-mcp#366)) ([#​1275](homeassistant-ai/ha-mcp#1275)) - **e2e**: Lower INPUT\_BOOLEAN\_WAIT from 30s to 10s (refs [#​366](homeassistant-ai/ha-mcp#366)) ([#​1273](homeassistant-ai/ha-mcp#1273)) - **e2e**: Generalize readiness-gate diagnostics helper (closes [#​1267](homeassistant-ai/ha-mcp#1267)) ([#​1271](homeassistant-ai/ha-mcp#1271)) - **e2e**: Narrow except clauses in e2e polling helpers (closes [#​1266](homeassistant-ai/ha-mcp#1266)) ([#​1270](homeassistant-ai/ha-mcp#1270)) - **e2e**: Drop ha\_mcp\_tools retry-path + pre-install manifest requirements ([#​1268](homeassistant-ai/ha-mcp#1268)) - **e2e**: Instrument and retry ha\_mcp\_tools readiness wait ([#​1262](homeassistant-ai/ha-mcp#1262)) - Use time.monotonic() in UAT runner and test\_env\_manager ([#​1254](homeassistant-ai/ha-mcp#1254)) - **e2e**: Detect partial/corrupt hacs\_frontend dir in fast-path guard ([#​1253](homeassistant-ai/ha-mcp#1253)) - **e2e**: Remove unused wait/assert helpers ([post-#​1249](https://github.com/post-/ha-mcp/issues/1249) audit) ([#​1256](homeassistant-ai/ha-mcp#1256)) - **e2e**: Clear stale .hacs\_frontend.lock from prior crashed runs ([#​1252](homeassistant-ai/ha-mcp#1252)) - **e2e**: Use time.monotonic() in workflow polling loops ([#​1258](homeassistant-ai/ha-mcp#1258)) - **e2e**: Use time.monotonic() for duration polling ([#​1234](homeassistant-ai/ha-mcp#1234)) ([#​1249](homeassistant-ai/ha-mcp#1249)) - **e2e**: Close ARM ha\_mcp\_tools readiness race under loadscope ([#​1208](homeassistant-ai/ha-mcp#1208)) - **hacs**: Tighten is\_hacs\_unavailable to not match legitimate "Repository not found" ([#​1246](homeassistant-ai/ha-mcp#1246)) - **seed**: Unblock 3 silent-skip pagination/state tests via baked recorder DB ([#​1240](homeassistant-ai/ha-mcp#1240)) - **seed**: Register a writable local\_calendar to unblock event-creation test ([#​1243](homeassistant-ai/ha-mcp#1243)) - **addon**: Fix base64 padding-bit flake in token tamper tests ([#​1238](homeassistant-ai/ha-mcp#1238)) ([#​1241](homeassistant-ai/ha-mcp#1241)) - **seed**: Add a writable scene for test\_call\_service\_scene\_turn\_on ([#​1231](homeassistant-ai/ha-mcp#1231)) - **seed**: Assign demo device to living\_room area for filter test ([#​1230](homeassistant-ai/ha-mcp#1230)) - **e2e**: Drop nonexistent sun service from session readiness wait ([#​1227](homeassistant-ai/ha-mcp#1227)) - **e2e**: Self-contain dashboard register/remove to fix ARM xdist race ([#​1196](homeassistant-ai/ha-mcp#1196)) ([#​1201](homeassistant-ai/ha-mcp#1201)) - Fix EN dash in docstring causing RUF002 lint failure ([`eac5916`](homeassistant-ai/ha-mcp@eac5916)) - Address Gemini review feedback on host detection and port allocation ([`960305e`](homeassistant-ai/ha-mcp@960305e)) - Fix three categories of E2E test flakiness ([`39417ff`](homeassistant-ai/ha-mcp@39417ff)) - **e2e**: Pin config\_hash stability for dashboards ([#​1132](homeassistant-ai/ha-mcp#1132)) </details> </details> --- ### Configuration 📅 **Schedule**: (in timezone America/New_York) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about these updates again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNjAuNyIsInVwZGF0ZWRJblZlciI6IjQzLjE2MC43IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJyZW5vdmF0ZS9jb250YWluZXIiLCJ0eXBlL21pbm9yIl19--> Co-authored-by: todd <tpunderson@greyrock.io> Reviewed-on: https://git.greyrock.io/greyrock-labs/home-ops/pulls/26
… non-addon installs (#1283) * fix: HA Core proxy fallback for ha_get_logs(source=system_service) on non-addon installs Closes #1260. Pre-fix `_get_system_service_logs` had only the Supervisor-direct branch, so non-addon installs (the Docker image, uvx ha-mcp, pip-based deploys) fell straight through to the SUPERVISOR_TOKEN-absent fail-fast in `_supervisor_logs_get` for every system-service slug. Sibling `get_addon_logs` and `get_error_log` already had the `is_running_in_addon()` gate plus HA Core proxy fallback added in PR #1126; this PR closes the parallel gap. The reproduced symptom matched the issue exactly on a non-addon install (uvx ha-mcp pointed at a Supervisor-equipped HA): `source="supervisor"` worked via the existing Core proxy fallback, while `source="system_service"` with slug in {supervisor, host, core} returned AUTH_INVALID_TOKEN with the misleading "addon-mode gate fired but SUPERVISOR_TOKEN env var not set" message. Once the gate is added, that fail-fast string is accurate again because the only callers reaching it are addon-mode-confirmed. Verified the proxy path is reachable for all seven service slugs by reading HA Core's `homeassistant/components/hassio/http.py` — PATHS_ADMIN whitelists `{audio,cli,core,dns,host,multicast,observer,supervisor}/logs` plus `addons/{slug}/logs`. Admin LLA is sufficient. (HA Core also proxies `cli/logs`, which ha-mcp's SYSTEM_SERVICE_SLUGS doesn't include — leaving that out as scope for a separate PR if anyone wants CLI logs surfaced.) Tests: new TestGetSystemServiceLogsBranchSelection class mirrors the existing TestGetAddonLogsBranchSelection / TestGetErrorLogBranchSelection shape — non-addon branch parametrized over all seven slugs, plus an addon-branch test that proxy is not called. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * test(rest_client): Accept header + 404 path on system_service non-addon branch Two parity additions in TestGetSystemServiceLogsBranchSelection, per PR review by pr-test-analyzer: - Parametrized happy-path test now asserts `Accept: text/plain` on the proxy request. Without it the HA Core proxy negotiates application/json and the body stops being raw log text (same silent-failure signature #950 describes one layer up). - New `test_non_addon_install_404_raises_api_error_with_service_context` anchors the live "observer returned 404 on hubs that don't run it" case from the #1260 end-to-end verification. Guards against a future refactor wrapping the proxy call in a swallow-and-return-empty try/except in `_get_system_service_logs`. Parallels `TestGetAddonLogs::test_raises_api_error_on_404_with_slug_context`. 64 tests pass in this file (was 63), ruff clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(get_logs): branch-aware error suggestions + add cli to system_service slugs Two follow-ons from the PR #1283 review, both addressing review findings that were initially deferred as "future improvements" but are real behavior issues introduced or exposed by this PR's branch split: 1. Branch-aware wrapper suggestions in tools_utility.py: Pre-fix, the AuthError and 403 branches in `_get_supervisor_log` and `_get_system_service_log` always emitted SUPERVISOR_TOKEN/hassio_role hints — useless on non-addon installs that hit the new HA Core proxy path. With #1283's gate-and-fallback split, the wrapper now gates on `is_running_in_addon()` and picks branch-appropriate suggestions: - In-addon AuthError → "Verify SUPERVISOR_TOKEN..." (unchanged) - Non-addon AuthError → "Verify HOMEASSISTANT_TOKEN is a valid admin Long-Lived Access Token..." - In-addon 403 (system_service) → "Addon's hassio_role must be 'manager'..." (unchanged) - Non-addon 403 (system_service) → "The LLA must belong to an admin..." Same shape applied to `_get_supervisor_log` so source="supervisor" doesn't have the same dead-end advice on Docker/uvx installs either. 2. Add `cli` to SYSTEM_SERVICE_SLUGS: HA Core's hassio HTTP proxy already whitelists `cli/logs` in PATHS_ADMIN. Adding the slug surfaces Supervisor CLI logs via the same routes #1116 set up for the other seven services. Eight slugs total now. Tests: - Parametrized non-addon proxy test extended to 8 slugs (cli added) - `test_all_seven_allowed_services_dispatch` renamed → `_all_allowed_`, extended to 8 slugs - Existing `test_403_role_hint_suggestion` renamed to clarify it's the in-addon case + explicit `is_running_in_addon` mock added - 5 new tests pinning the branch-aware suggestion behavior (in-addon AuthError, non-addon AuthError, non-addon 403) on both wrappers - Supervisor mock updated to recognize the 8-slug set - Backtick consistency in TestGetAddonLogsBranchSelection + TestGetSystemServiceLogsBranchSelection class docstrings, per comment-analyzer S3 71 unit tests pass in test_tools_utility_supervisor_logs.py (was 63 pre-PR, 64 after first review-pass test additions). Ruff clean across all touched files. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: kingpanther13 <kingpanther13@users.noreply.github.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
What does this PR do?
Closes #1116. On add-on installs,
ha_get_logs(source="supervisor", slug=...)returns 403 for every slug because HA Core rejects theSUPERVISOR_TOKENagainst the proxy route/api/hassio/addons/{slug}/logs. Route around HA Core entirely on add-on installs by hitting the documented Supervisor REST API athttp://supervisor/addons/{slug}/logsdirectly with the Supervisor token — same access patterntools_bug_report.py:_fetch_addon_logsalready uses for self-logs.The HA-Core-proxy path stays as the fallback for non-addon installs (Docker, pyinstaller, pip pointing at a normal HA URL with admin LLA), where it continues to work fine. The bug only manifests on the addon-container call against
http://supervisor/core.Branching gate is the existing
is_running_in_addon()helper insrc/ha_mcp/_version.py— no fourth duplicate of theSUPERVISOR_TOKENenv-var check.Companion config change —
hassio_role: default → managerKP13 verified locally that the Supervisor token does not grant
/addons/{slug}/logs(or/{service}/logs) access on thedefaultrole. Bumped tomanagerin bothhomeassistant-addon/config.yamlandhomeassistant-addon-dev/config.yaml, with an inline comment citing the live test.Scope addition —
source="system_service"KP13's PR-comment 12:42 surfaced that #1116 also covers the missing-feature case: HA-Supervisor-managed system service logs (
/supervisor/logs,/host/logs,/core/logs,/dns/logs,/audio/logs,/multicast/logs,/observer/logs) were not reachable via any source value. Added a newsource="system_service"value matching KP13's data-type-named source convention (#911 / #1003).slugsemantics forsource="system_service": a service name fromSYSTEM_SERVICE_SLUGS = {supervisor, host, core, dns, audio, multicast, observer}. Caller-layer enum validation gives users the allowed set before the request fires.sourceparameter disambiguates:slug="supervisor"undersource="system_service"means the Supervisor service's own logs, not an add-on with that name. Docstring lists both slug semantics separately._get_system_service_logs(service)extracted to a shared_supervisor_logs_get(path)helper alongside_get_addon_logs_via_supervisor; both branches now share error handling, JSON-envelope parsing, role-hint 403 messaging, and the fail-fast empty-token guard.KP13 CR disposition (16 of 17 adopted)
HomeAssistantAuthErrorwith distinct "absent at call time" message>=400with role-hint suggestion_get_supervisor_logdocstringis_running_in_addon()_fetch_addon_logs" framingself) + role (manager vs default) differencesverify_sslno-op forhttp://supervisorjson.loads(text_body).get("message")first, then text/reason_phrase fallback"Timeout..."/"Transport error..."messageslevelparam applies tosource="supervisor"tools_utility.py:139—supervisoris in the level-not-applicable warning tuple, pinned bytest_level_param_emits_warning_for_supervisor_source. PR addssystem_serviceto the same tuple + parallel test for paritylogger.warningon>=400raise pathtest_raises_auth_error_on_empty_supervisor_token+ parallel for system_servicetest_raises_connection_error_on_remote_protocol_errortest_empty_body_no_reason_phrase_uses_placeholderverify+timeoutasserted on the URL+auth happy-path testtest_addon_install_uses_supervisor_directmock-the-mockpatch("httpx.AsyncClient", ...)— robust to eitherimport httpxorfrom httpx import AsyncClientis_running_in_addon(), not "SUPERVISOR_TOKEN env present"Test coverage
tests/src/unit/test_tools_utility_supervisor_logs.pyTestGetAddonLogsViaSupervisor(extended)TestGetSystemServiceLogs(new)TestGetSystemServiceLogWrapper(new)TestGetAddonLogsBranchSelection(modified)Local: 1703 unit tests pass, ruff clean, mypy clean.
Out of scope
The issue body asks for an integration/contract test against a real Supervisor-equipped HA. The existing E2E suite uses a Supervisor-less
homeassistant/home-assistanttestcontainer; spinning up a Supervisor side-car is outside this PR. Filing as a Suggested Improvement.Round 3 —
error_log+ slug warning + role docs (commita49dbc3)KP13's round-2 review surfaced three more items addressed in
a49dbc3:source="error_log"is broken on Supervisor installs — same root cause as [BUG] ha_get_logs(source="supervisor") returns 403 for every slug on add-on installs #1116. HA Core'sbootstrap.py:641-651setserr_log_path = Nonewhen theSUPERVISORenv var is present, sohass.data[DATA_LOGGING]is never populated and theAPIErrorLogview is not registered (/api/error_log→ 404 by-design). Fix shape mirrorsget_addon_logs: branchHomeAssistantClient.get_error_log()onis_running_in_addon()→_supervisor_logs_get("core")for the addon branch (HA Core's container log via Supervisor — same content, different transport). Pinned byTestGetErrorLogBranchSelection.slugparameter incompatibility warning — third warning intools_utility.ha_get_logs, parallels the existinglevelandentity_id/end_timewarnings. Pinned byTestSlugParameterIncompatibilityWarningparametrized over four non-supervisor sources (warn) and two supervisor sources (no warn).### Supervisor Permissionssection inhomeassistant-addon/DOCS.md, plus### Permissionssubsection inhomeassistant-addon-dev/DOCS.md, calling out thehassio_role: managerrequirement.Local: 1711 unit tests pass, ruff clean.
Type of change
Testing
uv run pytest)uv run ruff check)Checklist
Closes #1116