test(e2e): measure _POLL_CADENCE p50/p99 to validate or retune (closes #1389) - #1398
Conversation
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 implements a measurement protocol to validate the effectiveness of the current 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 the 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 counterproductive. 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
|
There was a problem hiding this comment.
Code Review
This pull request adds latency instrumentation to the REST client and introduces a new E2E test to validate polling cadence percentiles for issue #1389. Review feedback identifies an inaccuracy in a code comment regarding ID filtering and suggests refining the percentile calculation for small sample sizes to ensure the p99 metric correctly accounts for outliers.
Implementation SummaryRefs #1389. Delivers the measurement infrastructure for the pre-committed decision rule on Choices Made
Problems Encountered
Measurement ResultAcross the two
All 20 samples land in a Suggested Improvements (follow-ups, not blockers)
|
kingpanther13
left a comment
There was a problem hiding this comment.
Measurement scaffolding is in the right shape (instrumentation + xdist-aware terminal-summary plumbing mirroring _READINESS_TIMINGS). Three blockers, four should-fix, comment subtractions.
Blocking
1. not_verified_count is dead — verdict can silently falsely report VALIDATED.
src/ha_mcp/tools/tools_config_automations.py:776 pops entity_not_verified off the result before it returns and translates it into a warnings string ("Automation was submitted to Home Assistant but the entity was not found after polling…"). So create_data.get("entity_not_verified") in test_poll_cadence_measurement.py:86 is always None, not_verified_count is always 0, no_misses is always True. A run where every cadence step exhausted would still print VERDICT=VALIDATED if the captured DEBUG records happened to be empty — and combined with #4, assert samples is the only thing catching all-misses today.
Detect a miss by scanning create_data.get("warnings", []) for the sentinel substring, or check create_data.get("entity_id") is None alongside success=True.
2. PR body says Refs #1389 — issue won't auto-close on merge.
GitHub only documents closing-keyword recognition in the body and commits on the default branch. Title closing-keywords are folklore. Replace Refs #1389. with Closes #1389. in the PR description.
3. "Suggested Improvements (follow-ups, not blockers)" defers exactly what AGENTS.md says to fold in.
The retune to _POLL_CADENCE = (0.025, 1.0, 4.975) is 3 numbers, justified by the measurement table this PR produced, and the verdict line that drove the retune was emitted by this PR's own test. Per the Boy Scout Rule, fold the retune into this PR — it then is the PR that closes #1389. The "ships as a separate PR" framing splits one logical unit across two PRs for no benefit and leaves master in a verdict=RETUNE NEEDED, cadence unchanged state if the retune PR slips.
The HAOS E2E flake item ("Out of scope here; worth its own issue if it persists") uses the exact escape-hatch phrasing AGENTS.md flags. The fix you describe is small — a wait_for_addon_state("started") guard or _wait_addon_running helper before the strict-shape assertion. That's classic Boy Scout: discovered during this PR's CI runs, trivially small, mechanical mirror of an existing pattern. Fold it in here, don't defer.
Rename the section and land both items in this PR.
Should-fix
4. assert samples only catches zero-capture; partial captures silently skew percentiles. test_poll_cadence_measurement.py:103-107
If 9 iterations succeed and 1 misses, the assert passes with n=9 and reports p50/p99 over those 9 — and combined with #1, the miss is invisible. After parsing samples, add:
assert len(samples) + not_verified_count == self.N_SAMPLES, (
f"sample-count invariant violated: {len(samples)} samples + "
f"{not_verified_count} misses != {self.N_SAMPLES} attempts"
)Pair with #1 — miss-detection has to be real for this assert to be real.
5. The field labelled p99 is actually max for N=10. test_poll_cadence_measurement.py:114-118
The inline comment justifies the index-collapse, but the recorded dict key, the pytest_terminal_summary output, and the decision-rule line all call it p99. The closure-vs-retune decision rides on this number — name it for what it is. Rename to worst / p99_or_max in both writer and reader, or compute statistics.quantiles(samples, n=100, method="inclusive")[98] and surface max separately (already in the dict).
6. cleanup_tracker.track() is a no-op fixture. tests/src/e2e/conftest.py:1937-1942
The fixture's teardown only logs "Would clean up…" — there's no real delete. This test creates 10 automation.poll_cadence_measurement_1389_NN per run; on --dist loadscope they persist for the worker's lifetime. Pre-existing fixture defect, but this test is now the largest single producer. Either add an explicit try/finally in the test that calls ha_config_remove_automation per entity, or fix the fixture to actually delete — both qualify as in-scope cleanup for this PR.
7. caplog.set_level(DEBUG, logger="ha_mcp.client.rest_client") is sticky across tests on the same worker. test_poll_cadence_measurement.py:60-67
The docstring's "per-test-method-scoped" framing is correct for caplog.records but not for set_level — that mutates the worker's logger level. Every later test on the same xdist worker captures rest_client DEBUG at full volume until the worker exits. Use caplog.at_level(logging.DEBUG, logger="ha_mcp.client.rest_client") as a context manager around just the create-loop, or save/restore the prior level in a finally.
Nits
8. Comment subtractions — the PR is comment-heavy; a few earn nothing:
test_poll_cadence_measurement.py:68-70— duplicates thecaplog.clear()rationale from lines 60-66.test_poll_cadence_measurement.py:124-127— restates the decision-rule thresholds the code on the next line already says.conftest.py:92-98— the xdist-conftest-loading mechanism explanation is slightly inaccurate (xdist's master loads all conftests; the real point is shared module-level state). Trim to one sentence cross-referencing_READINESS_TIMINGS.record_poll_cadence_measurementdocstring (conftest.py:100-107) — the key list will rot on schema change; the call site is the source of truth.
9. N=10 + cadence (0.1, 1.0, 4.9) puts the decision boundary right at a cadence step. One late-sample run can flip VERDICT between VALIDATED and RETUNE for the same underlying behavior. With #5 fixed (renaming p99→worst), N=10 is fine for worst; if you keep the p99 < 1000ms rule, raise N to ~50 for boundary stability. (The retune in #3 collapses this concern anyway — at _POLL_CADENCE[0] = 0.025s the boundary moves far away from the cadence step.)
Verified clean
- Log-format migration from f-string to
%-style is correct (deferred formatting); zero downstream references to the old "Found actual entity_id" text. pytest_testnodedownlocal-variable hoist is a readability win, not scope creep.external_onlymarker skip is correct — inaddon mode runs rest_client in a separate process where caplog can't reach it._POLL_CADENCE_MEASUREMENTSxdist round-trip mirrors_READINESS_TIMINGSexactly.start_monotonicplacement outside the try block is fine — failed registrations correctly produce no log line.
- entity_not_verified detection via warnings-substring scan (homeassistant-ai#1297-popped flag was dead — VERDICT=VALIDATED could leak silently) - sample-count invariant: len(samples) + not_verified == N_SAMPLES - rename "p99" -> "worst" (at N=10 the percentile collapses to max; the threshold-check name now reflects what it measures) - per-test try/finally cleanup: cleanup_tracker is a logging-only no-op, so 10 automations were leaking into the next worker run - caplog.at_level context manager (set_level mutated worker-wide level and leaked DEBUG-on-rest_client into every later test) - 6 comment subtractions per Boy-Scout Boy-Scout fold per homeassistant-ai#1389 measurement (RETUNE NEEDED p50>=100ms): - _POLL_CADENCE: (0.1, 1.0, 4.9) -> (0.025, 1.0, 4.975) — first-poll pulled to a 5x cushion above the measured ~4ms HA-Core entity-registration latency - unit-test pins updated to the new cadence values - test_proxy_http_request_headers_pass_through: add _wait_for_state helper + guard for state="started" (HAOS E2E fail: Node-RED was in "startup" when the strict status_code assertion ran) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Addressed in ab152e9. PR body updated Blocking1. 2. PR body 3. Boy-Scout fold — both items folded in.
Should-fix4. Sample-count invariant — 5. 6. 7. Nits8. Comment subtractions — six regions trimmed.
9. N=10 boundary — resolved by 5's rename. No code change. On the verified-clean listLog-format CI on |
…homeassistant-ai#1389) homeassistant-ai#1389's pre-committed decision rule needs empirical p50/p99 numbers for automation-entity-registration latency on the post-homeassistant-ai#1384 cadence ``_POLL_CADENCE = (0.1, 1.0, 4.9)``. Two pieces: 1. ``rest_client._poll_for_automation_entity`` now emits a DEBUG line ``entity-registration-elapsed: %.1fms`` measuring cumulative time from function entry (right after the automation POST returns) to the first successful ``get_states()`` match. Always-on instrumentation, near-zero cost (one ``time.monotonic()`` pair per registration). 2. New e2e test ``TestPollCadenceMeasurement1389`` creates N=10 automations cold-start, captures the DEBUG records via ``caplog``, computes p50 / p90 / p99, and reports the table at INFO so it surfaces in CI logs (default ``log_cli_level=INFO``). The decision-rule outcome (``VALIDATED`` vs ``RETUNE NEEDED``) is logged as a machine-greppable ``VERDICT`` line. The test is report-only — no threshold assertion. CI latency variance from parallel pytest-xdist workers sharing one HA testcontainer makes a strict threshold assertion flaky. The decision rule is applied to the reported numbers via a PR comment after CI runs. Cumulative not-verified iterations (``_poll_for_automation_entity`` returning ``None`` after exhausting the 6.0s cadence) are themselves ``p99 ≥ 6000ms`` evidence and flip ``VERDICT`` to ``RETUNE`` regardless of the measured samples.
…surement Three fixes on the new ``test_poll_cadence_measurement.py``: 1. **Comment accuracy** (Gemini ``:51``). The prior comment claimed cross-test pollution was bounded by "registrations matched against the unique ID prefix below", but the parsing loop never filters by unique_id. The actual protection is that ``caplog`` is per-test- method-scoped — other tests' records don't appear in ``caplog.records`` here. Comment now describes the real mechanism. 2. **Percentile calculation** (Gemini ``:104``). For ``N=10``, ``int(0.99 * (n-1)) == 8`` collapses to the same index as p90, silently dropping the worst-case sample. ``p99`` is now ``samples[-1]`` so an outlier can't violate the decision-rule threshold without surfacing. ``p90`` formula simplified to ``int(0.9 * n) - 1`` (numerically identical for both ``N=10`` and typical larger N, just clearer reading). 3. **HAOS-inaddon skip**. Class now carries ``@pytest.mark.external_only`` because ``caplog`` only captures DEBUG records emitted in pytest's own process; on the HAOS-inaddon tier the rest_client lives in the addon's separate process and the records never reach ``caplog``. Without this marker the test fires its "No 'entity-registration-elapsed' DEBUG records captured" assertion as a false-negative — observed on the first CI run.
…mary hook ``logger.info`` from a test method is captured by pytest-xdist's per-worker buffer and only surfaces on FAILURE — the prior commit's PASSED run dropped the measurement table silently. Without the data, the homeassistant-ai#1389 pre-committed decision rule (p50 < 100ms ∧ p99 < 1.0s → close vs. retune) cannot be applied, defeating the PR's stated purpose. Mirrors the established ``Readiness gate timings`` pattern in ``tests/src/e2e/conftest.py`` (introduced for homeassistant-ai#1310, consolidated for homeassistant-ai#366): worker-side list → ``pytest_sessionfinish`` ships via ``workeroutput`` → ``pytest_testnodedown`` aggregates on master → ``pytest_terminal_summary`` renders a ``homeassistant-ai#1389 _POLL_CADENCE measurement`` section outside the per-worker capture buffer. - New ``tests/src/e2e/workflows/automation/conftest.py`` with the 3-hook pattern and a public ``record_poll_cadence_measurement(dict)`` helper. - Test method now calls the helper alongside the existing ``logger.info`` calls (kept for local-without-xdist runs). - CI logs will surface ``[POLL_CADENCE_1389] N=X/10 p50=… p99=… VERDICT=…`` lines that the IS / closing comment on homeassistant-ai#1389 cite directly.
…onftest The prior fold placed the ``pytest_sessionfinish`` / ``pytest_testnodedown`` / ``pytest_terminal_summary`` hooks at ``tests/src/e2e/workflows/automation/conftest.py``. CI re-ran cleanly, test passed, but the measurement section still didn't surface — the xdist master only loads conftests up to where tests are collected, and ``pytest_terminal_summary`` (which writes to the visible terminal) is a master-only hook. Deep subdir conftests don't get their hooks invoked on the master. The Readiness gate timings pattern works because its hooks live at ``tests/src/e2e/conftest.py`` (the root e2e conftest the master always loads). Same fix here: move the storage, the ``record_poll_cadence_measurement`` helper, and the three hook extensions to the root conftest alongside the readiness ones. The deep ``workflows/automation/conftest.py`` is removed; the measurement test imports the helper from the root.
…+ retune) - entity_not_verified detection via warnings-substring scan (homeassistant-ai#1297-popped flag was dead — VERDICT=VALIDATED could leak silently) - sample-count invariant: len(samples) + not_verified == N_SAMPLES - rename "p99" -> "worst" (at N=10 the percentile collapses to max; the threshold-check name now reflects what it measures) - per-test try/finally cleanup: cleanup_tracker is a logging-only no-op, so 10 automations were leaking into the next worker run - caplog.at_level context manager (set_level mutated worker-wide level and leaked DEBUG-on-rest_client into every later test) - 6 comment subtractions per Boy-Scout Boy-Scout retune from homeassistant-ai#1389 measurement (RETUNE NEEDED p50>=100ms): - _POLL_CADENCE: (0.1, 1.0, 4.9) -> (0.025, 1.0, 4.975) — first-poll pulled to a 5x cushion above the measured ~4ms HA-Core entity-registration latency - unit-test pins updated to the new cadence values The HAOS proxy-header flake item from KP13's review landed independently on master via homeassistant-ai#1402 (_wait_addon_running guard); intentionally not duplicated here. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ab152e9 to
f34ea9a
Compare
|
Correction on the bundled reply above — withdrawing the HAOS portion of item 3. Cross-reference audit caught that #1402 (your PR, merged 2026-05-21 21:43 UTC) had already landed the exact same fix on master: the Branch force-pushed to Substantive changes vs the previous push: 4 files changed (rest_client.py + conftest.py + measurement test + unit-test pins). The retune and the 8 other review items remain — only the HAOS helper + the per-test guard line came out. |
kingpanther13
left a comment
There was a problem hiding this comment.
Verifying f34ea9a7 against my prior review: all 8 items + retune land cleanly. Three new findings from the rewrite.
Should-fix
1. Cleanup except Exception diverges from the project's polling-helper pattern. tests/src/e2e/workflows/automation/test_poll_cadence_measurement.py:209
safe_call_tool only catches ToolError; everything else (TypeError, AttributeError, KeyError, etc.) becomes a logger.warning line and silently continues to the next iteration of the cleanup loop. AGENTS.md "Exception handling in polling helpers" and tests/src/e2e/utilities/wait_helpers.py (per #1266) establish the inverse: bugs MUST propagate out of polling loops with their stack trace, not be downgraded to warnings. Per-entity cleanup is the same shape — same "keep going past one bad iteration" intent, same risk of swallowing programmer bugs across 10 identical iterations.
Tighten to a narrow tuple analogous to _POLLING_TRANSIENT_ERRORS — something like (ToolError, OSError, TimeoutError, McpError) covering what safe_call_tool plus its transport layer would raise on a real HA-side cleanup failure (404 on already-removed entity, connection blip), not what a programmer typo would raise.
2. _NOT_VERIFIED_WARNING_PREFIX is coupled to source by comment only. test_poll_cadence_measurement.py:42
The literal lives in two places (tools_config_automations.py:770 and the test) with just an inline "Mirrors the literal" comment connecting them. If the warning copy is reworded in the source, the test silently slides to not_verified_count == 0. The sample-count invariant catches the resulting count mismatch and fails the test loud — so it's not a current silent failure — but the error ("9 samples + 0 not-verified != 10 attempts") wouldn't point at the wording drift. Lift the constant out of tools_config_automations.py (export it from the module, or put it in a shared constants location) and import it in the test — mechanical fix, makes the coupling a compile-time error instead of a test-runtime puzzle.
Nit
3. Cleanup-block comment calls cleanup_tracker "session-scoped". test_poll_cadence_measurement.py:197
The fixture is bare @pytest.fixture at tests/src/e2e/conftest.py:1951 — function-scoped, not session-scoped. The substantive point (fixture only logs, doesn't delete) is correct and load-bearing; just the scope label is wrong. Replace "session-scoped" with "logging-only" (matches the commit-message framing).
Otherwise verified clean
- Sentinel substring at
tools_config_automations.py:770matches_NOT_VERIFIED_WARNING_PREFIXexactly. p99→worstrename consistent across dict key, terminal-summary writer, decision-rule check, test method name. No lingeringp99selectors._POLL_CADENCE = (0.025, 1.0, 4.975)sums to 6.0; unit-test pins updated in all three sites (test_poll_cadence_shape, full-miss test, partial-attempt test).caplog.at_levelscope is right —caplog.recordssurvives the context-manager exit because pytest's caplog accumulates per-test, not per-block.- Sample-count invariant placement: inside
try:, afterassert samples, before thefinally:runs cleanup. AssertionError propagates correctly. ha_config_remove_automation(identifier=...)signature matches the tool definition.- Per-test cleanup runs only on external/testcontainer tiers where the tool is registered (external_only handles inaddon).
- All 4 targeted comment subtractions from the prior review are gone.
- PR body now uses
Closes #1389✓. - HAOS proxy-header flake landed via merged #1402 and is on the PR's rebased base.
… items) 1. Narrow cleanup-loop exception in test_poll_cadence_measurement.py from `except Exception` to `except _POLLING_TRANSIENT_ERRORS` (the canonical tuple from wait_helpers.py). Programmer bugs (TypeError, AttributeError, KeyError, AssertionError) now propagate with their stack trace instead of being downgraded to a `logger.warning` line across 10 iterations. Aligns per-entity cleanup with the polling-helper pattern established for AGENTS.md "Exception handling in polling helpers" (homeassistant-ai#1266). 2. Lift the soft-failure warning prefix out of tools_config_automations.py as module-level `NOT_VERIFIED_WARNING_PREFIX` and import it in the test. The literal coupling becomes a compile-time edge instead of a runtime puzzle — rewording the source warning now breaks the test import, replacing the previous "9 samples + 0 not-verified != 10 attempts" indirect signal with a clear ModuleNotFoundError-style failure. 3. Replace the stale `session-scoped` label in the cleanup-block comment with `logging-only` (matches the commit-message framing for the ``cleanup_tracker`` fixture, which is function-scoped per its `@pytest.fixture` decorator in tests/src/e2e/conftest.py:1951).
) Pre-existing format-debt on ``src/ha_mcp/tools/tools_config_automations.py`` became blocking once 4fd2852 added it to the PR's changed-files set — ``.github/workflows/pr.yml`` runs ``ruff format --check`` whole-file on every Python file in the PR diff, with the "grandfathered for untouched files" gate per the maintainer call on homeassistant-ai#1318. The 230-line diff on ``tools_config_automations.py`` is pure mechanical ``ruff format`` output: line-break placement on ``raise_tool_error(...)`` wrappers, multi-line argument splits, and dict-literal expansion. No logic, no semantic, no behavior change. Belongs to the homeassistant-ai#1318 sweep but has to land in this PR because the file is now in the touched set. The 1-line diff on ``test_poll_cadence_measurement.py`` (``isinstance(w, str) and w.startswith(...)`` collapsed to a single line) is the natural follow-on to the constant rename in 4fd2852 — the shorter name fits within 88 chars.
|
Addressed in 4fd2852, with a format-sweep follow-up at 376467b. Should-fix1. Cleanup Imported 2. Module-level constant defined in Nit3. "session-scoped" → "logging-only". Done. Matches the commit-message framing for the Format-sweep follow-up (376467b)Touching |
kingpanther13
left a comment
There was a problem hiding this comment.
All three items addressed cleanly:
_POLLING_TRANSIENT_ERRORSimport is the right tuple —(McpError, FastMCPError, ClientError, RuntimeError, OSError, TimeoutError)fromwait_helpers.py:28.TypeError/AttributeError/KeyError/AssertionErrorpropagate; transient transport/HA errors get the warn-and-continue. Private-symbol import is an established pattern in this repo (also used intest_manage_addon_modes.py:56).NOT_VERIFIED_WARNING_PREFIXis module-level public attools_config_automations.py:63, consumed via f-string at:781. Adjacent-string concat is byte-identical to the previous literal. Grep confirms a single emit site — no hardcoded-literal drift surface. Compile-time coupling achieved.- "session-scoped" → "logging-only" with propagation-intent expansion. Reads correctly.
Format-sweep 376467bc: AST-identical on both files (parsed both pre/post, byte-equal). No statement/argument/default/dict-key changes — pure layout. Test-file 1-line collapse is semantically unchanged.
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. |
…ired by this refactor The homeassistant-ai#1389/homeassistant-ai#1398 work added an e2e test (``test_poll_cadence_measurement.py``) plus xdist plumbing in ``tests/src/e2e/conftest.py`` (``record_poll_cadence_measurement``, ``_POLL_CADENCE_MEASUREMENTS`` + xdist worker handoff, terminal-summary section) to empirically validate ``_POLL_CADENCE``'s p50/p99/worst percentiles. That test consumed the ``entity-registration-elapsed`` DEBUG log line emitted by ``_poll_for_automation_entity`` on each successful registration. This PR removes both ``_POLL_CADENCE`` and the elapsed-time instrumentation: the cadence loop is replaced by the WS event-driven discovery helper, which resolves sub-second on the happy path without any cadence tuning needed. The measurement test is therefore consuming a log signal that no longer exists — CI fail signature is "No 'entity-registration-elapsed' DEBUG records captured after 10 automation creations." Deletes: - ``tests/src/e2e/workflows/automation/test_poll_cadence_measurement.py`` (207 lines) — entire test file. The cadence tuple it validates is gone. - ``record_poll_cadence_measurement()`` + ``_POLL_CADENCE_MEASUREMENTS`` / ``_ALL_POLL_CADENCE_MEASUREMENTS`` + xdist worker handoff in ``pytest_sessionfinish`` / ``pytest_testnodedown`` + the ``homeassistant-ai#1389 _POLL_CADENCE measurement`` terminal section in ``pytest_terminal_summary``. Also updates the ``NOT_VERIFIED_WARNING_PREFIX`` comment in ``tools_config_automations.py`` from "exhausts ``_POLL_CADENCE``" to "exhausts its budget (``_POLL_BUDGET_S``)" and drops the test-file reference, since the test that consumed the export is gone. Per Patch76's homeassistant-ai#1406 review note: "the deletion wins" — extending that to the e2e measurement infra that consumed the deleted instrumentation. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…loses #1395) (#1406) * refactor: route _poll_for_automation_entity through WS event waiter (closes #1395) Replaces the REST poll loop in ``HomeAssistantClient._poll_for_automation_entity`` with the WS event-driven discovery pattern PR #1382 landed for the ``wait_for_entity_*`` helpers. ``state_changed`` events for fresh-create automations carry ``new_state.attributes.id == unique_id`` because ``BaseAutomationEntity.capability_attributes`` exposes the unique_id as ``CONF_ID`` on every emit (HA Core, ``components/automation/__init__.py`` L454-459), so the same "subscribe → sample → wait" shape resolves discovery sub-second instead of waiting on the cadence loop. - ``_ws_wait_for_condition`` / ``_legacy_poll_until`` rename their internal ``entity_id`` parameter to ``identifier`` (log-only) so the helpers can serve discovery waits that don't know the entity_id up front. The signature for existing callers is positional-compatible. - ``_ws_wait_for_condition`` grows an optional ``event_filter`` parameter. When ``None`` (the existing callers) the default predicate matches ``data["entity_id"] == identifier`` — exactly the previous behaviour. Discovery callers pass a custom predicate. - New public helper ``wait_for_automation_entity_by_unique_id(client, unique_id, timeout=6.0, poll_interval=0.3)``. Subscribes to ``state_changed``, filters automation entities by ``new_state.attributes.id``, captures the discovered entity_id in a closure cell so the post-event sample short-circuits the full ``get_states()`` scan. Falls back to REST polling via the same ``_legacy_poll_until`` path the existing waiters use when the WS is unavailable. - ``_poll_for_automation_entity`` is now a thin wrapper that delegates to the new helper with a local import (mirroring the same circular- import workaround ``_get_waiter_ws_client`` uses). - ``_POLL_CADENCE: tuple[float, ...] = (0.1, 1.0, 4.9)`` is gone — vestigial once the WS happy path is the primary route — replaced by ``_POLL_BUDGET_S: float = 6.0`` preserving the 6s upper-bound budget PR #1384 tuned. REST fallback uses uniform polling at ``poll_interval``. - The ``except HomeAssistantError`` narrow catch is preserved so transient API errors surface as ``entity_not_verified=True`` and programming bugs (TypeError, etc.) propagate. - ``tests/src/unit/test_rest_client_automations.py``: ``TestPollForAutomationEntity`` replaced. Old tests pinned the cadence tuple and ``asyncio.sleep`` call shape — both gone with the refactor. New tests lock the delegation contract: budget shape, unique_id / timeout forwarding, ``None`` on timeout, transient HA errors swallowed, programming bugs propagate. - ``tests/src/unit/test_wait_helpers.py``: two new classes. - ``TestRestPathAutomationDiscovery`` — REST-fallback coverage (autouse ``force_rest_fallback`` fixture): resolves via REST sample, ignores ``script.*`` entities sharing the same id attribute, full miss returns None, transient ``HomeAssistantAPIError`` swallowed by sample callback. - ``TestWsPathAutomationDiscovery`` — WS coverage: post-subscribe sample resolves immediately, state_changed event arrival drives discovery, events for non-automation entities don't nudge, events for other automations (different unique_id) don't nudge. - ``FakeWebSocketClient.fire_state_changed`` grows an optional ``new_state=`` kwarg so discovery tests can include the ``data.new_state.attributes`` shape the filter inspects. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor: harden event_filter against malformed payloads and duplicate matches Addresses review-toolkit findings on PR #1406: - ``event_filter`` in ``wait_for_automation_entity_by_unique_id`` now guards every field access with ``isinstance`` checks before calling string / dict methods. The WS event dispatcher in ``websocket_client.py`` catches handler exceptions broadly (the pre-existing #1382 surface), so an ``AttributeError`` from a malformed payload reaching ``.startswith`` would be swallowed silently and the wait would time out reporting "not found" when the real cause was schema drift. The shape-hardening pattern is symmetric with the existing defense in ``sample()``. - The captured-cell now records only the first observed entity_id rather than last-writer-wins. HA's automation storage forbids duplicate unique_id by construction, but if a future race ever fires two matching events the helper now keeps the first and warns on the collision instead of silently coin-flipping. Two new tests in ``test_wait_helpers.py``: - ``test_event_capture_short_circuits_rest_scan`` — pins the closure-cell short-circuit with a discriminator: the REST scan would resolve ``automation.from_rest`` and the event carries ``automation.from_event``. Whichever path wins, the test proves the wait resolves (didn't silently time out). - ``test_connection_drop_during_discovery_falls_back_to_rest`` — mirrors ``TestWsPathConnectionDrop`` coverage for the discovery path. Pins that a WS drop mid-wait routes to the discovery-shaped ``get_states()`` sample rather than the entity-id-shaped ``get_entity_state()`` used by sibling waiters. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix: address sidelined silent-failure findings + fix connection-drop test Three findings I previously marked "out of scope" — wrongly, per AGENTS.md § Boy Scout Rule which explicitly forbids that escape hatch: 1. WS dispatcher swallowed handler exceptions without a traceback (``websocket_client.py:403``). The bare ``logger.error(f"... {e}")`` gave operators one line and no stack, so a handler bug (AttributeError on a malformed event, KeyError on schema drift) would silently stop nudging the waiter's ``asyncio.Event`` and the calling waiter would time out reporting "not found." Added ``exc_info=True`` so the traceback lands in logs. The dispatcher itself still swallows so one buggy handler can't kill the WS — but the bug is now visible. 2. ``wait_for_automation_entity_by_unique_id`` emitted a redundant "Automation with unique_id X was not found" warning at the same level as ``_ws_wait_for_condition``'s generic timeout warning. Replaced the redundant warning with a conditional one that fires only when REST sampling was wedged the entire budget, so operators can distinguish "automation truly not published" from "REST channel down." 3. Transient ``HomeAssistantAPIError`` from ``get_states()`` was debug-only with no signal at timeout time. Now tracked in the closure cell and surfaced in the new conditional warning above ("timed out with every REST sample failing; last error: ..."). Also fixes ``test_connection_drop_during_discovery_falls_back_to_rest`` which I wrote against the wrong nudge shape: the original noise event didn't match the discovery filter so the wait timed out at the backstop instead of dropping. Rewritten to mirror ``test_connection_drop_before_wait_loop_falls_back_to_rest`` — drop ``ws_client.is_connected`` inside the post-subscribe sample so the connection-drop branch routes us straight to ``_legacy_poll_until``. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * test: address Patch76 review findings on PR #1406 Three findings from Patch76's review of #1406: 1. **Discriminator test wasn't actually discriminating** — ``test_event_capture_short_circuits_rest_scan`` previously seeded ``get_states()`` to return ``automation.from_rest`` on every call and asserted ``result in {"automation.from_event", "automation.from_rest"}``. That accepts both outcomes, so a regression that broke the closure-cell short-circuit (forcing ``sample()`` to always fall through to ``get_states()``) would silently pass — REST would win every time. Now seeds ``get_states()`` with a side_effect that returns empty on the first call (post-subscribe sample) and the REST entity on subsequent calls, then asserts ``result == "automation.from_event"`` (deterministic discriminator: cell wins → event entity, regression → REST entity) and ``call_count == 1`` (the cell short-circuit means the post-event re-sample never touches REST). 2. **Duplicate-unique-id collision branch untested** — Patch76 noted the first-wins guard in ``event_filter`` (``util_helpers.py:1197``) had no test pinning the contract. Added ``test_duplicate_unique_id_collision_first_wins`` which fires two matching state_changed events back-to-back and asserts both "automation.first wins" and "warning logged naming both entity_ids." 3. **``last_api_error`` wedged-channel branch untested** — Patch76 noted the conditional warning at ``util_helpers.py:1222`` had no test pinning the "REST channel down" vs "automation never published" discrimination the code exists to make. Added ``test_wedged_rest_channel_surfaces_last_api_error`` which seeds ``get_states()`` to raise ``HomeAssistantAPIError`` on every call and asserts the timeout warning includes "every REST sample failing" and the last error message string. Rebased onto current upstream/master. Mechanical conflict resolution per Patch76: the ``_POLL_CADENCE`` deletion wins, taking #1389's measurement instrumentation with it. ``_poll_for_automation_entity`` no longer needs the cadence loop or the elapsed-time instrumentation because the WS event-driven path resolves sub-second on the happy path and the REST fallback uses uniform polling. The redundant local ``import time`` inside ``upsert_automation_config`` is also gone now that the top-level ``import time`` (added by #1389) remains for the unique_id-generation use at ``time.time() * 1000``. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * test(e2e): remove #1389 cadence-measurement infra retired by this refactor The #1389/#1398 work added an e2e test (``test_poll_cadence_measurement.py``) plus xdist plumbing in ``tests/src/e2e/conftest.py`` (``record_poll_cadence_measurement``, ``_POLL_CADENCE_MEASUREMENTS`` + xdist worker handoff, terminal-summary section) to empirically validate ``_POLL_CADENCE``'s p50/p99/worst percentiles. That test consumed the ``entity-registration-elapsed`` DEBUG log line emitted by ``_poll_for_automation_entity`` on each successful registration. This PR removes both ``_POLL_CADENCE`` and the elapsed-time instrumentation: the cadence loop is replaced by the WS event-driven discovery helper, which resolves sub-second on the happy path without any cadence tuning needed. The measurement test is therefore consuming a log signal that no longer exists — CI fail signature is "No 'entity-registration-elapsed' DEBUG records captured after 10 automation creations." Deletes: - ``tests/src/e2e/workflows/automation/test_poll_cadence_measurement.py`` (207 lines) — entire test file. The cadence tuple it validates is gone. - ``record_poll_cadence_measurement()`` + ``_POLL_CADENCE_MEASUREMENTS`` / ``_ALL_POLL_CADENCE_MEASUREMENTS`` + xdist worker handoff in ``pytest_sessionfinish`` / ``pytest_testnodedown`` + the ``#1389 _POLL_CADENCE measurement`` terminal section in ``pytest_terminal_summary``. Also updates the ``NOT_VERIFIED_WARNING_PREFIX`` comment in ``tools_config_automations.py`` from "exhausts ``_POLL_CADENCE``" to "exhausts its budget (``_POLL_BUDGET_S``)" and drops the test-file reference, since the test that consumed the export is gone. Per Patch76's #1406 review note: "the deletion wins" — extending that to the e2e measurement infra that consumed the deleted instrumentation. 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>
….0 ) (#141) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [ghcr.io/homeassistant-ai/ha-mcp](https://github.com/homeassistant-ai/ha-mcp) | minor | `7.5.0` → `7.6.0` | --- ### Release Notes <details> <summary>homeassistant-ai/ha-mcp (ghcr.io/homeassistant-ai/ha-mcp)</summary> ### [`v7.6.0`](https://github.com/homeassistant-ai/ha-mcp/blob/HEAD/CHANGELOG.md#v760-2026-05-27) [Compare Source](homeassistant-ai/ha-mcp@v7.5.0...v7.6.0) ##### Added - Make HTTP bind host configurable via MCP\_HOST (closes [#​1434](homeassistant-ai/ha-mcp#1434)) ([#​1436](homeassistant-ai/ha-mcp#1436)) - Tool Security Policies — per-tool approval gating ([#​966](homeassistant-ai/ha-mcp#966)) ([#​1421](homeassistant-ai/ha-mcp#1421)) - Rename ha\_delete\_helpers\_integrations → ha\_remove\_helpers\_integrations + raise on missing target ([#​1424](homeassistant-ai/ha-mcp#1424)) - Auto-backup edited entities before write/destructive tool calls (closes [#​1288](homeassistant-ai/ha-mcp#1288)) ([#​1403](homeassistant-ai/ha-mcp#1403)) - Persistent settings UI for stdio mode ([#​1381](homeassistant-ai/ha-mcp#1381)) - Add fields= projection to ha\_search\_entities, ha\_get\_overview, ha\_get\_state, ha\_get\_history, ha\_config\_list\_areas, ha\_list\_services ([#​1199](homeassistant-ai/ha-mcp#1199)) ([#​1225](homeassistant-ai/ha-mcp#1225)) - Route entity-registration wait through WS events (closes [#​1152](homeassistant-ai/ha-mcp#1152)) ([#​1382](homeassistant-ai/ha-mcp#1382)) - Add config subentry support ([#​1393](homeassistant-ai/ha-mcp#1393)) - Add Assist pipeline management tool ([#​1392](homeassistant-ai/ha-mcp#1392)) - Add knx to ha\_config\_set\_yaml allowlist ([#​1374](homeassistant-ai/ha-mcp#1374)) - Extend automation\_id parity to set/remove automation responses ([#​1343](homeassistant-ai/ha-mcp#1343)) - **haos-e2e**: Add parallel inaddon test tier (ha-mcp runs inside HAOS addon) ([#​1361](homeassistant-ai/ha-mcp#1361)) - Expose integration diagnostics via ha\_get\_integration and ha\_get\_system\_health (closes [#​1148](homeassistant-ai/ha-mcp#1148)) ([#​1328](homeassistant-ai/ha-mcp#1328)) - Return canonical script\_id from ha\_config\_get\_script ([#​1334](homeassistant-ai/ha-mcp#1334)) ([#​1352](homeassistant-ai/ha-mcp#1352)) - Add automation\_id parity key to ha\_config\_get\_automation ([#​1329](homeassistant-ai/ha-mcp#1329)) - Reject empty/whitespace identifiers on registry-metadata writes (closes [#​1294](homeassistant-ai/ha-mcp#1294)) ([#​1312](homeassistant-ai/ha-mcp#1312)) - Add HA brand assets for custom integration ([#​1317](homeassistant-ai/ha-mcp#1317)) - Unify ha\_config\_set\_helper response shape (closes [#​1293](homeassistant-ai/ha-mcp#1293)) ([#​1303](homeassistant-ai/ha-mcp#1303)) - Mirror create-side validation guards onto update path (closes [#​1292](homeassistant-ai/ha-mcp#1292)) ([#​1304](homeassistant-ai/ha-mcp#1304)) - Add array\_patch mode to ha\_manage\_addon for atomic GET-modify-POST ([#​1063](homeassistant-ai/ha-mcp#1063)) ##### Changed - **agents**: Drop ha\_backup\_create + ha\_backup\_restore from accepted exceptions ([#​1445](homeassistant-ai/ha-mcp#1445)) - Update contributors list \[contributors-updated] ([`c7665a6`](homeassistant-ai/ha-mcp@c7665a6)) - **overview**: Enumerate dismissed\_repair\_count in fields= description + static drift test ([#​1411](homeassistant-ai/ha-mcp#1411)) - Credit [@​tomwilkie](https://github.com/tomwilkie) and six other contributors in README ([#​1400](homeassistant-ai/ha-mcp#1400)) - **[#​1157](homeassistant-ai/ha-mcp#1157: Bump skills-vendor + auto-update via Renovate + native for: field + scrub eval\_template anti-patterns ([#​1383](homeassistant-ai/ha-mcp#1383)) - Extend Boy Scout weasel-phrase list with common variants; clarify semantic match ([#​1373](homeassistant-ai/ha-mcp#1373)) - Merge Boy Scout Rule + Handling Discovered Improvements; tighten deferral gate ([#​1359](homeassistant-ai/ha-mcp#1359)) - Categorize Issue Labels table and document 6 reverse-drift labels ([#​1335](homeassistant-ai/ha-mcp#1335)) - Strip stale L-refs from test\_identifier\_validation\_family docstrings ([#​1324](homeassistant-ai/ha-mcp#1324)) - Align label refs with live label set and fix triaged-removal trigger ([#​1316](homeassistant-ai/ha-mcp#1316)) - Surface tool-discovery / categorized search ([#​1123](homeassistant-ai/ha-mcp#1123)) - Fix two stale ha\_get\_skill\_guide references missed in [#​1289](homeassistant-ai/ha-mcp#1289) ([#​1305](homeassistant-ai/ha-mcp#1305)) - Clarify setup wizard placeholders need braces removed ([#​1284](homeassistant-ai/ha-mcp#1284)) ([#​1286](homeassistant-ai/ha-mcp#1286)) ##### Fixed - Remove counter from ha\_reload\_core targets ([#​1453](homeassistant-ai/ha-mcp#1453)) ([#​1456](homeassistant-ai/ha-mcp#1456)) - **backup**: Post-timeout match correctness + state-gate (closes [#​1433](homeassistant-ai/ha-mcp#1433)) ([#​1435](homeassistant-ai/ha-mcp#1435)) - Sync addon settings UI with Supervisor options end-to-end ([#​1420](homeassistant-ai/ha-mcp#1420)) - **calendar**: Switch ha\_config\_remove\_calendar\_event to WebSocket (closes [#​1413](homeassistant-ai/ha-mcp#1413), [#​1416](homeassistant-ai/ha-mcp#1416)) ([#​1418](homeassistant-ai/ha-mcp#1418)) - Error-shape consistency for non-entity not-found (closes [#​1297](homeassistant-ai/ha-mcp#1297)) ([#​1397](homeassistant-ai/ha-mcp#1397)) - Guard against silent automation overwrite on id mismatch ([#​1404](homeassistant-ai/ha-mcp#1404)) ([#​1405](homeassistant-ai/ha-mcp#1405)) - Cache YAML instance to prevent CPU spikes in bulk edits ([#​1370](homeassistant-ai/ha-mcp#1370)) ([#​1371](homeassistant-ai/ha-mcp#1371)) - **client**: Route get\_error\_log via hassio proxy on external-HAOS clients ([#​1360](homeassistant-ai/ha-mcp#1360)) - Classify dashboard 404s ("unknown config specified") as RESOURCE\_NOT\_FOUND ([#​1345](homeassistant-ai/ha-mcp#1345)) - Detect HA addon installs as http transport, not stdio ([#​1322](homeassistant-ai/ha-mcp#1322)) ([#​1327](homeassistant-ai/ha-mcp#1327)) - Actionable 403 suggestion when addon has unmapped container ports ([#​1319](homeassistant-ai/ha-mcp#1319)) ([#​1325](homeassistant-ai/ha-mcp#1325)) - Filter dismissed repairs in overview and system\_health ([#​1307](homeassistant-ai/ha-mcp#1307)) ([#​1309](homeassistant-ai/ha-mcp#1309)) - Exit on HA container death + daily reset before CI check ([#​1295](homeassistant-ai/ha-mcp#1295)) - Align ha\_config\_set\_dashboard with sibling re-fetch-after-save pattern ([#​1291](homeassistant-ai/ha-mcp#1291)) ([#​1301](homeassistant-ai/ha-mcp#1301)) - Allow str.replace in python\_transform; hint at search mode on IndexError ([#​1287](homeassistant-ai/ha-mcp#1287)) - **array\_patch**: Tighten validation and surface silent failures ([#​1285](homeassistant-ai/ha-mcp#1285)) - HA Core proxy fallback for ha\_get\_logs(source=system\_service) on non-addon installs ([#​1283](homeassistant-ai/ha-mcp#1283)) ##### Performance Improvements - Tighten \_poll\_for\_automation\_entity first-poll cadence ([#​1384](homeassistant-ai/ha-mcp#1384)) - Parallelize ha\_get\_system\_health optional sections via asyncio.gather ([#​1336](homeassistant-ai/ha-mcp#1336)) ##### Refactoring - **service**: Compact ha\_call\_service result default ([#​1446](homeassistant-ai/ha-mcp#1446)) ([#​1447](homeassistant-ai/ha-mcp#1447)) - Rename ha\_update\_device → ha\_set\_device ([#​1444](homeassistant-ai/ha-mcp#1444)) - Remove duplicate flat area/floor list tools (consolidation followup to [#​1016](homeassistant-ai/ha-mcp#1016)) ([#​1429](homeassistant-ai/ha-mcp#1429)) - **complexity**: Migrate tools\_utility.py to class-based pattern ([#​1423](homeassistant-ai/ha-mcp#1423)) - **complexity**: Reduce C901 violations in tools/ — batch 4 ([#​1408](homeassistant-ai/ha-mcp#1408)) - Route \_poll\_for\_automation\_entity through WS event waiter (closes [#​1395](homeassistant-ai/ha-mcp#1395)) ([#​1406](homeassistant-ai/ha-mcp#1406)) - **yaml**: Use threading.local subclass for cached instance ([#​1396](homeassistant-ai/ha-mcp#1396)) - Align dashboards 404 shape with sibling config tools ([#​1386](homeassistant-ai/ha-mcp#1386)) - Complete singular warning → warnings list migration repo-wide (closes [#​1332](homeassistant-ai/ha-mcp#1332)) ([#​1341](homeassistant-ai/ha-mcp#1341)) - Complete warnings-list migration for lifecycle-write tools ([#​1340](homeassistant-ai/ha-mcp#1340)) - Drop redundant identifier echo key from ha\_config\_get\_automation ([#​1354](homeassistant-ai/ha-mcp#1354)) - Drop logger.error in config-tool except blocks ([#​1302](homeassistant-ai/ha-mcp#1302)) ([#​1353](homeassistant-ai/ha-mcp#1353)) - Extend validate\_identifier\_not\_empty to automations/scripts/dashboards CRUD (closes [#​1313](homeassistant-ai/ha-mcp#1313)) ([#​1321](homeassistant-ai/ha-mcp#1321)) - Migrate tools\_config\_scenes inline empty-id guards to shared helper ([#​1320](homeassistant-ai/ha-mcp#1320)) - Remove ha\_get\_helper\_schema (closes [#​1186](homeassistant-ai/ha-mcp#1186)) ([#​1315](homeassistant-ai/ha-mcp#1315)) - Consolidate skill tools; fix stable submodule packaging ([#​1289](homeassistant-ai/ha-mcp#1289)) - Align tools\_config\_automations.py error-handling with sibling pattern ([#​1290](homeassistant-ai/ha-mcp#1290)) ([#​1298](homeassistant-ai/ha-mcp#1298)) *** <details> <summary>Internal Changes</summary> ##### Fixed - **ci**: Install libguestfs in HAOS publish workflow ([#​1358](homeassistant-ai/ha-mcp#1358)) ##### Build System - **deps**: Bump esbuild from 0.24.2 to 0.25.0 in /tests/js ([#​1427](homeassistant-ai/ha-mcp#1427)) - **deps**: Bump devalue from 5.6.4 to 5.8.1 in /site ([#​1282](homeassistant-ai/ha-mcp#1282)) - **deps**: Bump astro from 6.1.6 to 6.1.10 in /site ([#​1274](homeassistant-ai/ha-mcp#1274)) ##### Chores - **addon**: Publish dev addon version 7.5.0.dev360 \[skip ci] ([`ad7aed1`](homeassistant-ai/ha-mcp@ad7aed1)) - Sync tool docs after merge \[skip ci] ([`9c4984f`](homeassistant-ai/ha-mcp@9c4984f)) - **deps**: Update ghcr.io/home-assistant/home-assistant docker tag to v2026.5.4 ([#​1450](homeassistant-ai/ha-mcp#1450)) - **addon**: Publish dev addon version 7.5.0.dev359 \[skip ci] ([`b82d4ee`](homeassistant-ai/ha-mcp@b82d4ee)) - **deps**: Update ghcr.io/astral-sh/uv docker tag to v0.11.16 ([#​1449](homeassistant-ai/ha-mcp#1449)) - **addon**: Publish dev addon version 7.5.0.dev358 \[skip ci] ([`53fba6d`](homeassistant-ai/ha-mcp@53fba6d)) - Sync tool docs after merge \[skip ci] ([`dc7750d`](homeassistant-ai/ha-mcp@dc7750d)) - **addon**: Publish dev addon version 7.5.0.dev357 \[skip ci] ([`fd150c9`](homeassistant-ai/ha-mcp@fd150c9)) - **addon**: Publish dev addon version 7.5.0.dev356 \[skip ci] ([`5fa1463`](homeassistant-ai/ha-mcp@5fa1463)) - **addon**: Publish dev addon version 7.5.0.dev355 \[skip ci] ([`174ac5d`](homeassistant-ai/ha-mcp@174ac5d)) - **addon**: Publish dev addon version 7.5.0.dev354 \[skip ci] ([`4f93989`](homeassistant-ai/ha-mcp@4f93989)) - **addon**: Publish dev addon version 7.5.0.dev353 \[skip ci] ([`53f282f`](homeassistant-ai/ha-mcp@53f282f)) - **addon**: Publish dev addon version 7.5.0.dev352 \[skip ci] ([`4911d46`](homeassistant-ai/ha-mcp@4911d46)) - Sync tool docs after merge \[skip ci] ([`8a79837`](homeassistant-ai/ha-mcp@8a79837)) - **addon**: Publish dev addon version 7.5.0.dev351 \[skip ci] ([`13afa9d`](homeassistant-ai/ha-mcp@13afa9d)) - **addon**: Publish dev addon version 7.5.0.dev350 \[skip ci] ([`e93d680`](homeassistant-ai/ha-mcp@e93d680)) - **addon**: Publish dev addon version 7.5.0.dev349 \[skip ci] ([`1631ad1`](homeassistant-ai/ha-mcp@1631ad1)) - **addon**: Publish dev addon version 7.5.0.dev348 \[skip ci] ([`18a8aef`](homeassistant-ai/ha-mcp@18a8aef)) - Sync tool docs after merge \[skip ci] ([`9e0493d`](homeassistant-ai/ha-mcp@9e0493d)) - **addon**: Publish dev addon version 7.5.0.dev347 \[skip ci] ([`e2067e4`](homeassistant-ai/ha-mcp@e2067e4)) - Sync tool docs after merge \[skip ci] ([`7bdb3d4`](homeassistant-ai/ha-mcp@7bdb3d4)) - **addon**: Publish dev addon version 7.5.0.dev346 \[skip ci] ([`c2d4dd7`](homeassistant-ai/ha-mcp@c2d4dd7)) - Sync tool docs after merge \[skip ci] ([`393b354`](homeassistant-ai/ha-mcp@393b354)) - **addon**: Publish dev addon version 7.5.0.dev345 \[skip ci] ([`42ede8b`](homeassistant-ai/ha-mcp@42ede8b)) - **addon**: Publish dev addon version 7.5.0.dev344 \[skip ci] ([`e6cc7a1`](homeassistant-ai/ha-mcp@e6cc7a1)) - Sync tool docs after merge \[skip ci] ([`fb35f30`](homeassistant-ai/ha-mcp@fb35f30)) - **addon**: Publish dev addon version 7.5.0.dev343 \[skip ci] ([`401b7b4`](homeassistant-ai/ha-mcp@401b7b4)) - **addon**: Publish dev addon version 7.5.0.dev342 \[skip ci] ([`0679371`](homeassistant-ai/ha-mcp@0679371)) - Sync tool docs after merge \[skip ci] ([`f6796ec`](homeassistant-ai/ha-mcp@f6796ec)) - **addon**: Publish dev addon version 7.5.0.dev341 \[skip ci] ([`3654478`](homeassistant-ai/ha-mcp@3654478)) - **addon**: Publish dev addon version 7.5.0.dev340 \[skip ci] ([`64f00b6`](homeassistant-ai/ha-mcp@64f00b6)) - **addon**: Publish dev addon version 7.5.0.dev339 \[skip ci] ([`d6e8873`](homeassistant-ai/ha-mcp@d6e8873)) - Sync tool docs after merge \[skip ci] ([`7525e93`](homeassistant-ai/ha-mcp@7525e93)) - **addon**: Publish dev addon version 7.5.0.dev338 \[skip ci] ([`288ca4a`](homeassistant-ai/ha-mcp@288ca4a)) - **addon**: Publish dev addon version 7.5.0.dev337 \[skip ci] ([`f539ae5`](homeassistant-ai/ha-mcp@f539ae5)) - **addon**: Publish dev addon version 7.5.0.dev336 \[skip ci] ([`5568a86`](homeassistant-ai/ha-mcp@5568a86)) - **addon**: Publish dev addon version 7.5.0.dev335 \[skip ci] ([`e069405`](homeassistant-ai/ha-mcp@e069405)) - **addon**: Publish dev addon version 7.5.0.dev334 \[skip ci] ([`f7be6ea`](homeassistant-ai/ha-mcp@f7be6ea)) - **addon**: Publish dev addon version 7.5.0.dev333 \[skip ci] ([`cb480ea`](homeassistant-ai/ha-mcp@cb480ea)) - Sync tool docs after merge \[skip ci] ([`9a5bc3c`](homeassistant-ai/ha-mcp@9a5bc3c)) - **addon**: Publish dev addon version 7.5.0.dev332 \[skip ci] ([`e0e59ee`](homeassistant-ai/ha-mcp@e0e59ee)) - Sync tool docs after merge \[skip ci] ([`499ebf0`](homeassistant-ai/ha-mcp@499ebf0)) - **addon**: Publish dev addon version 7.5.0.dev331 \[skip ci] ([`3e0ce92`](homeassistant-ai/ha-mcp@3e0ce92)) - **addon**: Publish dev addon version 7.5.0.dev330 \[skip ci] ([`e48d056`](homeassistant-ai/ha-mcp@e48d056)) - **deps**: Update ghcr.io/astral-sh/uv docker tag to v0.11.15 ([#​1376](homeassistant-ai/ha-mcp#1376)) - **deps**: Update ghcr.io/home-assistant/home-assistant docker tag to v2026.5.3 ([#​1377](homeassistant-ai/ha-mcp#1377)) - **addon**: Publish dev addon version 7.5.0.dev329 \[skip ci] ([`c523c50`](homeassistant-ai/ha-mcp@c523c50)) - Sync tool docs after merge \[skip ci] ([`5b7a8aa`](homeassistant-ai/ha-mcp@5b7a8aa)) - **addon**: Publish dev addon version 7.5.0.dev328 \[skip ci] ([`6c42fba`](homeassistant-ai/ha-mcp@6c42fba)) - **addon**: Publish dev addon version 7.5.0.dev327 \[skip ci] ([`aecd025`](homeassistant-ai/ha-mcp@aecd025)) - **addon**: Publish dev addon version 7.5.0.dev326 \[skip ci] ([`399c17c`](homeassistant-ai/ha-mcp@399c17c)) - **addon**: Publish dev addon version 7.5.0.dev325 \[skip ci] ([`b580b45`](homeassistant-ai/ha-mcp@b580b45)) - Sync tool docs after merge \[skip ci] ([`8567c3a`](homeassistant-ai/ha-mcp@8567c3a)) - **addon**: Publish dev addon version 7.5.0.dev324 \[skip ci] ([`a65579d`](homeassistant-ai/ha-mcp@a65579d)) - **addon**: Publish dev addon version 7.5.0.dev323 \[skip ci] ([`c7667ba`](homeassistant-ai/ha-mcp@c7667ba)) - **addon**: Publish dev addon version 7.5.0.dev322 \[skip ci] ([`44d15a8`](homeassistant-ai/ha-mcp@44d15a8)) - **addon**: Publish dev addon version 7.5.0.dev321 \[skip ci] ([`8739f6c`](homeassistant-ai/ha-mcp@8739f6c)) - **addon**: Publish dev addon version 7.5.0.dev320 \[skip ci] ([`02b6e47`](homeassistant-ai/ha-mcp@02b6e47)) - Sync tool docs after merge \[skip ci] ([`ab68c9a`](homeassistant-ai/ha-mcp@ab68c9a)) - **addon**: Publish dev addon version 7.5.0.dev319 \[skip ci] ([`4472904`](homeassistant-ai/ha-mcp@4472904)) - **addon**: Publish dev addon version 7.5.0.dev318 \[skip ci] ([`e030dbc`](homeassistant-ai/ha-mcp@e030dbc)) - **addon**: Publish dev addon version 7.5.0.dev317 \[skip ci] ([`d87855c`](homeassistant-ai/ha-mcp@d87855c)) - Sync tool docs after merge \[skip ci] ([`a72a4e8`](homeassistant-ai/ha-mcp@a72a4e8)) - **addon**: Publish dev addon version 7.5.0.dev316 \[skip ci] ([`bd9397f`](homeassistant-ai/ha-mcp@bd9397f)) - **addon**: Publish dev addon version 7.5.0.dev315 \[skip ci] ([`264bfc2`](homeassistant-ai/ha-mcp@264bfc2)) - **addon**: Publish dev addon version 7.5.0.dev314 \[skip ci] ([`df62881`](homeassistant-ai/ha-mcp@df62881)) - **addon**: Publish dev addon version 7.5.0.dev313 \[skip ci] ([`f6c47ca`](homeassistant-ai/ha-mcp@f6c47ca)) - **addon**: Publish dev addon version 7.5.0.dev312 \[skip ci] ([`2bb7a74`](homeassistant-ai/ha-mcp@2bb7a74)) - Sync tool docs after merge \[skip ci] ([`137e279`](homeassistant-ai/ha-mcp@137e279)) - **addon**: Publish dev addon version 7.5.0.dev311 \[skip ci] ([`28324ea`](homeassistant-ai/ha-mcp@28324ea)) - Sync tool docs after merge \[skip ci] ([`9a753d4`](homeassistant-ai/ha-mcp@9a753d4)) - **addon**: Publish dev addon version 7.5.0.dev310 \[skip ci] ([`f893b2e`](homeassistant-ai/ha-mcp@f893b2e)) - **addon**: Publish dev addon version 7.5.0.dev309 \[skip ci] ([`8cbdb7b`](homeassistant-ai/ha-mcp@8cbdb7b)) - **addon**: Publish dev addon version 7.5.0.dev308 \[skip ci] ([`2d18016`](homeassistant-ai/ha-mcp@2d18016)) - **addon**: Publish dev addon version 7.5.0.dev307 \[skip ci] ([`3fc3b28`](homeassistant-ai/ha-mcp@3fc3b28)) - Sync tool docs after merge \[skip ci] ([`9e6cff8`](homeassistant-ai/ha-mcp@9e6cff8)) - **addon**: Publish dev addon version 7.5.0.dev306 \[skip ci] ([`8bdd0fc`](homeassistant-ai/ha-mcp@8bdd0fc)) - **addon**: Publish dev addon version 7.5.0.dev305 \[skip ci] ([`83535b9`](homeassistant-ai/ha-mcp@83535b9)) - **addon**: Publish dev addon version 7.5.0.dev304 \[skip ci] ([`1435b3a`](homeassistant-ai/ha-mcp@1435b3a)) - **addon**: Publish dev addon version 7.5.0.dev303 \[skip ci] ([`e2da659`](homeassistant-ai/ha-mcp@e2da659)) - Sync tool docs after merge \[skip ci] ([`23789fa`](homeassistant-ai/ha-mcp@23789fa)) - **addon**: Publish dev addon version 7.5.0.dev302 \[skip ci] ([`6c8e574`](homeassistant-ai/ha-mcp@6c8e574)) - Sync tool docs after merge \[skip ci] ([`d2329cb`](homeassistant-ai/ha-mcp@d2329cb)) - **addon**: Publish dev addon version 7.5.0.dev301 \[skip ci] ([`bb538f7`](homeassistant-ai/ha-mcp@bb538f7)) - Sync tool docs after merge \[skip ci] ([`f70f0e1`](homeassistant-ai/ha-mcp@f70f0e1)) - **addon**: Publish version 7.5.0 \[skip ci] ([`9c5eb37`](homeassistant-ai/ha-mcp@9c5eb37)) ##### Continuous Integration - **deps**: Bump actions/upload-artifact in the github-actions group ([#​1437](homeassistant-ai/ha-mcp#1437)) - Share qcow2 cache + GHCR fallback between HAOS lanes ([#​1407](homeassistant-ai/ha-mcp#1407)) - Add ruff format --check on changed Python files ([#​1387](homeassistant-ai/ha-mcp#1387)) - Exempt assigned issues from stale bot ([#​1368](homeassistant-ai/ha-mcp#1368)) - **deps**: Bump the github-actions group with 3 updates ([#​1362](homeassistant-ai/ha-mcp#1362)) ##### Refactoring - Consolidate lovelace/dashboards/list through shared helper ([#​1344](homeassistant-ai/ha-mcp#1344)) ##### Testing - **haos-e2e**: Bake + install webhook-proxy addon and exercise its runtime ([#​1443](homeassistant-ai/ha-mcp#1443)) - **config-subentry**: Mark forecast\_solar e2e as known flaky + relative-import sweep ([#​1430](homeassistant-ai/ha-mcp#1430)) - **haos-e2e**: Trim cache-save race, compress GHCR qcow2, eval boot snapshot ([#​1428](homeassistant-ai/ha-mcp#1428)) - JSDOM behaviour harness + auto-discovery parse coverage for every rendered <script> ([#​1425](homeassistant-ai/ha-mcp#1425)) - **hacs**: Retry TestMcpToolsInstallation on flake ([#​1426](homeassistant-ai/ha-mcp#1426)) - **e2e**: Drop redundant lifecycle roundtrips, keep only Matter Server ([#​1414](homeassistant-ai/ha-mcp#1414)) ([#​1419](homeassistant-ai/ha-mcp#1419)) - **e2e**: Assert backend dispatch matches workflow env on every lane ([#​1409](homeassistant-ai/ha-mcp#1409)) - Escape ideographic space and format file ([#​1237](homeassistant-ai/ha-mcp#1237)) ([#​1410](homeassistant-ai/ha-mcp#1410)) - **e2e**: Measure \_POLL\_CADENCE p50/p99 to validate or retune (closes [#​1389](homeassistant-ai/ha-mcp#1389)) ([#​1398](homeassistant-ai/ha-mcp#1398)) - **e2e**: Wait for addon state=started in haos proxy header test ([#​1402](homeassistant-ai/ha-mcp#1402)) - Pin remaining \_classify\_by\_message branches ([#​1385](homeassistant-ai/ha-mcp#1385)) - **haos-e2e**: Slim addon set + real-addon ha\_manage\_addon coverage (closes [#​1350](homeassistant-ai/ha-mcp#1350)) ([#​1379](homeassistant-ai/ha-mcp#1379)) - **haos-e2e**: Close out [#​1349](homeassistant-ai/ha-mcp#1349) — lifecycle, integrations, supervisor\_mock migration, no more skips ([#​1375](homeassistant-ai/ha-mcp#1375)) - **e2e**: Consolidate readiness gates onto /api/core/state (refs [#​366](homeassistant-ai/ha-mcp#366)) ([#​1372](homeassistant-ai/ha-mcp#1372)) - **e2e**: Tighten 5 readiness-gate budgets with 2-63x headroom (refs [#​366](homeassistant-ai/ha-mcp#366)) ([#​1369](homeassistant-ai/ha-mcp#1369)) - Scaffold HAOS E2E tier image-build pipeline (refs [#​1281](homeassistant-ai/ha-mcp#1281)) ([#​1326](homeassistant-ai/ha-mcp#1326)) - **e2e**: Instrument HA\_MCP\_TOOLS\_WAIT readiness gate (refs [#​366](homeassistant-ai/ha-mcp#366)) ([#​1346](homeassistant-ai/ha-mcp#1346)) - **e2e**: Centralize wait\_for\_entity\_registration helper (refs [#​366](homeassistant-ai/ha-mcp#366)) ([#​1308](homeassistant-ai/ha-mcp#1308)) - **e2e**: Unify dict-error message extraction across e2e tests (refs [#​366](homeassistant-ai/ha-mcp#366)) ([#​1311](homeassistant-ai/ha-mcp#1311)) - **e2e**: Surface readiness-gate elapsed times in CI logs (refs [#​366](homeassistant-ai/ha-mcp#366)) ([#​1310](homeassistant-ai/ha-mcp#1310)) </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:eyJjcmVhdGVkSW5WZXIiOiI0My4xOTUuNCIsInVwZGF0ZWRJblZlciI6IjQzLjE5NS40IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJyZW5vdmF0ZS9jb250YWluZXIiLCJ0eXBlL21pbm9yIl19--> Reviewed-on: https://git.greyrock.io/greyrock-labs/home-ops/pulls/141
…➔ 7.6.0) (#904) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [ghcr.io/homeassistant-ai/ha-mcp](https://github.com/homeassistant-ai/ha-mcp) | minor | `7.5.0` → `7.6.0` | --- ### Release Notes <details> <summary>homeassistant-ai/ha-mcp (ghcr.io/homeassistant-ai/ha-mcp)</summary> ### [`v7.6.0`](https://github.com/homeassistant-ai/ha-mcp/blob/HEAD/CHANGELOG.md#v760-2026-05-27) [Compare Source](homeassistant-ai/ha-mcp@v7.5.0...v7.6.0) ##### Added - Make HTTP bind host configurable via MCP\_HOST (closes [#​1434](homeassistant-ai/ha-mcp#1434)) ([#​1436](homeassistant-ai/ha-mcp#1436)) - Tool Security Policies — per-tool approval gating ([#​966](homeassistant-ai/ha-mcp#966)) ([#​1421](homeassistant-ai/ha-mcp#1421)) - Rename ha\_delete\_helpers\_integrations → ha\_remove\_helpers\_integrations + raise on missing target ([#​1424](homeassistant-ai/ha-mcp#1424)) - Auto-backup edited entities before write/destructive tool calls (closes [#​1288](homeassistant-ai/ha-mcp#1288)) ([#​1403](homeassistant-ai/ha-mcp#1403)) - Persistent settings UI for stdio mode ([#​1381](homeassistant-ai/ha-mcp#1381)) - Add fields= projection to ha\_search\_entities, ha\_get\_overview, ha\_get\_state, ha\_get\_history, ha\_config\_list\_areas, ha\_list\_services ([#​1199](homeassistant-ai/ha-mcp#1199)) ([#​1225](homeassistant-ai/ha-mcp#1225)) - Route entity-registration wait through WS events (closes [#​1152](homeassistant-ai/ha-mcp#1152)) ([#​1382](homeassistant-ai/ha-mcp#1382)) - Add config subentry support ([#​1393](homeassistant-ai/ha-mcp#1393)) - Add Assist pipeline management tool ([#​1392](homeassistant-ai/ha-mcp#1392)) - Add knx to ha\_config\_set\_yaml allowlist ([#​1374](homeassistant-ai/ha-mcp#1374)) - Extend automation\_id parity to set/remove automation responses ([#​1343](homeassistant-ai/ha-mcp#1343)) - **haos-e2e**: Add parallel inaddon test tier (ha-mcp runs inside HAOS addon) ([#​1361](homeassistant-ai/ha-mcp#1361)) - Expose integration diagnostics via ha\_get\_integration and ha\_get\_system\_health (closes [#​1148](homeassistant-ai/ha-mcp#1148)) ([#​1328](homeassistant-ai/ha-mcp#1328)) - Return canonical script\_id from ha\_config\_get\_script ([#​1334](homeassistant-ai/ha-mcp#1334)) ([#​1352](homeassistant-ai/ha-mcp#1352)) - Add automation\_id parity key to ha\_config\_get\_automation ([#​1329](homeassistant-ai/ha-mcp#1329)) - Reject empty/whitespace identifiers on registry-metadata writes (closes [#​1294](homeassistant-ai/ha-mcp#1294)) ([#​1312](homeassistant-ai/ha-mcp#1312)) - Add HA brand assets for custom integration ([#​1317](homeassistant-ai/ha-mcp#1317)) - Unify ha\_config\_set\_helper response shape (closes [#​1293](homeassistant-ai/ha-mcp#1293)) ([#​1303](homeassistant-ai/ha-mcp#1303)) - Mirror create-side validation guards onto update path (closes [#​1292](homeassistant-ai/ha-mcp#1292)) ([#​1304](homeassistant-ai/ha-mcp#1304)) - Add array\_patch mode to ha\_manage\_addon for atomic GET-modify-POST ([#​1063](homeassistant-ai/ha-mcp#1063)) ##### Changed - **agents**: Drop ha\_backup\_create + ha\_backup\_restore from accepted exceptions ([#​1445](homeassistant-ai/ha-mcp#1445)) - Update contributors list \[contributors-updated] ([`c7665a6`](homeassistant-ai/ha-mcp@c7665a6)) - **overview**: Enumerate dismissed\_repair\_count in fields= description + static drift test ([#​1411](homeassistant-ai/ha-mcp#1411)) - Credit [@​tomwilkie](https://github.com/tomwilkie) and six other contributors in README ([#​1400](homeassistant-ai/ha-mcp#1400)) - **[#​1157](homeassistant-ai/ha-mcp#1157: Bump skills-vendor + auto-update via Renovate + native for: field + scrub eval\_template anti-patterns ([#​1383](homeassistant-ai/ha-mcp#1383)) - Extend Boy Scout weasel-phrase list with common variants; clarify semantic match ([#​1373](homeassistant-ai/ha-mcp#1373)) - Merge Boy Scout Rule + Handling Discovered Improvements; tighten deferral gate ([#​1359](homeassistant-ai/ha-mcp#1359)) - Categorize Issue Labels table and document 6 reverse-drift labels ([#​1335](homeassistant-ai/ha-mcp#1335)) - Strip stale L-refs from test\_identifier\_validation\_family docstrings ([#​1324](homeassistant-ai/ha-mcp#1324)) - Align label refs with live label set and fix triaged-removal trigger ([#​1316](homeassistant-ai/ha-mcp#1316)) - Surface tool-discovery / categorized search ([#​1123](homeassistant-ai/ha-mcp#1123)) - Fix two stale ha\_get\_skill\_guide references missed in [#​1289](homeassistant-ai/ha-mcp#1289) ([#​1305](homeassistant-ai/ha-mcp#1305)) - Clarify setup wizard placeholders need braces removed ([#​1284](homeassistant-ai/ha-mcp#1284)) ([#​1286](homeassistant-ai/ha-mcp#1286)) ##### Fixed - Remove counter from ha\_reload\_core targets ([#​1453](homeassistant-ai/ha-mcp#1453)) ([#​1456](homeassistant-ai/ha-mcp#1456)) - **backup**: Post-timeout match correctness + state-gate (closes [#​1433](homeassistant-ai/ha-mcp#1433)) ([#​1435](homeassistant-ai/ha-mcp#1435)) - Sync addon settings UI with Supervisor options end-to-end ([#​1420](homeassistant-ai/ha-mcp#1420)) - **calendar**: Switch ha\_config\_remove\_calendar\_event to WebSocket (closes [#​1413](homeassistant-ai/ha-mcp#1413), [#​1416](homeassistant-ai/ha-mcp#1416)) ([#​1418](homeassistant-ai/ha-mcp#1418)) - Error-shape consistency for non-entity not-found (closes [#​1297](homeassistant-ai/ha-mcp#1297)) ([#​1397](homeassistant-ai/ha-mcp#1397)) - Guard against silent automation overwrite on id mismatch ([#​1404](homeassistant-ai/ha-mcp#1404)) ([#​1405](homeassistant-ai/ha-mcp#1405)) - Cache YAML instance to prevent CPU spikes in bulk edits ([#​1370](homeassistant-ai/ha-mcp#1370)) ([#​1371](homeassistant-ai/ha-mcp#1371)) - **client**: Route get\_error\_log via hassio proxy on external-HAOS clients ([#​1360](homeassistant-ai/ha-mcp#1360)) - Classify dashboard 404s ("unknown config specified") as RESOURCE\_NOT\_FOUND ([#​1345](homeassistant-ai/ha-mcp#1345)) - Detect HA addon installs as http transport, not stdio ([#​1322](homeassistant-ai/ha-mcp#1322)) ([#​1327](homeassistant-ai/ha-mcp#1327)) - Actionable 403 suggestion when addon has unmapped container ports ([#​1319](homeassistant-ai/ha-mcp#1319)) ([#​1325](homeassistant-ai/ha-mcp#1325)) - Filter dismissed repairs in overview and system\_health ([#​1307](homeassistant-ai/ha-mcp#1307)) ([#​1309](homeassistant-ai/ha-mcp#1309)) - Exit on HA container death + daily reset before CI check ([#​1295](homeassistant-ai/ha-mcp#1295)) - Align ha\_config\_set\_dashboard with sibling re-fetch-after-save pattern ([#​1291](homeassistant-ai/ha-mcp#1291)) ([#​1301](homeassistant-ai/ha-mcp#1301)) - Allow str.replace in python\_transform; hint at search mode on IndexError ([#​1287](homeassistant-ai/ha-mcp#1287)) - **array\_patch**: Tighten validation and surface silent failures ([#​1285](homeassistant-ai/ha-mcp#1285)) - HA Core proxy fallback for ha\_get\_logs(source=system\_service) on non-addon installs ([#​1283](homeassistant-ai/ha-mcp#1283)) ##### Performance Improvements - Tighten \_poll\_for\_automation\_entity first-poll cadence ([#​1384](homeassistant-ai/ha-mcp#1384)) - Parallelize ha\_get\_system\_health optional sections via asyncio.gather ([#​1336](homeassistant-ai/ha-mcp#1336)) ##### Refactoring - **service**: Compact ha\_call\_service result default ([#​1446](homeassistant-ai/ha-mcp#1446)) ([#​1447](homeassistant-ai/ha-mcp#1447)) - Rename ha\_update\_device → ha\_set\_device ([#​1444](homeassistant-ai/ha-mcp#1444)) - Remove duplicate flat area/floor list tools (consolidation followup to [#​1016](homeassistant-ai/ha-mcp#1016)) ([#​1429](homeassistant-ai/ha-mcp#1429)) - **complexity**: Migrate tools\_utility.py to class-based pattern ([#​1423](homeassistant-ai/ha-mcp#1423)) - **complexity**: Reduce C901 violations in tools/ — batch 4 ([#​1408](homeassistant-ai/ha-mcp#1408)) - Route \_poll\_for\_automation\_entity through WS event waiter (closes [#​1395](homeassistant-ai/ha-mcp#1395)) ([#​1406](homeassistant-ai/ha-mcp#1406)) - **yaml**: Use threading.local subclass for cached instance ([#​1396](homeassistant-ai/ha-mcp#1396)) - Align dashboards 404 shape with sibling config tools ([#​1386](homeassistant-ai/ha-mcp#1386)) - Complete singular warning → warnings list migration repo-wide (closes [#​1332](homeassistant-ai/ha-mcp#1332)) ([#​1341](homeassistant-ai/ha-mcp#1341)) - Complete warnings-list migration for lifecycle-write tools ([#​1340](homeassistant-ai/ha-mcp#1340)) - Drop redundant identifier echo key from ha\_config\_get\_automation ([#​1354](homeassistant-ai/ha-mcp#1354)) - Drop logger.error in config-tool except blocks ([#​1302](homeassistant-ai/ha-mcp#1302)) ([#​1353](homeassistant-ai/ha-mcp#1353)) - Extend validate\_identifier\_not\_empty to automations/scripts/dashboards CRUD (closes [#​1313](homeassistant-ai/ha-mcp#1313)) ([#​1321](homeassistant-ai/ha-mcp#1321)) - Migrate tools\_config\_scenes inline empty-id guards to shared helper ([#​1320](homeassistant-ai/ha-mcp#1320)) - Remove ha\_get\_helper\_schema (closes [#​1186](homeassistant-ai/ha-mcp#1186)) ([#​1315](homeassistant-ai/ha-mcp#1315)) - Consolidate skill tools; fix stable submodule packaging ([#​1289](homeassistant-ai/ha-mcp#1289)) - Align tools\_config\_automations.py error-handling with sibling pattern ([#​1290](homeassistant-ai/ha-mcp#1290)) ([#​1298](homeassistant-ai/ha-mcp#1298)) *** <details> <summary>Internal Changes</summary> ##### Fixed - **ci**: Install libguestfs in HAOS publish workflow ([#​1358](homeassistant-ai/ha-mcp#1358)) ##### Build System - **deps**: Bump esbuild from 0.24.2 to 0.25.0 in /tests/js ([#​1427](homeassistant-ai/ha-mcp#1427)) - **deps**: Bump devalue from 5.6.4 to 5.8.1 in /site ([#​1282](homeassistant-ai/ha-mcp#1282)) - **deps**: Bump astro from 6.1.6 to 6.1.10 in /site ([#​1274](homeassistant-ai/ha-mcp#1274)) ##### Chores - **addon**: Publish dev addon version 7.5.0.dev360 \[skip ci] ([`ad7aed1`](homeassistant-ai/ha-mcp@ad7aed1)) - Sync tool docs after merge \[skip ci] ([`9c4984f`](homeassistant-ai/ha-mcp@9c4984f)) - **deps**: Update ghcr.io/home-assistant/home-assistant docker tag to v2026.5.4 ([#​1450](homeassistant-ai/ha-mcp#1450)) - **addon**: Publish dev addon version 7.5.0.dev359 \[skip ci] ([`b82d4ee`](homeassistant-ai/ha-mcp@b82d4ee)) - **deps**: Update ghcr.io/astral-sh/uv docker tag to v0.11.16 ([#​1449](homeassistant-ai/ha-mcp#1449)) - **addon**: Publish dev addon version 7.5.0.dev358 \[skip ci] ([`53fba6d`](homeassistant-ai/ha-mcp@53fba6d)) - Sync tool docs after merge \[skip ci] ([`dc7750d`](homeassistant-ai/ha-mcp@dc7750d)) - **addon**: Publish dev addon version 7.5.0.dev357 \[skip ci] ([`fd150c9`](homeassistant-ai/ha-mcp@fd150c9)) - **addon**: Publish dev addon version 7.5.0.dev356 \[skip ci] ([`5fa1463`](homeassistant-ai/ha-mcp@5fa1463)) - **addon**: Publish dev addon version 7.5.0.dev355 \[skip ci] ([`174ac5d`](homeassistant-ai/ha-mcp@174ac5d)) - **addon**: Publish dev addon version 7.5.0.dev354 \[skip ci] ([`4f93989`](homeassistant-ai/ha-mcp@4f93989)) - **addon**: Publish dev addon version 7.5.0.dev353 \[skip ci] ([`53f282f`](homeassistant-ai/ha-mcp@53f282f)) - **addon**: Publish dev addon version 7.5.0.dev352 \[skip ci] ([`4911d46`](homeassistant-ai/ha-mcp@4911d46)) - Sync tool docs after merge \[skip ci] ([`8a79837`](homeassistant-ai/ha-mcp@8a79837)) - **addon**: Publish dev addon version 7.5.0.dev351 \[skip ci] ([`13afa9d`](homeassistant-ai/ha-mcp@13afa9d)) - **addon**: Publish dev addon version 7.5.0.dev350 \[skip ci] ([`e93d680`](homeassistant-ai/ha-mcp@e93d680)) - **addon**: Publish dev addon version 7.5.0.dev349 \[skip ci] ([`1631ad1`](homeassistant-ai/ha-mcp@1631ad1)) - **addon**: Publish dev addon version 7.5.0.dev348 \[skip ci] ([`18a8aef`](homeassistant-ai/ha-mcp@18a8aef)) - Sync tool docs after merge \[skip ci] ([`9e0493d`](homeassistant-ai/ha-mcp@9e0493d)) - **addon**: Publish dev addon version 7.5.0.dev347 \[skip ci] ([`e2067e4`](homeassistant-ai/ha-mcp@e2067e4)) - Sync tool docs after merge \[skip ci] ([`7bdb3d4`](homeassistant-ai/ha-mcp@7bdb3d4)) - **addon**: Publish dev addon version 7.5.0.dev346 \[skip ci] ([`c2d4dd7`](homeassistant-ai/ha-mcp@c2d4dd7)) - Sync tool docs after merge \[skip ci] ([`393b354`](homeassistant-ai/ha-mcp@393b354)) - **addon**: Publish dev addon version 7.5.0.dev345 \[skip ci] ([`42ede8b`](homeassistant-ai/ha-mcp@42ede8b)) - **addon**: Publish dev addon version 7.5.0.dev344 \[skip ci] ([`e6cc7a1`](homeassistant-ai/ha-mcp@e6cc7a1)) - Sync tool docs after merge \[skip ci] ([`fb35f30`](homeassistant-ai/ha-mcp@fb35f30)) - **addon**: Publish dev addon version 7.5.0.dev343 \[skip ci] ([`401b7b4`](homeassistant-ai/ha-mcp@401b7b4)) - **addon**: Publish dev addon version 7.5.0.dev342 \[skip ci] ([`0679371`](homeassistant-ai/ha-mcp@0679371)) - Sync tool docs after merge \[skip ci] ([`f6796ec`](homeassistant-ai/ha-mcp@f6796ec)) - **addon**: Publish dev addon version 7.5.0.dev341 \[skip ci] ([`3654478`](homeassistant-ai/ha-mcp@3654478)) - **addon**: Publish dev addon version 7.5.0.dev340 \[skip ci] ([`64f00b6`](homeassistant-ai/ha-mcp@64f00b6)) - **addon**: Publish dev addon version 7.5.0.dev339 \[skip ci] ([`d6e8873`](homeassistant-ai/ha-mcp@d6e8873)) - Sync tool docs after merge \[skip ci] ([`7525e93`](homeassistant-ai/ha-mcp@7525e93)) - **addon**: Publish dev addon version 7.5.0.dev338 \[skip ci] ([`288ca4a`](homeassistant-ai/ha-mcp@288ca4a)) - **addon**: Publish dev addon version 7.5.0.dev337 \[skip ci] ([`f539ae5`](homeassistant-ai/ha-mcp@f539ae5)) - **addon**: Publish dev addon version 7.5.0.dev336 \[skip ci] ([`5568a86`](homeassistant-ai/ha-mcp@5568a86)) - **addon**: Publish dev addon version 7.5.0.dev335 \[skip ci] ([`e069405`](homeassistant-ai/ha-mcp@e069405)) - **addon**: Publish dev addon version 7.5.0.dev334 \[skip ci] ([`f7be6ea`](homeassistant-ai/ha-mcp@f7be6ea)) - **addon**: Publish dev addon version 7.5.0.dev333 \[skip ci] ([`cb480ea`](homeassistant-ai/ha-mcp@cb480ea)) - Sync tool docs after merge \[skip ci] ([`9a5bc3c`](homeassistant-ai/ha-mcp@9a5bc3c)) - **addon**: Publish dev addon version 7.5.0.dev332 \[skip ci] ([`e0e59ee`](homeassistant-ai/ha-mcp@e0e59ee)) - Sync tool docs after merge \[skip ci] ([`499ebf0`](homeassistant-ai/ha-mcp@499ebf0)) - **addon**: Publish dev addon version 7.5.0.dev331 \[skip ci] ([`3e0ce92`](homeassistant-ai/ha-mcp@3e0ce92)) - **addon**: Publish dev addon version 7.5.0.dev330 \[skip ci] ([`e48d056`](homeassistant-ai/ha-mcp@e48d056)) - **deps**: Update ghcr.io/astral-sh/uv docker tag to v0.11.15 ([#​1376](homeassistant-ai/ha-mcp#1376)) - **deps**: Update ghcr.io/home-assistant/home-assistant docker tag to v2026.5.3 ([#​1377](homeassistant-ai/ha-mcp#1377)) - **addon**: Publish dev addon version 7.5.0.dev329 \[skip ci] ([`c523c50`](homeassistant-ai/ha-mcp@c523c50)) - Sync tool docs after merge \[skip ci] ([`5b7a8aa`](homeassistant-ai/ha-mcp@5b7a8aa)) - **addon**: Publish dev addon version 7.5.0.dev328 \[skip ci] ([`6c42fba`](homeassistant-ai/ha-mcp@6c42fba)) - **addon**: Publish dev addon version 7.5.0.dev327 \[skip ci] ([`aecd025`](homeassistant-ai/ha-mcp@aecd025)) - **addon**: Publish dev addon version 7.5.0.dev326 \[skip ci] ([`399c17c`](homeassistant-ai/ha-mcp@399c17c)) - **addon**: Publish dev addon version 7.5.0.dev325 \[skip ci] ([`b580b45`](homeassistant-ai/ha-mcp@b580b45)) - Sync tool docs after merge \[skip ci] ([`8567c3a`](homeassistant-ai/ha-mcp@8567c3a)) - **addon**: Publish dev addon version 7.5.0.dev324 \[skip ci] ([`a65579d`](homeassistant-ai/ha-mcp@a65579d)) - **addon**: Publish dev addon version 7.5.0.dev323 \[skip ci] ([`c7667ba`](homeassistant-ai/ha-mcp@c7667ba)) - **addon**: Publish dev addon version 7.5.0.dev322 \[skip ci] ([`44d15a8`](homeassistant-ai/ha-mcp@44d15a8)) - **addon**: Publish dev addon version 7.5.0.dev321 \[skip ci] ([`8739f6c`](homeassistant-ai/ha-mcp@8739f6c)) - **addon**: Publish dev addon version 7.5.0.dev320 \[skip ci] ([`02b6e47`](homeassistant-ai/ha-mcp@02b6e47)) - Sync tool docs after merge \[skip ci] ([`ab68c9a`](homeassistant-ai/ha-mcp@ab68c9a)) - **addon**: Publish dev addon version 7.5.0.dev319 \[skip ci] ([`4472904`](homeassistant-ai/ha-mcp@4472904)) - **addon**: Publish dev addon version 7.5.0.dev318 \[skip ci] ([`e030dbc`](homeassistant-ai/ha-mcp@e030dbc)) - **addon**: Publish dev addon version 7.5.0.dev317 \[skip ci] ([`d87855c`](homeassistant-ai/ha-mcp@d87855c)) - Sync tool docs after merge \[skip ci] ([`a72a4e8`](homeassistant-ai/ha-mcp@a72a4e8)) - **addon**: Publish dev addon version 7.5.0.dev316 \[skip ci] ([`bd9397f`](homeassistant-ai/ha-mcp@bd9397f)) - **addon**: Publish dev addon version 7.5.0.dev315 \[skip ci] ([`264bfc2`](homeassistant-ai/ha-mcp@264bfc2)) - **addon**: Publish dev addon version 7.5.0.dev314 \[skip ci] ([`df62881`](homeassistant-ai/ha-mcp@df62881)) - **addon**: Publish dev addon version 7.5.0.dev313 \[skip ci] ([`f6c47ca`](homeassistant-ai/ha-mcp@f6c47ca)) - **addon**: Publish dev addon version 7.5.0.dev312 \[skip ci] ([`2bb7a74`](homeassistant-ai/ha-mcp@2bb7a74)) - Sync tool docs after merge \[skip ci] ([`137e279`](homeassistant-ai/ha-mcp@137e279)) - **addon**: Publish dev addon version 7.5.0.dev311 \[skip ci] ([`28324ea`](homeassistant-ai/ha-mcp@28324ea)) - Sync tool docs after merge \[skip ci] ([`9a753d4`](homeassistant-ai/ha-mcp@9a753d4)) - **addon**: Publish dev addon version 7.5.0.dev310 \[skip ci] ([`f893b2e`](homeassistant-ai/ha-mcp@f893b2e)) - **addon**: Publish dev addon version 7.5.0.dev309 \[skip ci] ([`8cbdb7b`](homeassistant-ai/ha-mcp@8cbdb7b)) - **addon**: Publish dev addon version 7.5.0.dev308 \[skip ci] ([`2d18016`](homeassistant-ai/ha-mcp@2d18016)) - **addon**: Publish dev addon version 7.5.0.dev307 \[skip ci] ([`3fc3b28`](homeassistant-ai/ha-mcp@3fc3b28)) - Sync tool docs after merge \[skip ci] ([`9e6cff8`](homeassistant-ai/ha-mcp@9e6cff8)) - **addon**: Publish dev addon version 7.5.0.dev306 \[skip ci] ([`8bdd0fc`](homeassistant-ai/ha-mcp@8bdd0fc)) - **addon**: Publish dev addon version 7.5.0.dev305 \[skip ci] ([`83535b9`](homeassistant-ai/ha-mcp@83535b9)) - **addon**: Publish dev addon version 7.5.0.dev304 \[skip ci] ([`1435b3a`](homeassistant-ai/ha-mcp@1435b3a)) - **addon**: Publish dev addon version 7.5.0.dev303 \[skip ci] ([`e2da659`](homeassistant-ai/ha-mcp@e2da659)) - Sync tool docs after merge \[skip ci] ([`23789fa`](homeassistant-ai/ha-mcp@23789fa)) - **addon**: Publish dev addon version 7.5.0.dev302 \[skip ci] ([`6c8e574`](homeassistant-ai/ha-mcp@6c8e574)) - Sync tool docs after merge \[skip ci] ([`d2329cb`](homeassistant-ai/ha-mcp@d2329cb)) - **addon**: Publish dev addon version 7.5.0.dev301 \[skip ci] ([`bb538f7`](homeassistant-ai/ha-mcp@bb538f7)) - Sync tool docs after merge \[skip ci] ([`f70f0e1`](homeassistant-ai/ha-mcp@f70f0e1)) - **addon**: Publish version 7.5.0 \[skip ci] ([`9c5eb37`](homeassistant-ai/ha-mcp@9c5eb37)) ##### Continuous Integration - **deps**: Bump actions/upload-artifact in the github-actions group ([#​1437](homeassistant-ai/ha-mcp#1437)) - Share qcow2 cache + GHCR fallback between HAOS lanes ([#​1407](homeassistant-ai/ha-mcp#1407)) - Add ruff format --check on changed Python files ([#​1387](homeassistant-ai/ha-mcp#1387)) - Exempt assigned issues from stale bot ([#​1368](homeassistant-ai/ha-mcp#1368)) - **deps**: Bump the github-actions group with 3 updates ([#​1362](homeassistant-ai/ha-mcp#1362)) ##### Refactoring - Consolidate lovelace/dashboards/list through shared helper ([#​1344](homeassistant-ai/ha-mcp#1344)) ##### Testing - **haos-e2e**: Bake + install webhook-proxy addon and exercise its runtime ([#​1443](homeassistant-ai/ha-mcp#1443)) - **config-subentry**: Mark forecast\_solar e2e as known flaky + relative-import sweep ([#​1430](homeassistant-ai/ha-mcp#1430)) - **haos-e2e**: Trim cache-save race, compress GHCR qcow2, eval boot snapshot ([#​1428](homeassistant-ai/ha-mcp#1428)) - JSDOM behaviour harness + auto-discovery parse coverage for every rendered <script> ([#​1425](homeassistant-ai/ha-mcp#1425)) - **hacs**: Retry TestMcpToolsInstallation on flake ([#​1426](homeassistant-ai/ha-mcp#1426)) - **e2e**: Drop redundant lifecycle roundtrips, keep only Matter Server ([#​1414](homeassistant-ai/ha-mcp#1414)) ([#​1419](homeassistant-ai/ha-mcp#1419)) - **e2e**: Assert backend dispatch matches workflow env on every lane ([#​1409](homeassistant-ai/ha-mcp#1409)) - Escape ideographic space and format file ([#​1237](homeassistant-ai/ha-mcp#1237)) ([#​1410](homeassistant-ai/ha-mcp#1410)) - **e2e**: Measure \_POLL\_CADENCE p50/p99 to validate or retune (closes [#​1389](homeassistant-ai/ha-mcp#1389)) ([#​1398](homeassistant-ai/ha-mcp#1398)) - **e2e**: Wait for addon state=started in haos proxy header test ([#​1402](homeassistant-ai/ha-mcp#1402)) - Pin remaining \_classify\_by\_message branches ([#​1385](homeassistant-ai/ha-mcp#1385)) - **haos-e2e**: Slim addon set + real-addon ha\_manage\_addon coverage (closes [#​1350](homeassistant-ai/ha-mcp#1350)) ([#​1379](homeassistant-ai/ha-mcp#1379)) - **haos-e2e**: Close out [#​1349](homeassistant-ai/ha-mcp#1349) — lifecycle, integrations, supervisor\_mock migration, no more skips ([#​1375](homeassistant-ai/ha-mcp#1375)) - **e2e**: Consolidate readiness gates onto /api/core/state (refs [#​366](homeassistant-ai/ha-mcp#366)) ([#​1372](homeassistant-ai/ha-mcp#1372)) - **e2e**: Tighten 5 readiness-gate budgets with 2-63x headroom (refs [#​366](homeassistant-ai/ha-mcp#366)) ([#​1369](homeassistant-ai/ha-mcp#1369)) - Scaffold HAOS E2E tier image-build pipeline (refs [#​1281](homeassistant-ai/ha-mcp#1281)) ([#​1326](homeassistant-ai/ha-mcp#1326)) - **e2e**: Instrument HA\_MCP\_TOOLS\_WAIT readiness gate (refs [#​366](homeassistant-ai/ha-mcp#366)) ([#​1346](homeassistant-ai/ha-mcp#1346)) - **e2e**: Centralize wait\_for\_entity\_registration helper (refs [#​366](homeassistant-ai/ha-mcp#366)) ([#​1308](homeassistant-ai/ha-mcp#1308)) - **e2e**: Unify dict-error message extraction across e2e tests (refs [#​366](homeassistant-ai/ha-mcp#366)) ([#​1311](homeassistant-ai/ha-mcp#1311)) - **e2e**: Surface readiness-gate elapsed times in CI logs (refs [#​366](homeassistant-ai/ha-mcp#366)) ([#​1310](homeassistant-ai/ha-mcp#1310)) </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/904
…➔ 7.7.0) (#994)
This PR contains the following updates:
| Package | Update | Change |
|---|---|---|
| [ghcr.io/homeassistant-ai/ha-mcp](https://github.com/homeassistant-ai/ha-mcp) | minor | `7.5.0` → `7.7.0` |
---
### Release Notes
<details>
<summary>homeassistant-ai/ha-mcp (ghcr.io/homeassistant-ai/ha-mcp)</summary>
### [`v7.7.0`](https://github.com/homeassistant-ai/ha-mcp/blob/HEAD/CHANGELOG.md#v770-2026-06-10)
[Compare Source](https://github.com/homeassistant-ai/ha-mcp/compare/v7.6.0...v7.7.0)
##### Added
- User-configurable custom filesystem directories for the file tools (closes [#​1567](https://github.com/homeassistant-ai/ha-mcp/issues/1567))
([#​1568](https://github.com/homeassistant-ai/ha-mcp/pull/1568))
- Expose all user-tunable env vars in the settings UI (add-on parity)
([#​1554](https://github.com/homeassistant-ai/ha-mcp/pull/1554))
- Warn when default MCP\_SECRET\_PATH is bound non-loopback
([#​1472](https://github.com/homeassistant-ai/ha-mcp/pull/1472))
- **search**: Consolidate ha\_search\_entities + ha\_deep\_search into ha\_search
([#​1529](https://github.com/homeassistant-ai/ha-mcp/pull/1529))
- **addon**: Install the MCP Server add-on from the ha\_mcp\_tools integration
([#​1528](https://github.com/homeassistant-ai/ha-mcp/pull/1528))
- Add opt-in dashboard screenshot mode
([#​1510](https://github.com/homeassistant-ai/ha-mcp/pull/1510))
- Add Linux support for install & docs
([#​1096](https://github.com/homeassistant-ai/ha-mcp/pull/1096))
- Surface the web settings page for non-add-on installs ([#​1458](https://github.com/homeassistant-ai/ha-mcp/issues/1458))
([#​1511](https://github.com/homeassistant-ai/ha-mcp/pull/1511))
- Convert Pydantic arg-validation errors to actionable ToolErrors
([#​1491](https://github.com/homeassistant-ai/ha-mcp/pull/1491))
- Per-key toggles for automation/script/scene in packages/\*.yaml
([#​1476](https://github.com/homeassistant-ai/ha-mcp/pull/1476))
- Direct skills retrieval for write tools + improved best practice checker warnings with embedded skills responses ([#​1182](https://github.com/homeassistant-ai/ha-mcp/issues/1182))
([#​1448](https://github.com/homeassistant-ai/ha-mcp/pull/1448))
- Detect last\_changed/last\_updated duration math and suggest for: field ([#​1157](https://github.com/homeassistant-ai/ha-mcp/issues/1157))
([#​1264](https://github.com/homeassistant-ai/ha-mcp/pull/1264))
- Advanced settings panel + nested beta master toggle ([#​1164](https://github.com/homeassistant-ai/ha-mcp/issues/1164))
([#​1431](https://github.com/homeassistant-ai/ha-mcp/pull/1431))
- Allow automation/script/scene yaml\_path in packages/\*.yaml only
([#​1452](https://github.com/homeassistant-ai/ha-mcp/pull/1452))
- Restrict ha\_mcp\_tools services to ha-mcp callers (caller token + ha\_call\_service refusal)
([#​1459](https://github.com/homeassistant-ai/ha-mcp/pull/1459))
##### Changed
- **security**: Soften vulnerability-response SLA to best-effort
([`a24e7da`](https://github.com/homeassistant-ai/ha-mcp/commit/a24e7da4787aad570ac2998a5732de06229fa160))
- Update contributors list \[contributors-updated]
([`7cc187f`](https://github.com/homeassistant-ai/ha-mcp/commit/7cc187f4de2f6eb58cafaa4fb21f8016cb180a61))
- Telemetry wording — follow HA analytics setting, not opt-in-only
([#​1481](https://github.com/homeassistant-ai/ha-mcp/pull/1481))
- **security**: Note that security-advisory disposition is API-blind (UI-only)
([#​1561](https://github.com/homeassistant-ai/ha-mcp/pull/1561))
- **tools**: Sharpen ha\_eval\_template usage routing for compute-from-state queries
([#​1550](https://github.com/homeassistant-ai/ha-mcp/pull/1550))
- Differentiate ha-mcp from Home Assistant's built-in MCP Server
([#​1542](https://github.com/homeassistant-ai/ha-mcp/pull/1542))
- Update advanced mode notes
([#​1533](https://github.com/homeassistant-ai/ha-mcp/pull/1533))
- **[#​1157](https://github.com/homeassistant-ai/ha-mcp/issues/1157)**: Scripts native-for: guidance + fix numeric\_state-condition for: overclaim
([#​1480](https://github.com/homeassistant-ai/ha-mcp/pull/1480))
- Clarify add-on vs uvx; add Codex + HTTP-native client setup
([#​1478](https://github.com/homeassistant-ai/ha-mcp/pull/1478))
- **security**: Explicit threat model for trusted clients, LAN, sandbox, and OAuth tokens
([#​1463](https://github.com/homeassistant-ai/ha-mcp/pull/1463))
- Clarify telemetry is a planned future feature, not implemented
([#​1469](https://github.com/homeassistant-ai/ha-mcp/pull/1469))
##### Fixed
- **tools**: Bring HA API field names to 2026.6 — stale docstrings, automation plural canonicalization, fan speed (closes [#​1540](https://github.com/homeassistant-ai/ha-mcp/issues/1540))
([#​1566](https://github.com/homeassistant-ai/ha-mcp/pull/1566))
- **energy**: Accept "water" energy source in ha\_manage\_energy\_prefs
([#​1553](https://github.com/homeassistant-ai/ha-mcp/pull/1553))
- **tools**: Use action: not service: in automation docstring examples
([#​1539](https://github.com/homeassistant-ai/ha-mcp/pull/1539))
- **security**: Narrow GHSA-mc92-ww4q-6fg4 to the masker and log redaction
([#​1512](https://github.com/homeassistant-ai/ha-mcp/pull/1512))
- **addon**: Restrict settings UI root routes to HA ingress
([#​1508](https://github.com/homeassistant-ai/ha-mcp/pull/1508))
- Add name attributes to generated settings-UI form controls (a11y)
([#​1497](https://github.com/homeassistant-ai/ha-mcp/pull/1497))
- Add-on-aware code-mode locked note + suppress settings-UI favicon 404
([#​1494](https://github.com/homeassistant-ai/ha-mcp/pull/1494))
- Surface the real reason a WebSocket connection failed
([#​1495](https://github.com/homeassistant-ai/ha-mcp/pull/1495))
- Remove str from ha\_bulk\_control.operations schema + fix wrong-reason test
([#​1492](https://github.com/homeassistant-ai/ha-mcp/pull/1492))
- Remove str from bool/int param schemas across all tools
([#​1490](https://github.com/homeassistant-ai/ha-mcp/pull/1490))
- **addon**: Expose non-beta tool options on the stable add-on
([#​1488](https://github.com/homeassistant-ai/ha-mcp/pull/1488))
- **addon**: Enable ingress so the stable add-on shows the Open Web UI / Settings UI
([#​1486](https://github.com/homeassistant-ai/ha-mcp/pull/1486))
- Refine last\_changed/last\_updated duration-math detector ([#​1157](https://github.com/homeassistant-ai/ha-mcp/issues/1157))
([#​1483](https://github.com/homeassistant-ai/ha-mcp/pull/1483))
- Remove str from config param schema on service and entity tools
([#​1487](https://github.com/homeassistant-ai/ha-mcp/pull/1487))
- Surface flow-helper config to agents reading UI-created templates
([#​1474](https://github.com/homeassistant-ai/ha-mcp/pull/1474))
- Remove str from config param schema on set tools
([#​1485](https://github.com/homeassistant-ai/ha-mcp/pull/1485))
- Route malformed ha\_mcp\_tools version to a distinct reinstall error
([#​1484](https://github.com/homeassistant-ai/ha-mcp/pull/1484))
- Persist DCR client registrations and HMAC secret across restarts ([#​1261](https://github.com/homeassistant-ai/ha-mcp/issues/1261))
([#​1265](https://github.com/homeassistant-ai/ha-mcp/pull/1265))
- Stop dev builds from publishing the :latest Docker tag
([#​1477](https://github.com/homeassistant-ai/ha-mcp/pull/1477))
- Subscribe to HACS dispatch signal instead of 10x1s blind poll
([#​1455](https://github.com/homeassistant-ai/ha-mcp/pull/1455))
- Reject python\_transform while loops
([#​1462](https://github.com/homeassistant-ai/ha-mcp/pull/1462))
##### Performance Improvements
- Fast-fail HACS not-found lookups + batch-verify deep-search E2E fixtures ([#​1515](https://github.com/homeassistant-ai/ha-mcp/issues/1515))
([#​1552](https://github.com/homeassistant-ai/ha-mcp/pull/1552))
##### Refactoring
- Add display title to ha\_get\_skill\_guide tool
([#​1543](https://github.com/homeassistant-ai/ha-mcp/pull/1543))
- Fold ha\_check\_config into ha\_get\_system\_health include="config\_check"
([#​1516](https://github.com/homeassistant-ai/ha-mcp/pull/1516))
- **c901**: Smart\_search.py below C901 threshold
([#​1507](https://github.com/homeassistant-ai/ha-mcp/pull/1507))
- **hacs**: Consolidate HACS tools into ha\_get\_hacs + ha\_manage\_hacs ([#​1045](https://github.com/homeassistant-ai/ha-mcp/issues/1045))
([#​1502](https://github.com/homeassistant-ai/ha-mcp/pull/1502))
- **c901**: Tools\_config\_helpers.py below C901 threshold
([#​1498](https://github.com/homeassistant-ai/ha-mcp/pull/1498))
- **complexity**: Reduce C901 in tools\_addons.py via class-based pattern
([#​1432](https://github.com/homeassistant-ai/ha-mcp/pull/1432))
***
<details>
<summary>Internal Changes</summary>
##### Changed
- Trim AGENTS.md below 40k + improve subdirectory CLAUDE.md files
([#​1499](https://github.com/homeassistant-ai/ha-mcp/pull/1499))
##### Chores
- **addon**: Publish dev addon version 7.6.0.dev415 \[skip ci]
([`2c0148b`](https://github.com/homeassistant-ai/ha-mcp/commit/2c0148ba512a02b5299edbb4086c38410777a295))
- **deps**: Update ghcr.io/home-assistant/home-assistant docker tag to v2026.6.1
([#​1571](https://github.com/homeassistant-ai/ha-mcp/pull/1571))
- **deps**: Update ghcr.io/astral-sh/uv docker tag to v0.11.19
([#​1570](https://github.com/homeassistant-ai/ha-mcp/pull/1570))
- **addon**: Publish dev addon version 7.6.0.dev414 \[skip ci]
([`0bf9e39`](https://github.com/homeassistant-ai/ha-mcp/commit/0bf9e39947e8bf87d18bae23877d6b0d955dd35f))
- Sync tool docs after merge \[skip ci]
([`8f5e037`](https://github.com/homeassistant-ai/ha-mcp/commit/8f5e037b89296fd483888d158d8f72f4b1b7dfa8))
- **addon**: Publish dev addon version 7.6.0.dev413 \[skip ci]
([`6729327`](https://github.com/homeassistant-ai/ha-mcp/commit/6729327de8c0747f5cc7bb639859f95bbe1f0cfc))
- Sync tool docs after merge \[skip ci]
([`4341e95`](https://github.com/homeassistant-ai/ha-mcp/commit/4341e9574b3270c67bc016676f854f585fec816f))
- **addon**: Publish dev addon version 7.6.0.dev412 \[skip ci]
([`148f506`](https://github.com/homeassistant-ai/ha-mcp/commit/148f506a98c8f89292616a3a05dd0c9156516439))
- **addon**: Publish dev addon version 7.6.0.dev411 \[skip ci]
([`287fe55`](https://github.com/homeassistant-ai/ha-mcp/commit/287fe5503917e551f2dcb363cd28250237ed880c))
- Sync tool docs after merge \[skip ci]
([`b642b8e`](https://github.com/homeassistant-ai/ha-mcp/commit/b642b8eba67d8015d8fe5a1c1f88c9dd72ffc45f))
- **addon**: Publish dev addon version 7.6.0.dev410 \[skip ci]
([`29e34dd`](https://github.com/homeassistant-ai/ha-mcp/commit/29e34dd6eb517399de3c0a6a886e45ecf4749923))
- **addon**: Publish dev addon version 7.6.0.dev409 \[skip ci]
([`dec16a1`](https://github.com/homeassistant-ai/ha-mcp/commit/dec16a12d2ac3341908b130e9ea79f950d02466b))
- Sync tool docs after merge \[skip ci]
([`dd72535`](https://github.com/homeassistant-ai/ha-mcp/commit/dd725357f5d48a00959aaa7eceb4bad67a7ba202))
- **addon**: Publish dev addon version 7.6.0.dev408 \[skip ci]
([`c3c89f1`](https://github.com/homeassistant-ai/ha-mcp/commit/c3c89f1a758b6086b59ff21f9044597da103fa25))
- **addon**: Publish dev addon version 7.6.0.dev407 \[skip ci]
([`94195ee`](https://github.com/homeassistant-ai/ha-mcp/commit/94195ee4c8dbd0d8eec13d7c3d7ee392e5b7240f))
- **addon**: Publish dev addon version 7.6.0.dev406 \[skip ci]
([`f439424`](https://github.com/homeassistant-ai/ha-mcp/commit/f4394240dd1170f9d978e3c4a5011bab12f17f54))
- Sync tool docs after merge \[skip ci]
([`7464277`](https://github.com/homeassistant-ai/ha-mcp/commit/746427745d3debccea57c844278d1ba834d7ebfb))
- **addon**: Publish dev addon version 7.6.0.dev405 \[skip ci]
([`146eb07`](https://github.com/homeassistant-ai/ha-mcp/commit/146eb073a6f260ed0b0653cdb71346e9d29deae7))
- **addon**: Publish dev addon version 7.6.0.dev404 \[skip ci]
([`6a707bb`](https://github.com/homeassistant-ai/ha-mcp/commit/6a707bba576b987f8c3395adca3d59f7dd8a1050))
- Sync tool docs after merge \[skip ci]
([`85f3935`](https://github.com/homeassistant-ai/ha-mcp/commit/85f3935f80d9677f791b3098b201ec9c27e643be))
- **addon**: Publish dev addon version 7.6.0.dev403 \[skip ci]
([`be1fa1d`](https://github.com/homeassistant-ai/ha-mcp/commit/be1fa1dd2693170cbe3c037e7a88cf02f1847dcf))
- Sync tool docs after merge \[skip ci]
([`d9adbd2`](https://github.com/homeassistant-ai/ha-mcp/commit/d9adbd2c27750c9bc8faa55470d24564c48b3dbf))
- **addon**: Publish dev addon version 7.6.0.dev402 \[skip ci]
([`41ad7ca`](https://github.com/homeassistant-ai/ha-mcp/commit/41ad7caf1e0d982dd9e7bda3420ba3ca577cf765))
- **addon**: Publish dev addon version 7.6.0.dev401 \[skip ci]
([`8205034`](https://github.com/homeassistant-ai/ha-mcp/commit/820503485386f13dc66a0da3d304739e1f03dafd))
- **deps**: Update ghcr.io/astral-sh/uv docker tag to v0.11.18
([#​1523](https://github.com/homeassistant-ai/ha-mcp/pull/1523))
- **addon**: Publish dev addon version 7.6.0.dev400 \[skip ci]
([`532cdc4`](https://github.com/homeassistant-ai/ha-mcp/commit/532cdc440a8db053c524579f3e6b48b099c13c66))
- Sync tool docs after merge \[skip ci]
([`e2c08ff`](https://github.com/homeassistant-ai/ha-mcp/commit/e2c08ff797ffabf7b39bfc4b22b498b1c02ce1fa))
- **addon**: Publish dev addon version 7.6.0.dev399 \[skip ci]
([`9501348`](https://github.com/homeassistant-ai/ha-mcp/commit/95013488ea99761535ea9532285839bcd0ec8e3b))
- Sync tool docs after merge \[skip ci]
([`e70a050`](https://github.com/homeassistant-ai/ha-mcp/commit/e70a050efcb6edeb65d51dabd5307a192a22e66c))
- **addon**: Publish dev addon version 7.6.0.dev398 \[skip ci]
([`0b61424`](https://github.com/homeassistant-ai/ha-mcp/commit/0b61424ed823453dec27bb173d049f901eddc2d3))
- Sync tool docs after merge \[skip ci]
([`6df7987`](https://github.com/homeassistant-ai/ha-mcp/commit/6df79877669686a9fee3ec04979dff3960bc5e3f))
- **addon**: Publish dev addon version 7.6.0.dev397 \[skip ci]
([`c34915f`](https://github.com/homeassistant-ai/ha-mcp/commit/c34915f40cd82f83f0eb4af5c3a5655843608770))
- Sync tool docs after merge \[skip ci]
([`6f88e7e`](https://github.com/homeassistant-ai/ha-mcp/commit/6f88e7e0c8dcb7fee27792e0f87f6acd8aa892c4))
- **addon**: Publish dev addon version 7.6.0.dev396 \[skip ci]
([`1490e19`](https://github.com/homeassistant-ai/ha-mcp/commit/1490e190382454b17fc14cd362b17612a6af253f))
- Sync tool docs after merge \[skip ci]
([`ac2c7d0`](https://github.com/homeassistant-ai/ha-mcp/commit/ac2c7d038a90fb44466afa8f047378d7e8daed94))
- **addon**: Publish dev addon version 7.6.0.dev395 \[skip ci]
([`11e5ee8`](https://github.com/homeassistant-ai/ha-mcp/commit/11e5ee8f07f63f63b8cdf017397263c7602e80f6))
- **addon**: Publish dev addon version 7.6.0.dev394 \[skip ci]
([`5fc3e0f`](https://github.com/homeassistant-ai/ha-mcp/commit/5fc3e0f572bfd1bb367e65b3f4d78b96cb78fa91))
- Flag untrusted third-party content in HACS and add-on tool responses
([#​1509](https://github.com/homeassistant-ai/ha-mcp/pull/1509))
- **addon**: Publish dev addon version 7.6.0.dev393 \[skip ci]
([`9a37c28`](https://github.com/homeassistant-ai/ha-mcp/commit/9a37c28cfa0d1f3f652fe441ce2fe1d72a7360ab))
- **addon**: Publish dev addon version 7.6.0.dev392 \[skip ci]
([`4f737ac`](https://github.com/homeassistant-ai/ha-mcp/commit/4f737ac7c116e9afa046ab45b1230e2cdb5ae959))
- **addon**: Publish dev addon version 7.6.0.dev391 \[skip ci]
([`fd5d3f2`](https://github.com/homeassistant-ai/ha-mcp/commit/fd5d3f2d4ce87baa4cfcc85a173bb0cc9d132a35))
- **addon**: Publish dev addon version 7.6.0.dev390 \[skip ci]
([`28dedf4`](https://github.com/homeassistant-ai/ha-mcp/commit/28dedf43f3cd094b1c40fb50e535166cc8c33388))
- **addon**: Publish dev addon version 7.6.0.dev389 \[skip ci]
([`9443446`](https://github.com/homeassistant-ai/ha-mcp/commit/9443446fdd607a75d8db5fdad009130b188267d6))
- Sync tool docs after merge \[skip ci]
([`94fcbeb`](https://github.com/homeassistant-ai/ha-mcp/commit/94fcbeb14bd9cfa3bef274182f95e4562a379971))
- **addon**: Publish dev addon version 7.6.0.dev388 \[skip ci]
([`ccc1816`](https://github.com/homeassistant-ai/ha-mcp/commit/ccc18162eec520950c58cc8eabb2aac04ac57ab3))
- Drop dead entity\_cache attr + ruff-format fuzzy\_search.py
([#​1503](https://github.com/homeassistant-ai/ha-mcp/pull/1503))
- **addon**: Publish dev addon version 7.6.0.dev387 \[skip ci]
([`057c108`](https://github.com/homeassistant-ai/ha-mcp/commit/057c108b2958959bfee34225899b47b5c989a119))
- **addon**: Publish dev addon version 7.6.0.dev386 \[skip ci]
([`66f4ac6`](https://github.com/homeassistant-ai/ha-mcp/commit/66f4ac6a37d85412b895962afef1b03707400e56))
- **addon**: Publish dev addon version 7.6.0.dev385 \[skip ci]
([`f331f11`](https://github.com/homeassistant-ai/ha-mcp/commit/f331f1150f525a18bf5bd2e27007b46a07a3492c))
- **addon**: Publish dev addon version 7.6.0.dev384 \[skip ci]
([`17c319e`](https://github.com/homeassistant-ai/ha-mcp/commit/17c319e68ba4b4d4e6acd84deb57c588aafcb48b))
- Sync tool docs after merge \[skip ci]
([`f36cbb7`](https://github.com/homeassistant-ai/ha-mcp/commit/f36cbb7e620839b16808b37b61dbc7602557b409))
- **addon**: Publish dev addon version 7.6.0.dev383 \[skip ci]
([`782ba3b`](https://github.com/homeassistant-ai/ha-mcp/commit/782ba3b2bbcfe50564c5524d6a2c018a4c9c9ba6))
- **addon**: Publish dev addon version 7.6.0.dev382 \[skip ci]
([`b647ab6`](https://github.com/homeassistant-ai/ha-mcp/commit/b647ab6eea76a030c7e3c46f72d732ff339398fe))
- **addon**: Publish dev addon version 7.6.0.dev381 \[skip ci]
([`e999c24`](https://github.com/homeassistant-ai/ha-mcp/commit/e999c242553a60561ca06dbefe3177c627bb9e2d))
- Sync tool docs after merge \[skip ci]
([`50d76b0`](https://github.com/homeassistant-ai/ha-mcp/commit/50d76b04a0691c565fafaabc76fd4bd3cf321953))
- **addon**: Publish dev addon version 7.6.0.dev380 \[skip ci]
([`ebdc69b`](https://github.com/homeassistant-ai/ha-mcp/commit/ebdc69bde929fd3342234149956af0710b9f260a))
- Sync tool docs after merge \[skip ci]
([`1f03967`](https://github.com/homeassistant-ai/ha-mcp/commit/1f03967160156cbffdfc9fc7deb5ed9a2b25f2ba))
- **addon**: Publish dev addon version 7.6.0.dev379 \[skip ci]
([`7cabb2e`](https://github.com/homeassistant-ai/ha-mcp/commit/7cabb2ec342561dbc74251f7697e3c4df0a8fcb3))
- **addon**: Publish dev addon version 7.6.0.dev378 \[skip ci]
([`7b631c7`](https://github.com/homeassistant-ai/ha-mcp/commit/7b631c75e0e4163ee13906b90ddad7a1b744e402))
- **addon**: Publish dev addon version 7.6.0.dev377 \[skip ci]
([`ea7b614`](https://github.com/homeassistant-ai/ha-mcp/commit/ea7b614615606a8fc05a0a18cb9cafa2f0a42c0d))
- **addon**: Publish dev addon version 7.6.0.dev376 \[skip ci]
([`fd33ecd`](https://github.com/homeassistant-ai/ha-mcp/commit/fd33ecd4d260f5fc2ab4f229c90b1a4514c5ccde))
- Sync tool docs after merge \[skip ci]
([`ba8fae3`](https://github.com/homeassistant-ai/ha-mcp/commit/ba8fae3cc4f451dc65022756a86cce5275f6e35f))
- **addon**: Publish dev addon version 7.6.0.dev375 \[skip ci]
([`afcd0d8`](https://github.com/homeassistant-ai/ha-mcp/commit/afcd0d8e061e1cba65fd119727fc64ed77f1818d))
- Sync tool docs after merge \[skip ci]
([`f9b55ad`](https://github.com/homeassistant-ai/ha-mcp/commit/f9b55ad59c6f03d6a98c3d3f6dd52ba9ff7c8a7a))
- **addon**: Publish dev addon version 7.6.0.dev374 \[skip ci]
([`eecdf8b`](https://github.com/homeassistant-ai/ha-mcp/commit/eecdf8b058ba932ba94cfb292ebf2331a54d2def))
- Sync tool docs after merge \[skip ci]
([`ef16a8a`](https://github.com/homeassistant-ai/ha-mcp/commit/ef16a8a197c76e51a49ae6ac69eecb15d202a194))
- **addon**: Publish dev addon version 7.6.0.dev373 \[skip ci]
([`9a93703`](https://github.com/homeassistant-ai/ha-mcp/commit/9a9370362fe5573ac71cd6e90353877faccce8a6))
- **addon**: Publish dev addon version 7.6.0.dev372 \[skip ci]
([`7352ce8`](https://github.com/homeassistant-ai/ha-mcp/commit/7352ce88ef59feef74c29ab47f6991cc2ac132a8))
- **addon**: Publish dev addon version 7.6.0.dev371 \[skip ci]
([`d7601f5`](https://github.com/homeassistant-ai/ha-mcp/commit/d7601f5796308e1c42a01dbce9861460027a93c4))
- Sync tool docs after merge \[skip ci]
([`d0a4482`](https://github.com/homeassistant-ai/ha-mcp/commit/d0a448276306a08f8a52c4645f1b9c5aeaafd68e))
- **addon**: Publish dev addon version 7.6.0.dev370 \[skip ci]
([`f83c32c`](https://github.com/homeassistant-ai/ha-mcp/commit/f83c32c747ddaeccffb040bc28d3e08d7507ded4))
- **addon**: Publish dev addon version 7.6.0.dev369 \[skip ci]
([`ea16661`](https://github.com/homeassistant-ai/ha-mcp/commit/ea16661f1d144feada93aee119b625f968f990cb))
- **addon**: Publish dev addon version 7.6.0.dev368 \[skip ci]
([`af49ea5`](https://github.com/homeassistant-ai/ha-mcp/commit/af49ea5aff5c9f54914943cc2f8a67ebeea2fdee))
- **addon**: Publish dev addon version 7.6.0.dev367 \[skip ci]
([`7dd5f4c`](https://github.com/homeassistant-ai/ha-mcp/commit/7dd5f4cd0237ef4d80a454efe4dfc0801f18fdbd))
- **addon**: Publish dev addon version 7.6.0.dev366 \[skip ci]
([`6273b7e`](https://github.com/homeassistant-ai/ha-mcp/commit/6273b7ec8695706948eefe8e617cac39363940ce))
- Sync tool docs after merge \[skip ci]
([`4e3fd5f`](https://github.com/homeassistant-ai/ha-mcp/commit/4e3fd5f331ce5fefa8e0e5560da411de17f2a8db))
- **addon**: Publish dev addon version 7.6.0.dev365 \[skip ci]
([`f3bf17b`](https://github.com/homeassistant-ai/ha-mcp/commit/f3bf17be132ebc67005c33a3c8fde85025d56809))
- Sync tool docs after merge \[skip ci]
([`5307b60`](https://github.com/homeassistant-ai/ha-mcp/commit/5307b608879154fccf67bc1894f61e97f26719c6))
- **addon**: Publish dev addon version 7.6.0.dev364 \[skip ci]
([`76ec1ae`](https://github.com/homeassistant-ai/ha-mcp/commit/76ec1aefab8e904abf620bf1c1130e5f5d0c4bd9))
- Sync tool docs after merge \[skip ci]
([`be864b5`](https://github.com/homeassistant-ai/ha-mcp/commit/be864b5d685f167334487d4fe83324afbb4999ca))
- **addon**: Publish dev addon version 7.6.0.dev363 \[skip ci]
([`da10c75`](https://github.com/homeassistant-ai/ha-mcp/commit/da10c75a248dcc19442e4db6f34f325683cb0a71))
- **addon**: Publish dev addon version 7.6.0.dev362 \[skip ci]
([`69f4527`](https://github.com/homeassistant-ai/ha-mcp/commit/69f45279707d18c724bd702ced46111b26cd000c))
- **addon**: Publish version 7.6.0 \[skip ci]
([`086d75d`](https://github.com/homeassistant-ai/ha-mcp/commit/086d75d72dd7d1c735413d96ef2fd38ae57b90ca))
##### Continuous Integration
- Vendor Puppet add-on as a pinned submodule + retry transient add-on builds
([#​1565](https://github.com/homeassistant-ai/ha-mcp/pull/1565))
- Make sync-tool-docs push resilient to concurrent master advances
([#​1564](https://github.com/homeassistant-ai/ha-mcp/pull/1564))
- Fix stale token-cap comment and harden triage budget tests ([#​1514](https://github.com/homeassistant-ai/ha-mcp/issues/1514))
([#​1560](https://github.com/homeassistant-ai/ha-mcp/pull/1560))
- **deps**: Bump the github-actions group with 2 updates
([#​1556](https://github.com/homeassistant-ai/ha-mcp/pull/1556))
- Budget triage prompt dynamically under the GitHub Models cap ([#​1514](https://github.com/homeassistant-ai/ha-mcp/issues/1514))
([#​1522](https://github.com/homeassistant-ai/ha-mcp/pull/1522))
- Reduce Docker Hub pulls in performance-tests workflow
([#​1549](https://github.com/homeassistant-ai/ha-mcp/pull/1549))
- Add JavaScript to the CodeQL code-quality gate
([#​1548](https://github.com/homeassistant-ai/ha-mcp/pull/1548))
- Add CodeQL code-quality CI gate and clear all code-quality findings
([#​1526](https://github.com/homeassistant-ai/ha-mcp/pull/1526))
- Drop tool list from evaluate prompt + tighten caps to fit 8K token limit
([`6f47c92`](https://github.com/homeassistant-ai/ha-mcp/commit/6f47c92507ef0d854153632107c0c702812f0c3c))
- Remove broken maintainer check (GITHUB\_TOKEN lacks read:org)
([`010ec58`](https://github.com/homeassistant-ai/ha-mcp/commit/010ec58d1f3b6d46b20aa83c3caee373dd826694))
- Switch evaluate step to gpt-4o-mini (16K token free tier vs 8K on gpt-4.1)
([#​1496](https://github.com/homeassistant-ai/ha-mcp/pull/1496))
- Issue bot v2 — GitHub Models triage, needs-info auto-close, duplicate detection
([#​1442](https://github.com/homeassistant-ai/ha-mcp/pull/1442))
##### Refactoring
- Extract settings-UI JavaScript and CSS to separate files
([#​1505](https://github.com/homeassistant-ai/ha-mcp/pull/1505))
- Collapse settings-UI route registration into one table
([#​1504](https://github.com/homeassistant-ai/ha-mcp/pull/1504))
##### Testing
- **oauth**: Add HTTP smoke tests for OAuth metadata-discovery endpoints
([#​1562](https://github.com/homeassistant-ai/ha-mcp/pull/1562))
- **uat**: Relabel c01 as a mode-discrimination probe (taxonomy consistency)
([#​1563](https://github.com/homeassistant-ai/ha-mcp/pull/1563))
- **uat**: Rework c01 routing probe to ha\_search registry-listing mode after [#​1529](https://github.com/homeassistant-ai/ha-mcp/issues/1529)
([#​1559](https://github.com/homeassistant-ai/ha-mcp/pull/1559))
- **uat**: Add response\_contains\_any check and always log agent responses
([#​1537](https://github.com/homeassistant-ai/ha-mcp/pull/1537))
- **uat**: Treat request timeout as per-story failure, not suite abort
([#​1536](https://github.com/homeassistant-ai/ha-mcp/pull/1536))
- **uat**: Harden BAT story runner against agent crashes
([#​1535](https://github.com/homeassistant-ai/ha-mcp/pull/1535))
- **uat**: Log model and quantization in BAT story results
([#​1525](https://github.com/homeassistant-ai/ha-mcp/pull/1525))
- Capture reasoning tokens and detect inert --no-think in BAT openai agent
([#​1524](https://github.com/homeassistant-ai/ha-mcp/pull/1524))
</details>
### [`v7.6.0`](https://github.com/homeassistant-ai/ha-mcp/blob/HEAD/CHANGELOG.md#v760-2026-05-27)
[Compare Source](https://github.com/homeassistant-ai/ha-mcp/compare/v7.5.0...v7.6.0)
##### Added
- Make HTTP bind host configurable via MCP\_HOST (closes [#​1434](https://github.com/homeassistant-ai/ha-mcp/issues/1434))
([#​1436](https://github.com/homeassistant-ai/ha-mcp/pull/1436))
- Tool Security Policies — per-tool approval gating ([#​966](https://github.com/homeassistant-ai/ha-mcp/issues/966))
([#​1421](https://github.com/homeassistant-ai/ha-mcp/pull/1421))
- Rename ha\_delete\_helpers\_integrations → ha\_remove\_helpers\_integrations + raise on missing target
([#​1424](https://github.com/homeassistant-ai/ha-mcp/pull/1424))
- Auto-backup edited entities before write/destructive tool calls (closes [#​1288](https://github.com/homeassistant-ai/ha-mcp/issues/1288))
([#​1403](https://github.com/homeassistant-ai/ha-mcp/pull/1403))
- Persistent settings UI for stdio mode
([#​1381](https://github.com/homeassistant-ai/ha-mcp/pull/1381))
- Add fields= projection to ha\_search\_entities, ha\_get\_overview, ha\_get\_state, ha\_get\_history, ha\_config\_list\_areas, ha\_list\_services ([#​1199](https://github.com/homeassistant-ai/ha-mcp/issues/1199))
([#​1225](https://github.com/homeassistant-ai/ha-mcp/pull/1225))
- Route entity-registration wait through WS events (closes [#​1152](https://github.com/homeassistant-ai/ha-mcp/issues/1152))
([#​1382](https://github.com/homeassistant-ai/ha-mcp/pull/1382))
- Add config subentry support
([#​1393](https://github.com/homeassistant-ai/ha-mcp/pull/1393))
- Add Assist pipeline management tool
([#​1392](https://github.com/homeassistant-ai/ha-mcp/pull/1392))
- Add knx to ha\_config\_set\_yaml allowlist
([#​1374](https://github.com/homeassistant-ai/ha-mcp/pull/1374))
- Extend automation\_id parity to set/remove automation responses
([#​1343](https://github.com/homeassistant-ai/ha-mcp/pull/1343))
- **haos-e2e**: Add parallel inaddon test tier (ha-mcp runs inside HAOS addon)
([#​1361](https://github.com/homeassistant-ai/ha-mcp/pull/1361))
- Expose integration diagnostics via ha\_get\_integration and ha\_get\_system\_health (closes [#​1148](https://github.com/homeassistant-ai/ha-mcp/issues/1148))
([#​1328](https://github.com/homeassistant-ai/ha-mcp/pull/1328))
- Return canonical script\_id from ha\_config\_get\_script ([#​1334](https://github.com/homeassistant-ai/ha-mcp/issues/1334))
([#​1352](https://github.com/homeassistant-ai/ha-mcp/pull/1352))
- Add automation\_id parity key to ha\_config\_get\_automation
([#​1329](https://github.com/homeassistant-ai/ha-mcp/pull/1329))
- Reject empty/whitespace identifiers on registry-metadata writes (closes [#​1294](https://github.com/homeassistant-ai/ha-mcp/issues/1294))
([#​1312](https://github.com/homeassistant-ai/ha-mcp/pull/1312))
- Add HA brand assets for custom integration
([#​1317](https://github.com/homeassistant-ai/ha-mcp/pull/1317))
- Unify ha\_config\_set\_helper response shape (closes [#​1293](https://github.com/homeassistant-ai/ha-mcp/issues/1293))
([#​1303](https://github.com/homeassistant-ai/ha-mcp/pull/1303))
- Mirror create-side validation guards onto update path (closes [#​1292](https://github.com/homeassistant-ai/ha-mcp/issues/1292))
([#​1304](https://github.com/homeassistant-ai/ha-mcp/pull/1304))
- Add array\_patch mode to ha\_manage\_addon for atomic GET-modify-POST
([#​1063](https://github.com/homeassistant-ai/ha-mcp/pull/1063))
##### Changed
- **agents**: Drop ha\_backup\_create + ha\_backup\_restore from accepted exceptions
([#​1445](https://github.com/homeassistant-ai/ha-mcp/pull/1445))
- Update contributors list \[contributors-updated]
([`c7665a6`](https://github.com/homeassistant-ai/ha-mcp/commit/c7665a6f5a08737d8fcbebbbe6afdc88ec5c4901))
- **overview**: Enumerate dismissed\_repair\_count in fields= description + static drift test
([#​1411](https://github.com/homeassistant-ai/ha-mcp/pull/1411))
- Credit [@​tomwilkie](https://github.com/tomwilkie) and six other contributors in README
([#​1400](https://github.com/homeassistant-ai/ha-mcp/pull/1400))
- **[#​1157](https://github.com/homeassistant-ai/ha-mcp/issues/1157)**: Bump skills-vendor + auto-update via Renovate + native for: field + scrub eval\_template anti-patterns
([#​1383](https://github.com/homeassistant-ai/ha-mcp/pull/1383))
- Extend Boy Scout weasel-phrase list with common variants; clarify semantic match
([#​1373](https://github.com/homeassistant-ai/ha-mcp/pull/1373))
- Merge Boy Scout Rule + Handling Discovered Improvements; tighten deferral gate
([#​1359](https://github.com/homeassistant-ai/ha-mcp/pull/1359))
- Categorize Issue Labels table and document 6 reverse-drift labels
([#​1335](https://github.com/homeassistant-ai/ha-mcp/pull/1335))
- Strip stale L-refs from test\_identifier\_validation\_family docstrings
([#​1324](https://github.com/homeassistant-ai/ha-mcp/pull/1324))
- Align label refs with live label set and fix triaged-removal trigger
([#​1316](https://github.com/homeassistant-ai/ha-mcp/pull/1316))
- Surface tool-discovery / categorized search
([#​1123](https://github.com/homeassistant-ai/ha-mcp/pull/1123))
- Fix two stale ha\_get\_skill\_guide references missed in [#​1289](https://github.com/homeassistant-ai/ha-mcp/issues/1289)
([#​1305](https://github.com/homeassistant-ai/ha-mcp/pull/1305))
- Clarify setup wizard placeholders need braces removed ([#​1284](https://github.com/homeassistant-ai/ha-mcp/issues/1284))
([#​1286](https://github.com/homeassistant-ai/ha-mcp/pull/1286))
##### Fixed
- Remove counter from ha\_reload\_core targets ([#​1453](https://github.com/homeassistant-ai/ha-mcp/issues/1453))
([#​1456](https://github.com/homeassistant-ai/ha-mcp/pull/1456))
- **backup**: Post-timeout match correctness + state-gate (closes [#​1433](https://github.com/homeassistant-ai/ha-mcp/issues/1433))
([#​1435](https://github.com/homeassistant-ai/ha-mcp/pull/1435))
- Sync addon settings UI with Supervisor options end-to-end
([#​1420](https://github.com/homeassistant-ai/ha-mcp/pull/1420))
- **calendar**: Switch ha\_config\_remove\_calendar\_event to WebSocket (closes [#​1413](https://github.com/homeassistant-ai/ha-mcp/issues/1413), [#​1416](https://github.com/homeassistant-ai/ha-mcp/issues/1416))
([#​1418](https://github.com/homeassistant-ai/ha-mcp/pull/1418))
- Error-shape consistency for non-entity not-found (closes [#​1297](https://github.com/homeassistant-ai/ha-mcp/issues/1297))
([#​1397](https://github.com/homeassistant-ai/ha-mcp/pull/1397))
- Guard against silent automation overwrite on id mismatch ([#​1404](https://github.com/homeassistant-ai/ha-mcp/issues/1404))
([#​1405](https://github.com/homeassistant-ai/ha-mcp/pull/1405))
- Cache YAML instance to prevent CPU spikes in bulk edits ([#​1370](https://github.com/homeassistant-ai/ha-mcp/issues/1370))
([#​1371](https://github.com/homeassistant-ai/ha-mcp/pull/1371))
- **client**: Route get\_error\_log via hassio proxy on external-HAOS clients
([#​1360](https://github.com/homeassistant-ai/ha-mcp/pull/1360))
- Classify dashboard 404s ("unknown config specified") as RESOURCE\_NOT\_FOUND
([#​1345](https://github.com/homeassistant-ai/ha-mcp/pull/1345))
- Detect HA addon installs as http transport, not stdio ([#​1322](https://github.com/homeassistant-ai/ha-mcp/issues/1322))
([#​1327](https://github.com/homeassistant-ai/ha-mcp/pull/1327))
- Actionable 403 suggestion when addon has unmapped container ports ([#​1319](https://github.com/homeassistant-ai/ha-mcp/issues/1319))
([#​1325](https://github.com/homeassistant-ai/ha-mcp/pull/1325))
- Filter dismissed repairs in overview and system\_health ([#​1307](https://github.com/homeassistant-ai/ha-mcp/issues/1307))
([#​1309](https://github.com/homeassistant-ai/ha-mcp/pull/1309))
- Exit on HA container death + daily reset before CI check
([#​1295](https://github.com/homeassistant-ai/ha-mcp/pull/1295))
- Align ha\_config\_set\_dashboard with sibling re-fetch-after-save pattern ([#​1291](https://github.com/homeassistant-ai/ha-mcp/issues/1291))
([#​1301](https://github.com/homeassistant-ai/ha-mcp/pull/1301))
- Allow str.replace in python\_transform; hint at search mode on IndexError
([#​1287](https://github.com/homeassistant-ai/ha-mcp/pull/1287))
- **array\_patch**: Tighten validation and surface silent failures
([#​1285](https://github.com/homeassistant-ai/ha-mcp/pull/1285))
- HA Core proxy fallback for ha\_get\_logs(source=system\_service) on non-addon installs
([#​1283](https://github.com/homeassistant-ai/ha-mcp/pull/1283))
##### Performance Improvements
- Tighten \_poll\_for\_automation\_entity first-poll cadence
([#​1384](https://github.com/homeassistant-ai/ha-mcp/pull/1384))
- Parallelize ha\_get\_system\_health optional sections via asyncio.gather
([#​1336](https://github.com/homeassistant-ai/ha-mcp/pull/1336))
##### Refactoring
- **service**: Compact ha\_call\_service result default ([#​1446](https://github.com/homeassistant-ai/ha-mcp/issues/1446))
([#​1447](https://github.com/homeassistant-ai/ha-mcp/pull/1447))
- Rename ha\_update\_device → ha\_set\_device
([#​1444](https://github.com/homeassistant-ai/ha-mcp/pull/1444))
- Remove duplicate flat area/floor list tools (consolidation followup to [#​1016](https://github.com/homeassistant-ai/ha-mcp/issues/1016))
([#​1429](https://github.com/homeassistant-ai/ha-mcp/pull/1429))
- **complexity**: Migrate tools\_utility.py to class-based pattern
([#​1423](https://github.com/homeassistant-ai/ha-mcp/pull/1423))
- **complexity**: Reduce C901 violations in tools/ — batch 4
([#​1408](https://github.com/homeassistant-ai/ha-mcp/pull/1408))
- Route \_poll\_for\_automation\_entity through WS event waiter (closes [#​1395](https://github.com/homeassistant-ai/ha-mcp/issues/1395))
([#​1406](https://github.com/homeassistant-ai/ha-mcp/pull/1406))
- **yaml**: Use threading.local subclass for cached instance
([#​1396](https://github.com/homeassistant-ai/ha-mcp/pull/1396))
- Align dashboards 404 shape with sibling config tools
([#​1386](https://github.com/homeassistant-ai/ha-mcp/pull/1386))
- Complete singular warning → warnings list migration repo-wide (closes [#​1332](https://github.com/homeassistant-ai/ha-mcp/issues/1332))
([#​1341](https://github.com/homeassistant-ai/ha-mcp/pull/1341))
- Complete warnings-list migration for lifecycle-write tools
([#​1340](https://github.com/homeassistant-ai/ha-mcp/pull/1340))
- Drop redundant identifier echo key from ha\_config\_get\_automation
([#​1354](https://github.com/homeassistant-ai/ha-mcp/pull/1354))
- Drop logger.error in config-tool except blocks ([#​1302](https://github.com/homeassistant-ai/ha-mcp/issues/1302))
([#​1353](https://github.com/homeassistant-ai/ha-mcp/pull/1353))
- Extend validate\_identifier\_not\_empty to automations/scripts/dashboards CRUD (closes [#​1313](https://github.com/homeassistant-ai/ha-mcp/issues/1313))
([#​1321](https://github.com/homeassistant-ai/ha-mcp/pull/1321))
- Migrate tools\_config\_scenes inline empty-id guards to shared helper
([#​1320](https://github.com/homeassistant-ai/ha-mcp/pull/1320))
- Remove ha\_get\_helper\_schema (closes [#​1186](https://github.com/homeassistant-ai/ha-mcp/issues/1186))
([#​1315](https://github.com/homeassistant-ai/ha-mcp/pull/1315))
- Consolidate skill tools; fix stable submodule packaging
([#​1289](https://github.com/homeassistant-ai/ha-mcp/pull/1289))
- Align tools\_config\_automations.py error-handling with sibling pattern ([#​1290](https://github.com/homeassistant-ai/ha-mcp/issues/1290))
([#​1298](https://github.com/homeassistant-ai/ha-mcp/pull/1298))
***
<details>
<summary>Internal Changes</summary>
##### Fixed
- **ci**: Install libguestfs in HAOS publish workflow
([#​1358](https://github.com/homeassistant-ai/ha-mcp/pull/1358))
##### Build System
- **deps**: Bump esbuild from 0.24.2 to 0.25.0 in /tests/js
([#​1427](https://github.com/homeassistant-ai/ha-mcp/pull/1427))
- **deps**: Bump devalue from 5.6.4 to 5.8.1 in /site
([#​1282](https://github.com/homeassistant-ai/ha-mcp/pull/1282))
- **deps**: Bump astro from 6.1.6 to 6.1.10 in /site
([#​1274](https://github.com/homeassistant-ai/ha-mcp/pull/1274))
##### Chores
- **addon**: Publish dev addon version 7.5.0.dev360 \[skip ci]
([`ad7aed1`](https://github.com/homeassistant-ai/ha-mcp/commit/ad7aed13d6843967e2a259ae46fec2bbc6abc896))
- Sync tool docs after merge \[skip ci]
([`9c4984f`](https://github.com/homeassistant-ai/ha-mcp/commit/9c4984fc44d30c15a96372fbc1b401fbd679dc8f))
- **deps**: Update ghcr.io/home-assistant/home-assistant docker tag to v2026.5.4
([#​1450](https://github.com/homeassistant-ai/ha-mcp/pull/1450))
- **addon**: Publish dev addon version 7.5.0.dev359 \[skip ci]
([`b82d4ee`](https://github.com/homeassistant-ai/ha-mcp/commit/b82d4eea85792b620368d4859e99c143f9fbfadf))
- **deps**: Update ghcr.io/astral-sh/uv docker tag to v0.11.16
([#​1449](https://github.com/homeassistant-ai/ha-mcp/pull/1449))
- **addon**: Publish dev addon version 7.5.0.dev358 \[skip ci]
([`53fba6d`](https://github.com/homeassistant-ai/ha-mcp/commit/53fba6da76ce8c78a0de035883233a36762601bc))
- Sync tool docs after merge \[skip ci]
([`dc7750d`](https://github.com/homeassistant-ai/ha-mcp/commit/dc7750de16b60f70e40e6e5c8908d9e84e544683))
- **addon**: Publish dev addon version 7.5.0.dev357 \[skip ci]
([`fd150c9`](https://github.com/homeassistant-ai/ha-mcp/commit/fd150c9b9c4bdb9026e67eae340226c36b270d94))
- **addon**: Publish dev addon version 7.5.0.dev356 \[skip ci]
([`5fa1463`](https://github.com/homeassistant-ai/ha-mcp/commit/5fa14630229ba0d6b97d9328768e247bf9c20af4))
- **addon**: Publish dev addon version 7.5.0.dev355 \[skip ci]
([`174ac5d`](https://github.com/homeassistant-ai/ha-mcp/commit/174ac5dca7667702cd664420c50e0101366e6c3a))
- **addon**: Publish dev addon version 7.5.0.dev354 \[skip ci]
([`4f93989`](https://github.com/homeassistant-ai/ha-mcp/commit/4f939892dea2d1951541b1a557c51e957f6751c0))
- **addon**: Publish dev addon version 7.5.0.dev353 \[skip ci]
([`53f282f`](https://github.com/homeassistant-ai/ha-mcp/commit/53f282f19ee736637106f5baececa3939393778e))
- **addon**: Publish dev addon version 7.5.0.dev352 \[skip ci]
([`4911d46`](https://github.com/homeassistant-ai/ha-mcp/commit/4911d4682c4a865a93a8e821bc86bd26cef0ed5a))
- Sync tool docs after merge \[skip ci]
([`8a79837`](https://github.com/homeassistant-ai/ha-mcp/commit/8a798373a7b2f1adb94b93e65d626ab582c7bd5d))
- **addon**: Publish dev addon version 7.5.0.dev351 \[skip ci]
([`13afa9d`](https://github.com/homeassistant-ai/ha-mcp/commit/13afa9df026dd27332277140c34f7d41d0229efd))
- **addon**: Publish dev addon version 7.5.0.dev350 \[skip ci]
([`e93d680`](https://github.com/homeassistant-ai/ha-mcp/commit/e93d6806025c6d7fd2ef94c509a607c4ac85c8e0))
- **addon**: Publish dev addon version 7.5.0.dev349 \[skip ci]
([`1631ad1`](https://github.com/homeassistant-ai/ha-mcp/commit/1631ad10bdada4487d7b54049e92df6ddb29439a))
- **addon**: Publish dev addon version 7.5.0.dev348 \[skip ci]
([`18a8aef`](https://github.com/homeassistant-ai/ha-mcp/commit/18a8aef50675c1a881b279666e0af1b093679850))
- Sync tool docs after merge \[skip ci]
([`9e0493d`](https://github.com/homeassistant-ai/ha-mcp/commit/9e0493d248e23a8042841e90847662926395a448))
- **addon**: Publish dev addon version 7.5.0.dev347 \[skip ci]
([`e2067e4`](https://github.com/homeassistant-ai/ha-mcp/commit/e2067e446b127097e61d07516ae0e742ae2de6c8))
- Sync tool docs after merge \[skip ci]
([`7bdb3d4`](https://github.com/homeassistant-ai/ha-mcp/commit/7bdb3d402b60900a1012b8269e52b7cbeb400f84))
- **addon**: Publish dev addon version 7.5.0.dev346 \[skip ci]
([`c2d4dd7`](https://github.com/homeassistant-ai/ha-mcp/commit/c2d4dd7091653a618326f665fd34b5458d26c8f6))
- Sync tool docs after merge \[skip ci]
([`393b354`](https://github.com/homeassistant-ai/ha-mcp/commit/393b354e8a8e1280029eee9521971c693526970a))
- **addon**: Publish dev addon version 7.5.0.dev345 \[skip ci]
([`42ede8b`](https://github.com/homeassistant-ai/ha-mcp/commit/42ede8b0e6066faf3ed6f6920629a8d94d77f69a))
- **addon**: Publish dev addon version 7.5.0.dev344 \[skip ci]
([`e6cc7a1`](https://github.com/homeassistant-ai/ha-mcp/commit/e6cc7a1b8ed252f1aaa2b8c964e56c97a27b94c2))
- Sync tool docs after merge \[skip ci]
([`fb35f30`](https://github.com/homeassistant-ai/ha-mcp/commit/fb35f305cbf7de6807c29bd3ada9da2f028ff730))
- **addon**: Publish dev addon version 7.5.0.dev343 \[skip ci]
([`401b7b4`](https://github.com/homeassistant-ai/ha-mcp/commit/401b7b4d707dbb3c56a3afecad9e9d22ecbc7d1e))
- **addon**: Publish dev addon version 7.5.0.dev342 \[skip ci]
([`0679371`](https://github.com/homeassistant-ai/ha-mcp/commit/06793710b04a985ed0d66861266b9b79494e4111))
- Sync tool docs after merge \[skip ci]
([`f6796ec`](https://github.com/homeassistant-ai/ha-mcp/commit/f6796ec19b4596455ff54b58746bd3e075d5d280))
- **addon**: Publish dev addon version 7.5.0.dev341 \[skip ci]
([`3654478`](https://github.com/homeassistant-ai/ha-mcp/commit/3654478f80428d15671e49162acecea19d67f672))
- **addon**: Publish dev addon version 7.5.0.dev340 \[skip ci]
([`64f00b6`](https://github.com/homeassistant-ai/ha-mcp/commit/64f00b658846cad0e0714f37d221fb65327015cf))
- **addon**: Publish dev addon version 7.5.0.dev339 \[skip ci]
([`d6e8873`](https://github.com/homeassistant-ai/ha-mcp/commit/d6e88731556464deb768524dc24c90fd0a622a96))
- Sync tool docs after merge \[skip ci]
([`7525e93`](https://github.com/homeassistant-ai/ha-mcp/commit/7525e930a872871fed78f9b1461aea8e78eb5ad7))
- **addon**: Publish dev addon version 7.5.0.dev338 \[skip ci]
([`288ca4a`](https://github.com/homeassistant-ai/ha-mcp/commit/288ca4abd00b2b366cbaf671c1ace3398cc8f2fd))
- **addon**: Publish dev addon version 7.5.0.dev337 \[skip ci]
([`f539ae5`](https://github.com/homeassistant-ai/ha-mcp/commit/f539ae5aa881853d831e6952ff3af8bc85eb8b2a))
- **addon**: Publish dev addon version 7.5.0.dev336 \[skip ci]
([`5568a86`](https://github.com/homeassistant-ai/ha-mcp/commit/5568a861002cfb909e29368bd4e93ef0bd2e4c03))
- **addon**: Publish dev addon version 7.5.0.dev335 \[skip ci]
([`e069405`](https://github.com/homeassistant-ai/ha-mcp/commit/e0694054bd8627f6464379c34c1e3eec5b080a44))
- **addon**: Publish dev addon version 7.5.0.dev334 \[skip ci]
([`f7be6ea`](https://github.com/homeassistant-ai/ha-mcp/commit/f7be6ead486a32840a935a1e5ec78a34f8003c0d))
- **addon**: Publish dev addon version 7.5.0.dev333 \[skip ci]
([`cb480ea`](https://github.com/homeassistant-ai/ha-mcp/commit/cb480eae4d855345c19a6465351e0bdef2bdf5c3))
- Sync tool docs after merge \[skip ci]
([`9a5bc3c`](https://github.com/homeassistant-ai/ha-mcp/commit/9a5bc3c61372159bb936d7b929166924343dc76f))
- **addon**: Publish dev addon version 7.5.0.dev332 \[skip ci]
([`e0e59ee`](https://github.com/homeassistant-ai/ha-mcp/commit/e0e59ee08072bb4aac51e90928fab2d68f6156ce))
- Sync tool docs after merge \[skip ci]
([`499ebf0`](https://github.com/homeassistant-ai/ha-mcp/commit/499ebf0c9d4c4ec3784dd72782fe301cd9c19d60))
- **addon**: Publish dev addon version 7.5.0.dev331 \[skip ci]
([`3e0ce92`](https://github.com/homeassistant-ai/ha-mcp/commit/3e0ce92e11777a8fd9c86153e4c248007b8edae9))
- **addon**: Publish dev addon version 7.5.0.dev330 \[skip ci]
([`e48d056`](https://github.com/homeassistant-ai/ha-mcp/commit/e48d056ab356e11f8b2952b6c675307d1e76a895))
- **deps**: Update ghcr.io/astral-sh/uv docker tag to v0.11.15
([#​1376](https://github.com/homeassistant-ai/ha-mcp/pull/1376))
- **deps**: Update ghcr.io/home-assistant/home-assistant docker tag to v2026.5.3
([#​1377](https://github.com/homeassistant-ai/ha-mcp/pull/1377))
- **addon**: Publish dev addon version 7.5.0.dev329 \[skip ci]
([`c523c50`](https://github.com/homeassistant-ai/ha-mcp/commit/c523c502c5c6f282905620d3db489e9c69ec2472))
- Sync tool docs after merge \[skip ci]
([`5b7a8aa`](https://github.com/homeassistant-ai/ha-mcp/commit/5b7a8aa0794359a90d7b89a9cc61d73d8cf038d2))
- **addon**: Publish dev addon version 7.5.0.dev328 \[skip ci]
([`6c42fba`](https://github.com/homeassistant-ai/ha-mcp/commit/6c42fba92d4786d7498f738c53dfe50c899d0890))
- **addon**: Publish dev addon version 7.5.0.dev327 \[skip ci]
([`aecd025`](https://github.com/homeassistant-ai/ha-mcp/commit/aecd025eeea3d1edcd9466db3720cb17de71b90a))
- **addon**: Publish dev addon version 7.5.0.dev326 \[skip ci]
([`399c17c`](https://github.com/homeassistant-ai/ha-mcp/commit/399c17c36602a7767491df6e317186cb6291f3e4))
- **addon**: Publish dev addon version 7.5.0.dev325 \[skip ci]
([`b580b45`](https://github.com/homeassistant-ai/ha-mcp/commit/b580b452e9007deb33acc49098238988aa768603))
- Sync tool docs after merge \[skip ci]
([`8567c3a`](https://github.com/homeassistant-ai/ha-mcp/commit/8567c3a6e66e7bebbbad8e96b94058f8456deb14))
- **addon**: Publish dev addon version 7.5.0.dev324 \[skip ci]
([`a65579d`](https://github.com/homeassistant-ai/ha-mcp/commit/a65579d0b6e4a8bb7f8c1ed97fd432cd770c47a4))
- **addon**: Publish dev addon version 7.5.0.dev323 \[skip ci]
([`c7667ba`](https://github.com/homeassistant-ai/ha-mcp/commit/c7667ba66538f1ba8a06b7616fb15896bf021744))
- **addon**: Publish dev addon version 7.5.0.dev322 \[skip ci]
([`44d15a8`](https://github.com/homeassistant-ai/ha-mcp/commit/44d15a89cbacc2c38ab39868b380414507a6708b))
- **addon**: Publish dev addon version 7.5.0.dev321 \[skip ci]
([`8739f6c`](https://github.com/homeassistant-ai/ha-mcp/commit/8739f6c09121c88a596470df293ac8e7e0f1050a))
- **addon**: Publish dev addon version 7.5.0.dev320 \[skip ci]
([`02b6e47`](https://github.com/homeassistant-ai/ha-mcp/commit/02b6e47f8eb6c778f709d7adca115638c2fe98a2))
- Sync tool docs after merge \[skip ci]
([`ab68c9a`](https://github.com/homeassistant-ai/ha-mcp/commit/ab68c9a9aa94ac6861af7b59997ec679f1849503))
- **addon**: Publish dev addon version 7.5.0.dev319 \[skip ci]
([`4472904`](https://github.com/homeassistant-ai/ha-mcp/commit/44729040c11af0bd97189080c1ec59995fc563b4))
- **addon**: Publish dev addon version 7.5.0.dev318 \[skip ci]
([`e030dbc`](https://github.com/homeassistant-ai/ha-mcp/commit/e030dbcc99e002751834274b1d53da161ab27759))
- **addon**: Publish dev addon version 7.5.0.dev317 \[skip ci]
([`d87855c`](https://github.com/homeassistant-ai/ha-mcp/commit/d87855cf07cef9d9d7babf0bbec74d228149327d))
- Sync tool docs after merge \[skip ci]
([`a72a4e8`](https://github.com/homeassistant-ai/ha-mcp/commit/a72a4e8c0de99a8516f3820545642c37a31c17e5))
- **addon**: Publish dev addon version 7.5.0.dev316 \[skip ci]
([`bd9397f`](https://github.com/homeassistant-ai/ha-mcp/commit/bd9397f3a088a24a14af66a97afcf1c97904ef61))
- **addon**: Publish dev addon version 7.5.0.dev315 \[skip ci]
([`264bfc2`](https://github.com/homeassistant-ai/ha-mcp/commit/264bfc2fcb5ef6fe3ee6f9e073b69e0469eeafdd))
- **addon**: Publish dev addon version 7.5.0.dev314 \[skip ci]
([`df62881`](https://github.com/homeassistant-ai/ha-mcp/commit/df6288194cdde8b625132f19b0dd3edb2142a2b3))
- **addon**: Publish dev addon version 7.5.0.dev313 \[skip ci]
([`f6c47ca`](https://github.com/homeassistant-ai/ha-mcp/commit/f6c47caa21b0d82799b2be9330f97aa5494aa3c8))
- **addon**: Publish dev addon version 7.5.0.dev312 \[skip ci]
([`2bb7a74`](https://github.com/homeassistant-ai/ha-mcp/commit/2bb7a74f06e0652a729a735b08fc7cdc20a034f6))
- Sync tool docs after merge \[skip ci]
([`137e279`](https://github.com/homeassistant-ai/ha-mcp/commit/137e27943b1b704fe1d3e3a5b525b4d82bce33eb))
- **addon**: Publish dev addon version 7.5.0.dev311 \[skip ci]
([`28324ea`](https://github.com/homeassistant-ai/ha-mcp/commit/28324ea4a92fbf61f5ee40c561286c466af2309a))
- Sync tool docs after merge \[skip ci]
([`9a753d4`](https://github.com/homeassistant-ai/ha-mcp/commit/9a753d49abb4ccd84e874451dbcc563260f9e19d))
- **addon**: Publish dev addon version 7.5.0.dev310 \[skip ci]
([`f893b2e`](https://github.com/homeassistant-ai/ha-mcp/commit/f893b2ebf91967d0e2548f9205a15bfe0e7d86c2))
- **addon**: Publish dev addon version 7.5.0.dev309 \[skip ci]
([`8cbdb7b`](https://github.com/homeassistant-ai/ha-mcp/commit/8cbdb7bf318707fed1a0b3e8cb9922e6c170521e))
- **addon**: Publish dev addon version 7.5.0.dev308 \[skip ci]
([`2d18016`](https://github.com/homeassistant-ai/ha-mcp/commit/2d18016de8eb26a18cfb471e7b5f755f1309bd36))
- **addon**: Publish dev addon version 7.5.0.dev307 \[skip ci]
([`3fc3b28`](https://github.com/homeassistant-ai/ha-mcp/commit/3fc3b28881f237df02da8b65467fba9a7d693009))
- Sync tool docs after merge \[skip ci]
([`9e6cff8`](https://github.com/homeassistant-ai/ha-mcp/commit/9e6cff8f641bcd8122e94fc8be9c30aa18456e80))
- **addon**: Publish dev addon version 7.5.0.dev306 \[skip ci]
([`8bdd0fc`](https://github.com/homeassistant-ai/ha-mcp/commit/8bdd0fca9c107f45e4c3719e7616984b68876a9e))
- **addon**: Publish dev addon version 7.5.0.dev305 \[skip ci]
([`83535b9`](https://github.com/homeassistant-ai/ha-mcp/commit/83535b99e190fb56b7ce227334331ebf2affb3e1))
- **addon**: Publish dev addon version 7.5.0.dev304 \[skip ci]
([`1435b3a`](https://github.com/homeassistant-ai/ha-mcp/commit/1435b3a24d73503e189b83f8ea5aaeea20d9ebf3))
- **addon**: Publish dev addon version 7.5.0.dev303 \[skip ci]
([`e2da659`](https://github.com/homeassistant-ai/ha-mcp/commit/e2da6591d6ad2def0b48a9be750cb8a41f40524d))
- Sync tool docs after merge \[skip ci]
([`23789fa`](https://github.com/homeassistant-ai/ha-mcp/commit/23789fa978591b7d3966894082a2683ca6a6ae3b))
- **addon**: Publish dev addon version 7.5.0.dev302 \[skip ci]
([`6c8e574`](https://github.com/homeassistant-ai/ha-mcp/commit/6c8e574e7e3d8d78b3a2e48f6a70531d7a95eed8))
- Sync tool docs after merge \[skip ci]
([`d2329cb`](https://github.com/homeassistant-ai/ha-mcp/commit/d2329cbff39891d209317528fd7b42759c3414a8))
- **addon**: Publish dev addon version 7.5.0.dev301 \[skip ci]
([`bb538f7`](https://github.com/homeassistant-ai/ha-mcp/commit/bb538f70d2fc57072f09cfc6202e9d3dc1a2d257))
- Sync tool docs after merge \[skip ci]
([`f70f0e1`](https://github.com/homeassistant-ai/ha-mcp/commit/f70f0e14222b29a8923e706f113d1fafb4a5c23e))
- **addon**: Publish version 7.5.0 \[skip ci]
([`9c5eb37`](https://github.com/homeassistant-ai/ha-mcp/commit/9c5eb37779236ef19366a2a59a667d3916458e5a))
##### Continuous Integration
- **deps**: Bump actions/upload-artifact in the github-actions group
([#​1437](https://github.com/homeassistant-ai/ha-mcp/pull/1437))
- Share qcow2 cache + GHCR fallback between HAOS lanes
([#​1407](https://github.com/homeassistant-ai/ha-mcp/pull/1407))
- Add ruff format --check on changed Python files
([#​1387](https://github.com/homeassistant-ai/ha-mcp/pull/1387))
- Exempt assigned issues from stale bot
([#​1368](https://github.com/homeassistant-ai/ha-mcp/pull/1368))
- **deps**: Bump the github-actions group with 3 updates
([#​1362](https://github.com/homeassistant-ai/ha-mcp/pull/1362))
##### Refactoring
- Consolidate lovelace/dashboards/list through shared helper
([#​1344](https://github.com/homeassistant-ai/ha-mcp/pull/1344))
##### Testing
- **haos-e2e**: Bake + install webhook-proxy addon and exercise its runtime
([#​1443](https://github.com/homeassistant-ai/ha-mcp/pull/1443))
- **config-subentry**: Mark forecast\_solar e2e as known flaky + relative-import sweep
([#​1430](https://github.com/homeassistant-ai/ha-mcp/pull/1430))
- **haos-e2e**: Trim cache-save race, compress GHCR qcow2, eval boot snapshot
([#​1428](https://github.com/homeassistant-ai/ha-mcp/pull/1428))
- JSDOM behaviour harness + auto-discovery parse coverage for every rendered <script>
([#​1425](https://github.com/homeassistant-ai/ha-mcp/pull/1425))
- **hacs**: Retry TestMcpToolsInstallation on flake
([#​1426](https://github.com/homeassistant-ai/ha-mcp/pull/1426))
- **e2e**: Drop redundant lifecycle roundtrips, keep only Matter Server ([#​1414](https://github.com/homeassistant-ai/ha-mcp/issues/1414))
([#​1419](https://github.com/homeassistant-ai/ha-mcp/pull/1419))
- **e2e**: Assert backend dispatch matches workflow env on every lane
([#​1409](https://github.com/homeassistant-ai/ha-mcp/pull/1409))
- Escape ideographic space and format file ([#​1237](https://github.com/homeassistant-ai/ha-mcp/issues/1237))
([#​1410](https://github.com/homeassistant-ai/ha-mcp/pull/1410))
- **e2e**: Measure \_POLL\_CADENCE p50/p99 to validate or retune (closes [#​1389](https://github.com/homeassistant-ai/ha-mcp/issues/1389))
([#​1398](https://github.com/homeassistant-ai/ha-mcp/pull/1398))
- **e2e**: Wait for addon state=started in haos proxy header test
([#​1402](https://github.com/homeassistant-ai/ha-mcp/pull/1402))
- Pin remaining \_classify\_by\_message branches
([#​1385](https://github.com/homeassistant-ai/ha-mcp/pull/1385))
- **haos-e2e**: Slim addon set + real-addon ha\_manage\_addon coverage (closes [#​1350](https://github.com/homeassistant-ai/ha-mcp/issues/1350))
([#​1379](https://github.com/homeassistant-ai/ha-mcp/pull/1379))
- **haos-e2e**: Close out [#​1349](https://github.com/homeassistant-ai/ha-mcp/issues/1349) — lifecycle, integrations, supervisor\_mock migration, no more skips
([#​1375](https://github.com/homeassistant-ai/ha-mcp/pull/1375))
- **e2e**: Consolidate readiness gates onto /api/core/state (refs [#​366](https://github.com/homeassistant-ai/ha-mcp/issues/366))
([#​1372](https://github.com/homeassistant-ai/ha-mcp/pull/1372))
- **e2e**: Tighten 5 readiness-gate budgets with 2-63x headroom (refs [#​366](https://github.com/homeassistant-ai/ha-mcp/issues/366))
([#​1369](https://github.com/homeassistant-ai/ha-mcp/pull/1369))
- Scaffold HAOS E2E tier image-build pipeline (refs [#​1281](https://github.com/homeassistant-ai/ha-mcp/issues/1281))
([#​1326](https://github.com/homeassistant-ai/ha-mcp/pull/1326))
- **e2e**: Instrument HA\_MCP\_TOOLS\_WAIT readiness gate (refs [#​366](https://github.com/homeassistant-ai/ha-mcp/issues/366))
([#​1346](https://github.com/homeassistant-ai/ha-mcp/pull/1346))
- **e2e**: Centralize wait\_for\_entity\_registration helper (refs [#​366](https://github.com/homeassistant-ai/ha-mcp/issues/366))
([#​1308](https://github.com/homeassistant-ai/ha-mcp/pull/1308))
- **e2e**: Unify dict-error message extraction across e2e tests (refs [#​366](https://github.com/homeassistant-ai/ha-mcp/issues/366))
([#​1311](https://github.com/homeassistant-ai/ha-mcp/pull/1311))
- **e2e**: Surface readiness-gate elapsed times in CI logs (refs [#​366](https://github.com/homeassistant-ai/ha-mcp/issues/366))
([#​1310](https://github.com/homeassistant-ai/ha-mcp/pull/1310))
</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/994
What does this PR do?
Closes #1389.
Pre-committed measurement protocol for the post-#1384
_POLL_CADENCE = (0.1, 1.0, 4.9)shape plus the Boy-Scout retune that the decision rule landed on:_POLL_CADENCEretune:(0.1, 1.0, 4.9)→(0.025, 1.0, 4.975). Same 3-attempt × 6.0s budget; first-poll pulled to a 5× cushion above the measured ~4 ms HA-Core entity-registration latency. Decision rule on two E2E runs against65e6d89: p50 ≥ 100 ms (the prior first-poll sleep was the floor of every sample) → RETUNE NEEDED.Production instrumentation (
src/ha_mcp/client/rest_client.py):_poll_for_automation_entitycaptures elapsed time from function entry to the first successfulget_states()match and emitsentity-registration-elapsed: %.1fms (unique_id=..., entity_id=...)at DEBUG level. Onetime.monotonic()pair per registration.E2E measurement test (
tests/src/e2e/workflows/automation/test_poll_cadence_measurement.py):TestPollCadenceMeasurement1389creates N=10 automations cold-start, captures the DEBUG records viacaplog.at_level, computes p50 / p90 / worst, feeds them to arecord_poll_cadence_measurement()helper in the root e2e conftest. (At N=10 the 99th-percentile index collapses to p90's bucket, so the headline metric is namedworstfor what it actually measures.)Terminal-summary plumbing (
tests/src/e2e/conftest.py): mirrors the readiness-gate-timings pattern —pytest_terminal_summaryrenders the#1389 _POLL_CADENCE measurementsection with[POLL_CADENCE_1389]lines outside the per-worker capture buffer.HAOS proxy-header flake: addressed independently on master via #1402 (merged 2026-05-21 21:43 UTC;
_wait_addon_runningguard intest_manage_addon_modes.py). Not duplicated in this PR — branch rebased onto master so #1402's fix is now live on the PR's CI lane.External-only marker on the measurement test:
caplogonly captures DEBUG records emitted in pytest's own process; on the HAOS-inaddon tier the rest_client lives in the addon's separate process and the records never reachcaplog. Markedexternal_onlyso the test skips inaddon instead of false-negative-asserting.Report-only on percentiles: no threshold assert on the measurement itself. CI latency variance from parallel pytest-xdist workers sharing one HA testcontainer would make a strict threshold-assert flaky. The decision rule is applied to the reported numbers via PR comment —
VERDICTline in the output is machine-greppable.Type of change
(Production-code changes: the
_POLL_CADENCEretune + the one instrumentation line in_poll_for_automation_entity. Everything else is the measurement test, conftest plumbing, and the HAOS readiness guard.)Testing
uv run pytest)uv run ruff check)Local: 44 existing
test_rest_client_automations.py+test_helper_classifier.pyunit tests pass (3 pinned the old cadence — values updated in lockstep). Ruff + mypy clean. The new E2E test cannot be run locally (no Docker daemon in this environment) — measurement set lands in CI's E2E Validation job logs as the[POLL_CADENCE_1389]section.Checklist