ha-mcp-dev 7.6.0.dev634__tar.gz → 7.6.0.dev636__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. {ha_mcp_dev-7.6.0.dev634/src/ha_mcp_dev.egg-info → ha_mcp_dev-7.6.0.dev636}/PKG-INFO +4 -4
  2. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/README.md +3 -3
  3. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/pyproject.toml +1 -1
  4. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/settings_ui.py +65 -165
  5. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636/src/ha_mcp_dev.egg-info}/PKG-INFO +4 -4
  6. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/LICENSE +0 -0
  7. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/MANIFEST.in +0 -0
  8. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/setup.cfg +0 -0
  9. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/__init__.py +0 -0
  10. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/__main__.py +0 -0
  11. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/_pypi_marker +0 -0
  12. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/_version.py +0 -0
  13. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/auth/__init__.py +0 -0
  14. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/auth/consent_form.py +0 -0
  15. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/auth/provider.py +0 -0
  16. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/backup_manager.py +0 -0
  17. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/client/__init__.py +0 -0
  18. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/client/rest_client.py +0 -0
  19. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/client/supervisor_client.py +0 -0
  20. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/client/websocket_client.py +0 -0
  21. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/client/websocket_listener.py +0 -0
  22. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/config.py +0 -0
  23. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/errors.py +0 -0
  24. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/policy/__init__.py +0 -0
  25. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/policy/approval_queue.py +0 -0
  26. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/policy/evaluator.py +0 -0
  27. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/policy/handlers.py +0 -0
  28. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/policy/middleware.py +0 -0
  29. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/policy/model.py +0 -0
  30. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/policy/persistence.py +0 -0
  31. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/policy/value_sources.py +0 -0
  32. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/py.typed +0 -0
  33. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/resources/skills-vendor/.claude/settings.json +0 -0
  34. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/resources/skills-vendor/.claude-plugin/marketplace.json +0 -0
  35. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/resources/skills-vendor/.claude-plugin/plugin.json +0 -0
  36. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/resources/skills-vendor/.github/ISSUE_TEMPLATE/skill-rca.md +0 -0
  37. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/resources/skills-vendor/.github/pull_request_template.md +0 -0
  38. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/resources/skills-vendor/AGENTS.md +0 -0
  39. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/resources/skills-vendor/CLAUDE.md +0 -0
  40. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/resources/skills-vendor/CONTRIBUTING.md +0 -0
  41. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/resources/skills-vendor/LICENSE +0 -0
  42. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/resources/skills-vendor/README.md +0 -0
  43. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/SKILL.md +0 -0
  44. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/evals/evals.json +0 -0
  45. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/automation-patterns.md +0 -0
  46. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-cards.md +0 -0
  47. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-guide.md +0 -0
  48. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/device-control.md +0 -0
  49. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/domain-docs.md +0 -0
  50. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/examples.yaml +0 -0
  51. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/helper-selection.md +0 -0
  52. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/safe-refactoring.md +0 -0
  53. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/template-guidelines.md +0 -0
  54. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/yaml-only-integrations.md +0 -0
  55. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/server.py +0 -0
  56. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/smoke_test.py +0 -0
  57. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/stdio_settings_sidecar.py +0 -0
  58. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/tools/__init__.py +0 -0
  59. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/tools/auto_backup.py +0 -0
  60. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/tools/backup.py +0 -0
  61. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/tools/best_practice_checker.py +0 -0
  62. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/tools/device_control.py +0 -0
  63. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/tools/enhanced.py +0 -0
  64. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/tools/helpers.py +0 -0
  65. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/tools/reference_validator.py +0 -0
  66. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/tools/registry.py +0 -0
  67. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/tools/smart_search.py +0 -0
  68. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/tools/tools_addons.py +0 -0
  69. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/tools/tools_areas.py +0 -0
  70. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/tools/tools_blueprints.py +0 -0
  71. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/tools/tools_bug_report.py +0 -0
  72. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/tools/tools_calendar.py +0 -0
  73. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/tools/tools_camera.py +0 -0
  74. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/tools/tools_categories.py +0 -0
  75. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/tools/tools_code.py +0 -0
  76. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/tools/tools_config_automations.py +0 -0
  77. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/tools/tools_config_dashboards.py +0 -0
  78. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/tools/tools_config_entry_flow.py +0 -0
  79. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/tools/tools_config_helpers.py +0 -0
  80. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/tools/tools_config_scenes.py +0 -0
  81. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/tools/tools_config_scripts.py +0 -0
  82. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/tools/tools_energy.py +0 -0
  83. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/tools/tools_entities.py +0 -0
  84. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/tools/tools_filesystem.py +0 -0
  85. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/tools/tools_groups.py +0 -0
  86. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/tools/tools_hacs.py +0 -0
  87. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/tools/tools_history.py +0 -0
  88. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/tools/tools_integrations.py +0 -0
  89. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/tools/tools_labels.py +0 -0
  90. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/tools/tools_mcp_component.py +0 -0
  91. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/tools/tools_registry.py +0 -0
  92. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/tools/tools_resources.py +0 -0
  93. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/tools/tools_search.py +0 -0
  94. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/tools/tools_service.py +0 -0
  95. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/tools/tools_services.py +0 -0
  96. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/tools/tools_system.py +0 -0
  97. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/tools/tools_todo.py +0 -0
  98. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/tools/tools_traces.py +0 -0
  99. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/tools/tools_updates.py +0 -0
  100. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/tools/tools_utility.py +0 -0
  101. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/tools/tools_voice_assistant.py +0 -0
  102. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/tools/tools_yaml_config.py +0 -0
  103. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/tools/tools_zones.py +0 -0
  104. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/tools/util_helpers.py +0 -0
  105. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/tools/validation_middleware.py +0 -0
  106. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/transforms/__init__.py +0 -0
  107. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/transforms/categorized_search.py +0 -0
  108. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/transforms/lite_docstrings.py +0 -0
  109. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/utils/__init__.py +0 -0
  110. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/utils/config_hash.py +0 -0
  111. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/utils/data_paths.py +0 -0
  112. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/utils/domain_handlers.py +0 -0
  113. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/utils/fuzzy_search.py +0 -0
  114. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/utils/kill_signal_diagnostics.py +0 -0
  115. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/utils/operation_manager.py +0 -0
  116. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/utils/python_sandbox.py +0 -0
  117. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/utils/skill_loader.py +0 -0
  118. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp/utils/usage_logger.py +0 -0
  119. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp_dev.egg-info/SOURCES.txt +0 -0
  120. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp_dev.egg-info/dependency_links.txt +0 -0
  121. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp_dev.egg-info/entry_points.txt +0 -0
  122. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp_dev.egg-info/requires.txt +0 -0
  123. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/src/ha_mcp_dev.egg-info/top_level.txt +0 -0
  124. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/tests/__init__.py +0 -0
  125. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/tests/test_constants.py +0 -0
  126. {ha_mcp_dev-7.6.0.dev634 → ha_mcp_dev-7.6.0.dev636}/tests/test_env_manager.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ha-mcp-dev
3
- Version: 7.6.0.dev634
3
+ Version: 7.6.0.dev636
4
4
  Summary: Home Assistant MCP Server - Complete control of Home Assistant through MCP
5
5
  Author-email: Julien <github@qc-h.net>
6
6
  License: MIT
@@ -38,7 +38,7 @@ Dynamic: license-file
38
38
  <!-- mcp-name: io.github.homeassistant-ai/ha-mcp -->
39
39
 
40
40
  <p align="center">
41
- <img src="https://img.shields.io/badge/tools-86-blue" alt="95+ Tools">
41
+ <img src="https://img.shields.io/badge/tools-84-blue" alt="95+ Tools">
42
42
  <a href="https://github.com/homeassistant-ai/ha-mcp/releases"><img src="https://img.shields.io/github/v/release/homeassistant-ai/ha-mcp" alt="Release"></a>
43
43
  <a href="https://github.com/homeassistant-ai/ha-mcp/actions/workflows/e2e-tests.yml"><img src="https://img.shields.io/github/actions/workflow/status/homeassistant-ai/ha-mcp/e2e-tests.yml?branch=master&label=E2E%20Tests" alt="E2E Tests"></a>
44
44
  <a href="LICENSE.md"><img src="https://img.shields.io/github/license/homeassistant-ai/ha-mcp.svg" alt="License"></a>
@@ -181,7 +181,7 @@ Spend less time configuring, more time enjoying your smart home.
181
181
  <details>
182
182
  <!-- TOOLS_TABLE_START -->
183
183
 
184
- <summary><b>Complete Tool List (86 tools)</b></summary>
184
+ <summary><b>Complete Tool List (84 tools)</b></summary>
185
185
 
186
186
  | Category | Tools |
187
187
  |----------|-------|
@@ -198,7 +198,7 @@ Spend less time configuring, more time enjoying your smart home.
198
198
  | **Entity Registry** | `ha_get_entity_exposure`, `ha_get_entity`, `ha_remove_entity`, `ha_set_entity` |
199
199
  | **Files** | `ha_delete_file` *(beta)*, `ha_list_files` *(beta)*, `ha_read_file` *(beta)*, `ha_write_file` *(beta)* |
200
200
  | **Groups** | `ha_config_list_groups`, `ha_config_remove_group`, `ha_config_set_group` |
201
- | **HACS** | `ha_hacs_add_repository`, `ha_hacs_download`, `ha_hacs_repository_info`, `ha_hacs_search` |
201
+ | **HACS** | `ha_get_hacs_info`, `ha_manage_hacs` |
202
202
  | **Helper Entities** | `ha_config_list_helpers`, `ha_config_set_helper`, `ha_remove_helpers_integrations` |
203
203
  | **History & Statistics** | `ha_get_automation_traces`, `ha_get_history`, `ha_get_logs` |
204
204
  | **Integrations** | `ha_get_integration`, `ha_get_system_health`, `ha_set_integration_enabled` |
@@ -8,7 +8,7 @@
8
8
  <!-- mcp-name: io.github.homeassistant-ai/ha-mcp -->
9
9
 
10
10
  <p align="center">
11
- <img src="https://img.shields.io/badge/tools-86-blue" alt="95+ Tools">
11
+ <img src="https://img.shields.io/badge/tools-84-blue" alt="95+ Tools">
12
12
  <a href="https://github.com/homeassistant-ai/ha-mcp/releases"><img src="https://img.shields.io/github/v/release/homeassistant-ai/ha-mcp" alt="Release"></a>
13
13
  <a href="https://github.com/homeassistant-ai/ha-mcp/actions/workflows/e2e-tests.yml"><img src="https://img.shields.io/github/actions/workflow/status/homeassistant-ai/ha-mcp/e2e-tests.yml?branch=master&label=E2E%20Tests" alt="E2E Tests"></a>
14
14
  <a href="LICENSE.md"><img src="https://img.shields.io/github/license/homeassistant-ai/ha-mcp.svg" alt="License"></a>
@@ -151,7 +151,7 @@ Spend less time configuring, more time enjoying your smart home.
151
151
  <details>
152
152
  <!-- TOOLS_TABLE_START -->
153
153
 
154
- <summary><b>Complete Tool List (86 tools)</b></summary>
154
+ <summary><b>Complete Tool List (84 tools)</b></summary>
155
155
 
156
156
  | Category | Tools |
157
157
  |----------|-------|
@@ -168,7 +168,7 @@ Spend less time configuring, more time enjoying your smart home.
168
168
  | **Entity Registry** | `ha_get_entity_exposure`, `ha_get_entity`, `ha_remove_entity`, `ha_set_entity` |
169
169
  | **Files** | `ha_delete_file` *(beta)*, `ha_list_files` *(beta)*, `ha_read_file` *(beta)*, `ha_write_file` *(beta)* |
170
170
  | **Groups** | `ha_config_list_groups`, `ha_config_remove_group`, `ha_config_set_group` |
171
- | **HACS** | `ha_hacs_add_repository`, `ha_hacs_download`, `ha_hacs_repository_info`, `ha_hacs_search` |
171
+ | **HACS** | `ha_get_hacs_info`, `ha_manage_hacs` |
172
172
  | **Helper Entities** | `ha_config_list_helpers`, `ha_config_set_helper`, `ha_remove_helpers_integrations` |
173
173
  | **History & Statistics** | `ha_get_automation_traces`, `ha_get_history`, `ha_get_logs` |
174
174
  | **Integrations** | `ha_get_integration`, `ha_get_system_health`, `ha_set_integration_enabled` |
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "ha-mcp-dev"
7
- version = "7.6.0.dev634"
7
+ version = "7.6.0.dev636"
8
8
  description = "Home Assistant MCP Server - Complete control of Home Assistant through MCP"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.13,<3.14"
@@ -1618,7 +1618,7 @@ function render() {
1618
1618
  `<span class="group-count">${groupEnabled}/${tools.length} enabled</span>` +
1619
1619
  `</div>` +
1620
1620
  `<label class="switch group-master" title="Enable/disable all tools in this group">` +
1621
- `<input type="checkbox" ${anyEnabled ? 'checked' : ''} ${toggleable.length === 0 ? 'disabled' : ''}>` +
1621
+ `<input type="checkbox" name="tool-group:${escapeHtml(tag)}" ${anyEnabled ? 'checked' : ''} ${toggleable.length === 0 ? 'disabled' : ''}>` +
1622
1622
  `<span class="slider"></span>` +
1623
1623
  `</label>`;
1624
1624
 
@@ -1722,20 +1722,20 @@ function render() {
1722
1722
  `</div>` +
1723
1723
  `<div class="tool-toggles">` +
1724
1724
  `<div class="toggle-group">` +
1725
- `<label class="switch"><input type="checkbox" data-tool="${escapeHtml(t.name)}" data-field="enabled" ` +
1725
+ `<label class="switch"><input type="checkbox" name="tool:${escapeHtml(t.name)}:enabled" data-tool="${escapeHtml(t.name)}" data-field="enabled" ` +
1726
1726
  `${isEnabled ? 'checked' : ''} ${lockEnabled ? 'disabled' : ''}>` +
1727
1727
  `<span class="slider"></span></label>` +
1728
1728
  `<span>enabled</span>` +
1729
1729
  `</div>` +
1730
1730
  `<div class="toggle-group ${!isEnabled ? 'disabled-toggle' : ''}">` +
1731
- `<label class="switch"><input type="checkbox" data-tool="${escapeHtml(t.name)}" data-field="pinned" ` +
1731
+ `<label class="switch"><input type="checkbox" name="tool:${escapeHtml(t.name)}:pinned" data-tool="${escapeHtml(t.name)}" data-field="pinned" ` +
1732
1732
  `${isPinned ? 'checked' : ''} ${lockPinned ? 'disabled' : ''}>` +
1733
1733
  `<span class="slider"></span></label>` +
1734
1734
  `<span>pinned</span>` +
1735
1735
  `</div>` +
1736
1736
  `<div class="toggle-group ${(policyState.enabled && isEnabled) ? '' : 'disabled-toggle'}" ` +
1737
1737
  `title="${policyState.enabled ? '' : 'Enable Tool Security Policies in addon config first.'}">` +
1738
- `<label class="switch"><input type="checkbox" data-tool="${escapeHtml(t.name)}" data-field="gated" ` +
1738
+ `<label class="switch"><input type="checkbox" name="tool:${escapeHtml(t.name)}:gated" data-tool="${escapeHtml(t.name)}" data-field="gated" ` +
1739
1739
  `${policyState.gatedTools.has(t.name) ? 'checked' : ''} ` +
1740
1740
  `${(policyState.enabled && isEnabled) ? '' : 'disabled'}>` +
1741
1741
  `<span class="slider"></span></label>` +
@@ -1926,16 +1926,16 @@ function renderBackupConfig() {
1926
1926
  row.className = 'backup-field';
1927
1927
  let controlHtml;
1928
1928
  if (typeof f.value === 'boolean') {
1929
- controlHtml = `<input type="checkbox" data-field="${escapeHtml(f.field)}" ${f.value ? 'checked' : ''} ${f.editable ? '' : 'disabled'}>`;
1929
+ controlHtml = `<input type="checkbox" name="backup:${escapeHtml(f.field)}" data-field="${escapeHtml(f.field)}" ${f.value ? 'checked' : ''} ${f.editable ? '' : 'disabled'}>`;
1930
1930
  } else if (typeof f.value === 'string') {
1931
1931
  // Path / freeform string fields (auto_backup_dir).
1932
- controlHtml = `<input type="text" data-field="${escapeHtml(f.field)}" value="${escapeHtml(String(f.value ?? ''))}" ${f.editable ? '' : 'disabled'}>`;
1932
+ controlHtml = `<input type="text" name="backup:${escapeHtml(f.field)}" data-field="${escapeHtml(f.field)}" value="${escapeHtml(String(f.value ?? ''))}" ${f.editable ? '' : 'disabled'}>`;
1933
1933
  } else {
1934
1934
  let min = 1;
1935
1935
  let max = 10000;
1936
1936
  if (f.field === 'auto_backup_throttle_minutes') { min = 0; max = 1440; }
1937
1937
  else if (f.field === 'auto_backup_calendar_lookahead_days') { min = 1; max = 365; }
1938
- controlHtml = `<input type="number" data-field="${escapeHtml(f.field)}" value="${Number(f.value)}" min="${min}" max="${max}" ${f.editable ? '' : 'disabled'}>`;
1938
+ controlHtml = `<input type="number" name="backup:${escapeHtml(f.field)}" data-field="${escapeHtml(f.field)}" value="${Number(f.value)}" min="${min}" max="${max}" ${f.editable ? '' : 'disabled'}>`;
1939
1939
  }
1940
1940
  let originMsg;
1941
1941
  if (f.origin === 'env') {
@@ -2396,6 +2396,7 @@ function renderFeatureFlags(flags) {
2396
2396
  label.className = 'switch';
2397
2397
  const input = document.createElement('input');
2398
2398
  input.type = 'checkbox';
2399
+ input.name = 'feature:' + fieldName;
2399
2400
  input.checked = !!f.value;
2400
2401
  input.disabled = !f.editable || lockedByMaster;
2401
2402
  input.addEventListener('change', () => {
@@ -2444,6 +2445,7 @@ function renderFeatureFlags(flags) {
2444
2445
  } else if (f.type === 'int') {
2445
2446
  const input = document.createElement('input');
2446
2447
  input.type = 'number';
2448
+ input.name = 'feature:' + fieldName;
2447
2449
  input.value = f.value;
2448
2450
  if (typeof f.min === 'number') input.min = f.min;
2449
2451
  if (typeof f.max === 'number') input.max = f.max;
@@ -2514,6 +2516,7 @@ function renderYamlPackagesSubRows(flags, parentEl, masterOn, parentOn) {
2514
2516
  label.className = 'switch';
2515
2517
  const input = document.createElement('input');
2516
2518
  input.type = 'checkbox';
2519
+ input.name = 'feature:' + fieldName;
2517
2520
  input.checked = !!f.value;
2518
2521
  input.disabled = !f.editable || lockedByGate;
2519
2522
  input.addEventListener('change', () => {
@@ -2605,6 +2608,7 @@ function renderCodeModeSubRows(parentEl, masterOn, codeModeOn) {
2605
2608
  }
2606
2609
  inputEl.disabled = disabled;
2607
2610
  inputEl.dataset.advField = f.field;
2611
+ inputEl.name = 'adv:' + f.field;
2608
2612
  inputEl.addEventListener('change', () => {
2609
2613
  let v;
2610
2614
  if (f.type === 'int') v = parseInt(inputEl.value, 10);
@@ -2817,15 +2821,15 @@ function renderPolicyCard(toolName, rule) {
2817
2821
  '<div class="policy-predicate-form" style="display:none;">' +
2818
2822
  '<div class="policy-form-row">' +
2819
2823
  '<label class="policy-form-label">Argument:</label>' +
2820
- '<select class="policy-predicate-path-select">' +
2824
+ '<select name="policy:predicate-path" class="policy-predicate-path-select">' +
2821
2825
  '<option value="">(loading...)</option>' +
2822
2826
  '</select>' +
2823
- '<input type="text" class="policy-predicate-path-custom" ' +
2827
+ '<input type="text" name="policy:predicate-path-custom" class="policy-predicate-path-custom" ' +
2824
2828
  'placeholder="e.g. args.color_temp" style="display:none">' +
2825
2829
  '</div>' +
2826
2830
  '<div class="policy-form-row">' +
2827
2831
  '<label class="policy-form-label">Match when:</label>' +
2828
- '<select class="policy-predicate-op">' +
2832
+ '<select name="policy:predicate-op" class="policy-predicate-op">' +
2829
2833
  '<option value="exists">is present (any value)</option>' +
2830
2834
  '<option value="eq">equals</option>' +
2831
2835
  '<option value="neq">does NOT equal</option>' +
@@ -2850,7 +2854,7 @@ function renderPolicyCard(toolName, rule) {
2850
2854
  '</div>' +
2851
2855
  '<div class="policy-rule-lifetime">' +
2852
2856
  '<label>Remember approval for:' +
2853
- '<input type="number" min="0" max="1440" class="policy-remember-minutes" ' +
2857
+ '<input type="number" name="policy:remember-minutes" min="0" max="1440" class="policy-remember-minutes" ' +
2854
2858
  'value="' + (rule.remember_minutes || 0) + '">' +
2855
2859
  'minutes (0 = single-shot)' +
2856
2860
  '</label>' +
@@ -3084,7 +3088,7 @@ function renderPolicyCard(toolName, rule) {
3084
3088
  const existingArr = Array.isArray(existingValue)
3085
3089
  ? existingValue
3086
3090
  : (existingValue !== undefined && existingValue !== null ? [existingValue] : []);
3087
- let html = '<select class="policy-predicate-value-control"' +
3091
+ let html = '<select name="policy:predicate-value" class="policy-predicate-value-control"' +
3088
3092
  (isMulti ? ' multiple size="6" style="min-width:220px"' : '') +
3089
3093
  '>';
3090
3094
  if (!isMulti) {
@@ -3114,7 +3118,7 @@ function renderPolicyCard(toolName, rule) {
3114
3118
  const initial = (existingValue === undefined || existingValue === null)
3115
3119
  ? ''
3116
3120
  : JSON.stringify(existingValue);
3117
- valueSlotEl.innerHTML = '<input type="text" ' +
3121
+ valueSlotEl.innerHTML = '<input type="text" name="policy:predicate-value" ' +
3118
3122
  'class="policy-predicate-value-control policy-predicate-value" ' +
3119
3123
  'placeholder="' + escapeHtml(placeholder) + '" ' +
3120
3124
  'value="' + escapeHtml(initial) + '">';
@@ -3643,22 +3647,22 @@ function renderAdvancedSection(containerId, fields) {
3643
3647
  const meta = ADVANCED_FIELD_META[f.field] || { label: f.field, help: '' };
3644
3648
  let controlHtml;
3645
3649
  if (f.choices) {
3646
- controlHtml = `<select data-adv-field="${escapeHtml(f.field)}" ${f.editable ? '' : 'disabled'}>` +
3650
+ controlHtml = `<select name="adv:${escapeHtml(f.field)}" data-adv-field="${escapeHtml(f.field)}" ${f.editable ? '' : 'disabled'}>` +
3647
3651
  f.choices.map(c =>
3648
3652
  `<option value="${escapeHtml(c)}" ${String(f.value) === c ? 'selected' : ''}>${escapeHtml(c)}</option>`
3649
3653
  ).join('') +
3650
3654
  '</select>';
3651
3655
  } else if (f.type === 'bool') {
3652
- controlHtml = `<input type="checkbox" data-adv-field="${escapeHtml(f.field)}" ${f.value ? 'checked' : ''} ${f.editable ? '' : 'disabled'}>`;
3656
+ controlHtml = `<input type="checkbox" name="adv:${escapeHtml(f.field)}" data-adv-field="${escapeHtml(f.field)}" ${f.value ? 'checked' : ''} ${f.editable ? '' : 'disabled'}>`;
3653
3657
  } else if (f.type === 'int' || f.type === 'float') {
3654
- controlHtml = `<input type="number" data-adv-field="${escapeHtml(f.field)}" value="${Number(f.value)}" ` +
3658
+ controlHtml = `<input type="number" name="adv:${escapeHtml(f.field)}" data-adv-field="${escapeHtml(f.field)}" value="${Number(f.value)}" ` +
3655
3659
  (f.min !== undefined ? `min="${f.min}" ` : '') +
3656
3660
  (f.max !== undefined ? `max="${f.max}" ` : '') +
3657
3661
  (f.type === 'float' ? 'step="0.1" ' : '') +
3658
3662
  (f.editable ? '' : 'disabled') + '>';
3659
3663
  } else {
3660
3664
  // str
3661
- controlHtml = `<input type="text" data-adv-field="${escapeHtml(f.field)}" value="${escapeHtml(String(f.value ?? ''))}" ${f.editable ? '' : 'disabled'}>`;
3665
+ controlHtml = `<input type="text" name="adv:${escapeHtml(f.field)}" data-adv-field="${escapeHtml(f.field)}" value="${escapeHtml(String(f.value ?? ''))}" ${f.editable ? '' : 'disabled'}>`;
3662
3666
  }
3663
3667
  let originMsg = '';
3664
3668
  if (f.origin === 'env') {
@@ -5990,6 +5994,47 @@ def register_settings_routes(
5990
5994
  )
5991
5995
  return
5992
5996
 
5997
+ # Every route this function mounts except the add-on-only root mount is defined
5998
+ # once in this table and mounted under each active prefix below: at root
5999
+ # in add-on mode (so HA ingress can proxy localhost:9583/), and under the
6000
+ # secret path when one is set (Docker / standalone direct access). A
6001
+ # deployment hits either, both, or — guarded above — neither. Deriving
6002
+ # the mounts from one table keeps them from drifting; the frontend uses
6003
+ # relative fetches (./api/settings/...) so the handlers work at any prefix.
6004
+ routes: list[tuple[str, list[str], str]] = [
6005
+ ("/settings", ["GET"], "settings_page"),
6006
+ ("/api/settings/tools", ["GET"], "get_tools"),
6007
+ ("/api/settings/tools", ["POST"], "save_tools"),
6008
+ ("/api/settings/restart", ["POST"], "restart_addon"),
6009
+ ("/api/settings/info", ["GET"], "settings_info"),
6010
+ ("/api/settings/features", ["GET"], "get_feature_flags"),
6011
+ ("/api/settings/features", ["POST"], "save_feature_flags"),
6012
+ # Advanced settings endpoints
6013
+ ("/api/settings/advanced", ["GET"], "get_advanced_settings"),
6014
+ ("/api/settings/advanced", ["POST"], "save_advanced_settings"),
6015
+ # Auto-backup endpoints (#1288)
6016
+ ("/api/settings/backups", ["GET"], "list_backups"),
6017
+ ("/api/settings/backups", ["DELETE"], "delete_backups_bulk"),
6018
+ ("/api/settings/backups/{name}", ["GET"], "view_backup"),
6019
+ ("/api/settings/backups/{name}/diff", ["GET"], "diff_backup"),
6020
+ ("/api/settings/backups/{name}/restore", ["POST"], "restore_backup"),
6021
+ ("/api/settings/backups/{name}", ["DELETE"], "delete_backup"),
6022
+ ("/api/settings/backup-config", ["GET"], "get_backup_config"),
6023
+ ("/api/settings/backup-config", ["POST"], "save_backup_config"),
6024
+ # Tool security policies endpoints
6025
+ ("/api/policy/config", ["GET"], "policy_get_config"),
6026
+ ("/api/policy/config", ["PUT"], "policy_put_config"),
6027
+ ("/api/policy/pending", ["GET"], "policy_get_pending"),
6028
+ ("/api/policy/approve", ["POST"], "policy_post_approve"),
6029
+ ("/api/policy/deny", ["POST"], "policy_post_deny"),
6030
+ ("/api/policy/tool-schema", ["GET"], "policy_get_tool_schema"),
6031
+ ("/api/policy/value-source", ["GET"], "policy_get_value_source"),
6032
+ ]
6033
+
6034
+ def _mount(prefix: str) -> None:
6035
+ for path, methods, handler_key in routes:
6036
+ mcp.custom_route(f"{prefix}{path}", methods=methods)(handlers[handler_key])
6037
+
5993
6038
  if is_addon:
5994
6039
  # Root mount lets HA ingress proxy localhost:9583/ → settings UI.
5995
6040
  # Direct port 9583 LAN access also reaches these routes; in this
@@ -5997,155 +6042,10 @@ def register_settings_routes(
5997
6042
  # port 9583 is exposed via host_network and the secret path is
5998
6043
  # the auth for direct access. Document this in DOCS.md.
5999
6044
  mcp.custom_route("/", methods=["GET"])(handlers["root_page"])
6000
- mcp.custom_route("/settings", methods=["GET"])(handlers["settings_page"])
6001
- mcp.custom_route("/api/settings/tools", methods=["GET"])(handlers["get_tools"])
6002
- mcp.custom_route("/api/settings/tools", methods=["POST"])(
6003
- handlers["save_tools"]
6004
- )
6005
- mcp.custom_route("/api/settings/restart", methods=["POST"])(
6006
- handlers["restart_addon"]
6007
- )
6008
- mcp.custom_route("/api/settings/info", methods=["GET"])(
6009
- handlers["settings_info"]
6010
- )
6011
- mcp.custom_route("/api/settings/features", methods=["GET"])(
6012
- handlers["get_feature_flags"]
6013
- )
6014
- mcp.custom_route("/api/settings/features", methods=["POST"])(
6015
- handlers["save_feature_flags"]
6016
- )
6017
- # Advanced settings endpoints
6018
- mcp.custom_route("/api/settings/advanced", methods=["GET"])(
6019
- handlers["get_advanced_settings"]
6020
- )
6021
- mcp.custom_route("/api/settings/advanced", methods=["POST"])(
6022
- handlers["save_advanced_settings"]
6023
- )
6024
- # Auto-backup endpoints (#1288)
6025
- mcp.custom_route("/api/settings/backups", methods=["GET"])(
6026
- handlers["list_backups"]
6027
- )
6028
- mcp.custom_route("/api/settings/backups", methods=["DELETE"])(
6029
- handlers["delete_backups_bulk"]
6030
- )
6031
- mcp.custom_route("/api/settings/backups/{name}", methods=["GET"])(
6032
- handlers["view_backup"]
6033
- )
6034
- mcp.custom_route("/api/settings/backups/{name}/diff", methods=["GET"])(
6035
- handlers["diff_backup"]
6036
- )
6037
- mcp.custom_route("/api/settings/backups/{name}/restore", methods=["POST"])(
6038
- handlers["restore_backup"]
6039
- )
6040
- mcp.custom_route("/api/settings/backups/{name}", methods=["DELETE"])(
6041
- handlers["delete_backup"]
6042
- )
6043
- mcp.custom_route("/api/settings/backup-config", methods=["GET"])(
6044
- handlers["get_backup_config"]
6045
- )
6046
- mcp.custom_route("/api/settings/backup-config", methods=["POST"])(
6047
- handlers["save_backup_config"]
6048
- )
6049
- # Tool security policies endpoints
6050
- mcp.custom_route("/api/policy/config", methods=["GET"])(
6051
- handlers["policy_get_config"]
6052
- )
6053
- mcp.custom_route("/api/policy/config", methods=["PUT"])(
6054
- handlers["policy_put_config"]
6055
- )
6056
- mcp.custom_route("/api/policy/pending", methods=["GET"])(
6057
- handlers["policy_get_pending"]
6058
- )
6059
- mcp.custom_route("/api/policy/approve", methods=["POST"])(
6060
- handlers["policy_post_approve"]
6061
- )
6062
- mcp.custom_route("/api/policy/deny", methods=["POST"])(
6063
- handlers["policy_post_deny"]
6064
- )
6065
- mcp.custom_route("/api/policy/tool-schema", methods=["GET"])(
6066
- handlers["policy_get_tool_schema"]
6067
- )
6068
- mcp.custom_route("/api/policy/value-source", methods=["GET"])(
6069
- handlers["policy_get_value_source"]
6070
- )
6045
+ _mount("")
6071
6046
 
6072
6047
  if secret_prefix:
6073
6048
  # Mount under the MCP secret path so Docker / standalone clients
6074
6049
  # need the same secret to reach the UI as they do for the MCP
6075
- # endpoint. The frontend uses relative fetches (./api/settings/...)
6076
- # so the JS works at either prefix unchanged.
6077
- mcp.custom_route(f"{secret_prefix}/settings", methods=["GET"])(
6078
- handlers["settings_page"]
6079
- )
6080
- mcp.custom_route(f"{secret_prefix}/api/settings/tools", methods=["GET"])(
6081
- handlers["get_tools"]
6082
- )
6083
- mcp.custom_route(f"{secret_prefix}/api/settings/tools", methods=["POST"])(
6084
- handlers["save_tools"]
6085
- )
6086
- mcp.custom_route(f"{secret_prefix}/api/settings/restart", methods=["POST"])(
6087
- handlers["restart_addon"]
6088
- )
6089
- mcp.custom_route(f"{secret_prefix}/api/settings/info", methods=["GET"])(
6090
- handlers["settings_info"]
6091
- )
6092
- mcp.custom_route(f"{secret_prefix}/api/settings/features", methods=["GET"])(
6093
- handlers["get_feature_flags"]
6094
- )
6095
- mcp.custom_route(f"{secret_prefix}/api/settings/features", methods=["POST"])(
6096
- handlers["save_feature_flags"]
6097
- )
6098
- # Advanced settings endpoints
6099
- mcp.custom_route(f"{secret_prefix}/api/settings/advanced", methods=["GET"])(
6100
- handlers["get_advanced_settings"]
6101
- )
6102
- mcp.custom_route(f"{secret_prefix}/api/settings/advanced", methods=["POST"])(
6103
- handlers["save_advanced_settings"]
6104
- )
6105
- # Auto-backup endpoints (#1288)
6106
- mcp.custom_route(f"{secret_prefix}/api/settings/backups", methods=["GET"])(
6107
- handlers["list_backups"]
6108
- )
6109
- mcp.custom_route(f"{secret_prefix}/api/settings/backups", methods=["DELETE"])(
6110
- handlers["delete_backups_bulk"]
6111
- )
6112
- mcp.custom_route(
6113
- f"{secret_prefix}/api/settings/backups/{{name}}", methods=["GET"]
6114
- )(handlers["view_backup"])
6115
- mcp.custom_route(
6116
- f"{secret_prefix}/api/settings/backups/{{name}}/diff", methods=["GET"]
6117
- )(handlers["diff_backup"])
6118
- mcp.custom_route(
6119
- f"{secret_prefix}/api/settings/backups/{{name}}/restore", methods=["POST"]
6120
- )(handlers["restore_backup"])
6121
- mcp.custom_route(
6122
- f"{secret_prefix}/api/settings/backups/{{name}}", methods=["DELETE"]
6123
- )(handlers["delete_backup"])
6124
- mcp.custom_route(
6125
- f"{secret_prefix}/api/settings/backup-config", methods=["GET"]
6126
- )(handlers["get_backup_config"])
6127
- mcp.custom_route(
6128
- f"{secret_prefix}/api/settings/backup-config", methods=["POST"]
6129
- )(handlers["save_backup_config"])
6130
- # Tool security policies endpoints
6131
- mcp.custom_route(f"{secret_prefix}/api/policy/config", methods=["GET"])(
6132
- handlers["policy_get_config"]
6133
- )
6134
- mcp.custom_route(f"{secret_prefix}/api/policy/config", methods=["PUT"])(
6135
- handlers["policy_put_config"]
6136
- )
6137
- mcp.custom_route(f"{secret_prefix}/api/policy/pending", methods=["GET"])(
6138
- handlers["policy_get_pending"]
6139
- )
6140
- mcp.custom_route(f"{secret_prefix}/api/policy/approve", methods=["POST"])(
6141
- handlers["policy_post_approve"]
6142
- )
6143
- mcp.custom_route(f"{secret_prefix}/api/policy/deny", methods=["POST"])(
6144
- handlers["policy_post_deny"]
6145
- )
6146
- mcp.custom_route(f"{secret_prefix}/api/policy/tool-schema", methods=["GET"])(
6147
- handlers["policy_get_tool_schema"]
6148
- )
6149
- mcp.custom_route(f"{secret_prefix}/api/policy/value-source", methods=["GET"])(
6150
- handlers["policy_get_value_source"]
6151
- )
6050
+ # endpoint.
6051
+ _mount(secret_prefix)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ha-mcp-dev
3
- Version: 7.6.0.dev634
3
+ Version: 7.6.0.dev636
4
4
  Summary: Home Assistant MCP Server - Complete control of Home Assistant through MCP
5
5
  Author-email: Julien <github@qc-h.net>
6
6
  License: MIT
@@ -38,7 +38,7 @@ Dynamic: license-file
38
38
  <!-- mcp-name: io.github.homeassistant-ai/ha-mcp -->
39
39
 
40
40
  <p align="center">
41
- <img src="https://img.shields.io/badge/tools-86-blue" alt="95+ Tools">
41
+ <img src="https://img.shields.io/badge/tools-84-blue" alt="95+ Tools">
42
42
  <a href="https://github.com/homeassistant-ai/ha-mcp/releases"><img src="https://img.shields.io/github/v/release/homeassistant-ai/ha-mcp" alt="Release"></a>
43
43
  <a href="https://github.com/homeassistant-ai/ha-mcp/actions/workflows/e2e-tests.yml"><img src="https://img.shields.io/github/actions/workflow/status/homeassistant-ai/ha-mcp/e2e-tests.yml?branch=master&label=E2E%20Tests" alt="E2E Tests"></a>
44
44
  <a href="LICENSE.md"><img src="https://img.shields.io/github/license/homeassistant-ai/ha-mcp.svg" alt="License"></a>
@@ -181,7 +181,7 @@ Spend less time configuring, more time enjoying your smart home.
181
181
  <details>
182
182
  <!-- TOOLS_TABLE_START -->
183
183
 
184
- <summary><b>Complete Tool List (86 tools)</b></summary>
184
+ <summary><b>Complete Tool List (84 tools)</b></summary>
185
185
 
186
186
  | Category | Tools |
187
187
  |----------|-------|
@@ -198,7 +198,7 @@ Spend less time configuring, more time enjoying your smart home.
198
198
  | **Entity Registry** | `ha_get_entity_exposure`, `ha_get_entity`, `ha_remove_entity`, `ha_set_entity` |
199
199
  | **Files** | `ha_delete_file` *(beta)*, `ha_list_files` *(beta)*, `ha_read_file` *(beta)*, `ha_write_file` *(beta)* |
200
200
  | **Groups** | `ha_config_list_groups`, `ha_config_remove_group`, `ha_config_set_group` |
201
- | **HACS** | `ha_hacs_add_repository`, `ha_hacs_download`, `ha_hacs_repository_info`, `ha_hacs_search` |
201
+ | **HACS** | `ha_get_hacs_info`, `ha_manage_hacs` |
202
202
  | **Helper Entities** | `ha_config_list_helpers`, `ha_config_set_helper`, `ha_remove_helpers_integrations` |
203
203
  | **History & Statistics** | `ha_get_automation_traces`, `ha_get_history`, `ha_get_logs` |
204
204
  | **Integrations** | `ha_get_integration`, `ha_get_system_health`, `ha_set_integration_enabled` |