Skip to content

refactor: consolidate HACS read tools from 4 to 2 - #871

Merged
kingpanther13 merged 4 commits into
homeassistant-ai:masterfrom
kingpanther13:fix/consolidate-hacs-read-tools
Apr 6, 2026
Merged

refactor: consolidate HACS read tools from 4 to 2#871
kingpanther13 merged 4 commits into
homeassistant-ai:masterfrom
kingpanther13:fix/consolidate-hacs-read-tools

Conversation

@kingpanther13

Copy link
Copy Markdown
Member

What does this PR do?

Consolidates the 4 read-only HACS tools down to 2, based on the discussion in #833:

  1. Merge ha_hacs_list_installed into ha_hacs_search — adds installed_only parameter. Both tools already called the same hacs/repositories/list WebSocket endpoint. ha_hacs_search(installed_only=True) replaces ha_hacs_list_installed().

  2. Remove ha_hacs_info entirely — every field it returned is available via ha_get_system_health (version, stage, lovelace_mode). HACS availability is already checked internally by _assert_hacs_available() in every HACS tool. The categories field isn't actionable — valid values are already hardcoded as Literal types in the tool parameter schemas.

Result: 4 read-only HACS tools → 2 (ha_hacs_search, ha_hacs_repository_info). The 2 write tools (ha_hacs_add_repository, ha_hacs_download) are unchanged.

ha_hacs_search changes

  • query is now optional (default "") — empty query with installed_only=True lists all installed repos
  • New installed_only param (default False) filters to installed repos only
  • When installed_only=True, response includes pending_update and domain fields per repo
  • When listing (no query), results sorted alphabetically by name instead of by score

Type of change

  • 🐛 Bug fix
  • ✨ New feature
  • 📚 Documentation
  • 🔧 Maintenance/refactor
  • 💥 Breaking change

Testing

  • I have tested these changes with a LLM agent
  • All automated tests pass (uv run pytest)
  • Code follows style guidelines (uv run ruff check)

Test updates:

  • Removed TestHacsInfo class
  • Renamed TestHacsListInstalledTestHacsSearchInstalled, updated to use ha_hacs_search(installed_only=True)
  • Updated all HACS availability checks from ha_hacs_info to ha_hacs_search

Checklist

  • I have updated documentation if needed

Closes #833

🤖 Generated with Claude Code

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, 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 refactors the HACS toolset to improve maintainability and reduce redundancy. By consolidating the read-only tools, the interface is simplified while retaining all existing functionality. The changes also leverage existing system health checks to provide necessary HACS status information, streamlining the codebase.

Highlights

  • Tool Consolidation: Consolidated four read-only HACS tools into two by merging ha_hacs_list_installed into ha_hacs_search and removing ha_hacs_info.
  • Enhanced Search Functionality: Updated ha_hacs_search to support an installed_only parameter, allowing it to serve as a replacement for listing installed repositories.
  • System Health Integration: Replaced reliance on ha_hacs_info with ha_get_system_health for retrieving HACS status and version information.
  • Test Suite Updates: Refactored the test suite to align with the new tool structure, including renaming and updating test classes to use the consolidated search tool.
Using Gemini Code Assist

The 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 /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request consolidates HACS tools by removing ha_hacs_info and ha_hacs_list_installed, integrating their functionality into an enhanced ha_hacs_search tool. The updated ha_hacs_search now supports an installed_only parameter, allowing users to list installed repositories or search the full store within a single interface. Corresponding updates were made to the README, documentation, and E2E tests to reflect these changes and ensure continued test coverage using the consolidated tool. I have no feedback to provide.

@kingpanther13
kingpanther13 marked this pull request as ready for review April 5, 2026 12:46
@kingpanther13
kingpanther13 requested a review from a team April 5, 2026 12:46
@kingpanther13
kingpanther13 enabled auto-merge (squash) April 5, 2026 12:46
Comment thread src/ha_mcp/tools/tools_hacs.py Outdated
Comment thread src/ha_mcp/tools/tools_hacs.py
Comment thread tests/src/e2e/workflows/hacs/test_hacs.py
Comment thread README.md
Comment thread src/ha_mcp/tools/tools_hacs.py Outdated
Comment thread src/ha_mcp/tools/tools_hacs.py
Comment thread tests/src/e2e/workflows/hacs/test_hacs.py
kingpanther13 and others added 2 commits April 6, 2026 08:09
Merge ha_hacs_list_installed into ha_hacs_search via new installed_only
parameter. Remove ha_hacs_info entirely — all its fields are already
available via ha_get_system_health.

Changes:
- ha_hacs_search: add installed_only param (default False), make query
  optional (default ""). When installed_only=True and no query, lists
  all installed repos sorted by name. When query is provided, filters
  by keyword as before. Includes pending_update and domain fields for
  installed repos.
- ha_hacs_info: removed. Version, stage, categories all available via
  ha_get_system_health. HACS availability already checked internally
  by _assert_hacs_available() in every HACS tool.
- ha_hacs_list_installed: removed. Replaced by
  ha_hacs_search(installed_only=True).
- Updated ha_hacs_repository_info and ha_hacs_download docstrings to
  reference ha_hacs_search instead of removed tools.
- Updated README tool table.
- Updated E2E tests: removed TestHacsInfo, converted TestHacsListInstalled
  to use ha_hacs_search(installed_only=True).

Closes homeassistant-ai#833

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1. Remove dead `or False` after coerce_bool_param (default=False never
   returns None)
2. Add test for installed_only=True with non-empty query
3. Assert installed_only field in response
4. Convert success:False returns to raise_tool_error in
   ha_hacs_repository_info, ha_hacs_add_repository, ha_hacs_download
   (per project guidelines: tool-level failures must raise ToolError)
5. Improve _assert_hacs_available to distinguish "HACS not installed"
   from "HACS installed but broken" by inspecting error response

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@kingpanther13
kingpanther13 force-pushed the fix/consolidate-hacs-read-tools branch from cd54cf5 to 6814293 Compare April 6, 2026 12:10
_is_hacs_available was merged into _assert_hacs_available. Tests in
test_tools_mcp_component.py that patched the old function now patch
_assert_hacs_available instead.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
sergeykad pushed a commit that referenced this pull request Apr 6, 2026
Fixes 6 of 9 violations caught by the new `no-return-success-false`
ast-grep rule (remaining 3 are in tools_hacs.py, addressed by #871).

Returning `{"success": False, ...}` from tool functions doesn't set
`isError=true` on the MCP response, so LLM agents may not recognize
these as errors.

Changes:
- device_control.py: failed/timeout operation status now raises ToolError
- tools_entities.py: ha_set_entity exposure failure now raises ToolError
- tools_entities.py: _fetch_entity raises ValueError instead of returning
  error dict (callers already handle exceptions via return_exceptions)
- backup.py: _get_backup_password raises ToolError directly instead of
  returning (None, error_dict) tuples; callers updated accordingly
- test_tools_entities.py: updated test to expect ToolError
Explicitly documents that calling ha_hacs_search() with no query and
installed_only=False returns all HACS store repos sorted alphabetically.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@kingpanther13
kingpanther13 merged commit 62fc637 into homeassistant-ai:master Apr 6, 2026
15 checks passed
@github-actions

github-actions Bot commented Apr 6, 2026

Copy link
Copy Markdown
Contributor

🧪 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):
📖 Dev Channel Documentation

Quick start

# Run dev version
uvx ha-mcp-dev

# Check version
uvx ha-mcp-dev --version

Docker:

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:dev

Found an issue? Please open a new bug report and mention this PR for context.

sergeykad pushed a commit that referenced this pull request Apr 6, 2026
- Revert tools_hacs.py changes (will be handled by #871)
- Fix _update_single_entity exposure failure to raise ToolError
  instead of returning {"success": False} via variable assignment
- Re-add exposure_succeeded assertion in test
- Update 3 exposure failure tests to expect ToolError
sergeykad pushed a commit that referenced this pull request Apr 6, 2026
Fixes 6 of 9 violations caught by the new `no-return-success-false`
ast-grep rule (remaining 3 are in tools_hacs.py, addressed by #871).

Returning `{"success": False, ...}` from tool functions doesn't set
`isError=true` on the MCP response, so LLM agents may not recognize
these as errors.

Changes:
- device_control.py: failed/timeout operation status now raises ToolError
- tools_entities.py: ha_set_entity exposure failure now raises ToolError
- tools_entities.py: _fetch_entity raises ValueError instead of returning
  error dict (callers already handle exceptions via return_exceptions)
- backup.py: _get_backup_password raises ToolError directly instead of
  returning (None, error_dict) tuples; callers updated accordingly
- test_tools_entities.py: updated test to expect ToolError
sergeykad pushed a commit that referenced this pull request Apr 6, 2026
- Revert tools_hacs.py changes (will be handled by #871)
- Fix _update_single_entity exposure failure to raise ToolError
  instead of returning {"success": False} via variable assignment
- Re-add exposure_succeeded assertion in test
- Update 3 exposure failure tests to expect ToolError
sergeykad added a commit that referenced this pull request Apr 6, 2026
* fix: replace hand-built error dicts with raise_tool_error

Fixes 6 of 9 violations caught by the new `no-return-success-false`
ast-grep rule (remaining 3 are in tools_hacs.py, addressed by #871).

Returning `{"success": False, ...}` from tool functions doesn't set
`isError=true` on the MCP response, so LLM agents may not recognize
these as errors.

Changes:
- device_control.py: failed/timeout operation status now raises ToolError
- tools_entities.py: ha_set_entity exposure failure now raises ToolError
- tools_entities.py: _fetch_entity raises ValueError instead of returning
  error dict (callers already handle exceptions via return_exceptions)
- backup.py: _get_backup_password raises ToolError directly instead of
  returning (None, error_dict) tuples; callers updated accordingly
- test_tools_entities.py: updated test to expect ToolError

* fix(internal): add ast-grep rule to catch hand-built error dicts

The existing `no-return-error-response` rule catches `return create_error_response(...)`
but misses hand-built `return {"success": False, ...}` dicts that bypass `raise_tool_error`.
These return `isError=false` in MCP responses, so LLM agents may not recognize them as errors.

The new rule catches any dictionary with `"success": False` inside a return statement,
regardless of key ordering. It correctly excludes batch item appends (`.append(...)`) and
dict assignments which are legitimate uses.

Currently flags 9 pre-existing violations across 4 files:
- tools_hacs.py (3), device_control.py (2), tools_entities.py (2), backup.py (2)

* fix: preserve exposure_succeeded in ha_set_entity error context

The previous commit dropped partial-success data when converting
to raise_tool_error. Restore it via the context dict so LLM agents
can see which exposure changes succeeded before the failure.

* fix: address review feedback on PR #895

- Revert tools_hacs.py changes (will be handled by #871)
- Fix _update_single_entity exposure failure to raise ToolError
  instead of returning {"success": False} via variable assignment
- Re-add exposure_succeeded assertion in test
- Update 3 exposure failure tests to expect ToolError
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] Consolidate 4 read-only HACS tools into a single tool

2 participants