ha-mcp-dev 7.4.1.dev462__tar.gz → 7.4.1.dev463__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 (109) hide show
  1. {ha_mcp_dev-7.4.1.dev462/src/ha_mcp_dev.egg-info → ha_mcp_dev-7.4.1.dev463}/PKG-INFO +4 -3
  2. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/README.md +3 -2
  3. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/pyproject.toml +1 -1
  4. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/tools/tools_config_automations.py +92 -0
  5. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463/src/ha_mcp_dev.egg-info}/PKG-INFO +4 -3
  6. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/LICENSE +0 -0
  7. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/MANIFEST.in +0 -0
  8. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/setup.cfg +0 -0
  9. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/__init__.py +0 -0
  10. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/__main__.py +0 -0
  11. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/_pypi_marker +0 -0
  12. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/_version.py +0 -0
  13. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/auth/__init__.py +0 -0
  14. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/auth/consent_form.py +0 -0
  15. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/auth/provider.py +0 -0
  16. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/client/__init__.py +0 -0
  17. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/client/rest_client.py +0 -0
  18. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/client/websocket_client.py +0 -0
  19. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/client/websocket_listener.py +0 -0
  20. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/config.py +0 -0
  21. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/errors.py +0 -0
  22. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/py.typed +0 -0
  23. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/resources/skills-vendor/.claude/settings.json +0 -0
  24. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/resources/skills-vendor/.claude-plugin/marketplace.json +0 -0
  25. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/resources/skills-vendor/.claude-plugin/plugin.json +0 -0
  26. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/resources/skills-vendor/.github/ISSUE_TEMPLATE/skill-rca.md +0 -0
  27. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/resources/skills-vendor/AGENTS.md +0 -0
  28. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/resources/skills-vendor/CLAUDE.md +0 -0
  29. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/resources/skills-vendor/CONTRIBUTING.md +0 -0
  30. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/resources/skills-vendor/LICENSE +0 -0
  31. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/resources/skills-vendor/README.md +0 -0
  32. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/SKILL.md +0 -0
  33. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/evals/evals.json +0 -0
  34. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/automation-patterns.md +0 -0
  35. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-cards.md +0 -0
  36. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-guide.md +0 -0
  37. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/device-control.md +0 -0
  38. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/domain-docs.md +0 -0
  39. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/examples.yaml +0 -0
  40. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/helper-selection.md +0 -0
  41. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/safe-refactoring.md +0 -0
  42. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/template-guidelines.md +0 -0
  43. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/server.py +0 -0
  44. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/settings_ui.py +0 -0
  45. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/smoke_test.py +0 -0
  46. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/tools/__init__.py +0 -0
  47. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/tools/backup.py +0 -0
  48. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/tools/best_practice_checker.py +0 -0
  49. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/tools/device_control.py +0 -0
  50. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/tools/enhanced.py +0 -0
  51. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/tools/helpers.py +0 -0
  52. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/tools/reference_validator.py +0 -0
  53. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/tools/registry.py +0 -0
  54. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/tools/smart_search.py +0 -0
  55. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/tools/tools_addons.py +0 -0
  56. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/tools/tools_areas.py +0 -0
  57. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/tools/tools_blueprints.py +0 -0
  58. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/tools/tools_bug_report.py +0 -0
  59. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/tools/tools_calendar.py +0 -0
  60. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/tools/tools_camera.py +0 -0
  61. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/tools/tools_categories.py +0 -0
  62. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/tools/tools_code.py +0 -0
  63. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/tools/tools_config_dashboards.py +0 -0
  64. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/tools/tools_config_entry_flow.py +0 -0
  65. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/tools/tools_config_helpers.py +0 -0
  66. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/tools/tools_config_scenes.py +0 -0
  67. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/tools/tools_config_scripts.py +0 -0
  68. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/tools/tools_energy.py +0 -0
  69. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/tools/tools_entities.py +0 -0
  70. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/tools/tools_filesystem.py +0 -0
  71. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/tools/tools_groups.py +0 -0
  72. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/tools/tools_hacs.py +0 -0
  73. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/tools/tools_history.py +0 -0
  74. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/tools/tools_integrations.py +0 -0
  75. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/tools/tools_labels.py +0 -0
  76. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/tools/tools_mcp_component.py +0 -0
  77. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/tools/tools_registry.py +0 -0
  78. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/tools/tools_resources.py +0 -0
  79. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/tools/tools_search.py +0 -0
  80. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/tools/tools_service.py +0 -0
  81. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/tools/tools_services.py +0 -0
  82. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/tools/tools_system.py +0 -0
  83. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/tools/tools_todo.py +0 -0
  84. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/tools/tools_traces.py +0 -0
  85. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/tools/tools_updates.py +0 -0
  86. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/tools/tools_utility.py +0 -0
  87. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/tools/tools_voice_assistant.py +0 -0
  88. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/tools/tools_yaml_config.py +0 -0
  89. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/tools/tools_zones.py +0 -0
  90. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/tools/util_helpers.py +0 -0
  91. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/transforms/__init__.py +0 -0
  92. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/transforms/categorized_search.py +0 -0
  93. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/utils/__init__.py +0 -0
  94. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/utils/config_hash.py +0 -0
  95. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/utils/data_paths.py +0 -0
  96. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/utils/domain_handlers.py +0 -0
  97. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/utils/fuzzy_search.py +0 -0
  98. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/utils/kill_signal_diagnostics.py +0 -0
  99. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/utils/operation_manager.py +0 -0
  100. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/utils/python_sandbox.py +0 -0
  101. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp/utils/usage_logger.py +0 -0
  102. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp_dev.egg-info/SOURCES.txt +0 -0
  103. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp_dev.egg-info/dependency_links.txt +0 -0
  104. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp_dev.egg-info/entry_points.txt +0 -0
  105. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp_dev.egg-info/requires.txt +0 -0
  106. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/src/ha_mcp_dev.egg-info/top_level.txt +0 -0
  107. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/tests/__init__.py +0 -0
  108. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/tests/test_constants.py +0 -0
  109. {ha_mcp_dev-7.4.1.dev462 → ha_mcp_dev-7.4.1.dev463}/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.4.1.dev462
3
+ Version: 7.4.1.dev463
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-85-blue" alt="95+ Tools">
41
+ <img src="https://img.shields.io/badge/tools-88-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 (85 tools)</b></summary>
184
+ <summary><b>Complete Tool List (88 tools)</b></summary>
185
185
 
186
186
  | Category | Tools |
187
187
  |----------|-------|
@@ -202,6 +202,7 @@ Spend less time configuring, more time enjoying your smart home.
202
202
  | **History & Statistics** | `ha_get_automation_traces`, `ha_get_history`, `ha_get_logs` |
203
203
  | **Integrations** | `ha_get_integration`, `ha_set_integration_enabled` |
204
204
  | **Labels & Categories** | `ha_config_get_category`, `ha_config_get_label`, `ha_config_remove_category`, `ha_config_remove_label`, `ha_config_set_category`, `ha_config_set_label` |
205
+ | **Scenes** | `ha_config_get_scene`, `ha_config_remove_scene`, `ha_config_set_scene` |
205
206
  | **Scripts** | `ha_config_get_script`, `ha_config_remove_script`, `ha_config_set_script` |
206
207
  | **Search & Discovery** | `ha_deep_search`, `ha_get_overview`, `ha_get_state`, `ha_search_entities` |
207
208
  | **Service & Device Control** | `ha_bulk_control`, `ha_call_service`, `ha_get_operation_status`, `ha_list_services` |
@@ -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-85-blue" alt="95+ Tools">
11
+ <img src="https://img.shields.io/badge/tools-88-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 (85 tools)</b></summary>
154
+ <summary><b>Complete Tool List (88 tools)</b></summary>
155
155
 
156
156
  | Category | Tools |
157
157
  |----------|-------|
@@ -172,6 +172,7 @@ Spend less time configuring, more time enjoying your smart home.
172
172
  | **History & Statistics** | `ha_get_automation_traces`, `ha_get_history`, `ha_get_logs` |
173
173
  | **Integrations** | `ha_get_integration`, `ha_set_integration_enabled` |
174
174
  | **Labels & Categories** | `ha_config_get_category`, `ha_config_get_label`, `ha_config_remove_category`, `ha_config_remove_label`, `ha_config_set_category`, `ha_config_set_label` |
175
+ | **Scenes** | `ha_config_get_scene`, `ha_config_remove_scene`, `ha_config_set_scene` |
175
176
  | **Scripts** | `ha_config_get_script`, `ha_config_remove_script`, `ha_config_set_script` |
176
177
  | **Search & Discovery** | `ha_deep_search`, `ha_get_overview`, `ha_get_state`, `ha_search_entities` |
177
178
  | **Service & Device Control** | `ha_bulk_control`, `ha_call_service`, `ha_get_operation_status`, `ha_list_services` |
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "ha-mcp-dev"
7
- version = "7.4.1.dev462"
7
+ version = "7.4.1.dev463"
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"
@@ -168,6 +168,38 @@ def _normalize_trigger_keys(triggers: list[dict[str, Any]]) -> list[dict[str, An
168
168
  return normalized_triggers
169
169
 
170
170
 
171
+ def _action_contains_scene_create(action: Any) -> bool:
172
+ """True if the action — or any nested action under HA's wrapper keys —
173
+ invokes ``scene.create``.
174
+
175
+ Walks the standard wrappers: ``sequence``, ``parallel``, ``choose``
176
+ (with options' inner ``sequence``), ``default``, and the ``then``/
177
+ ``else`` siblings of ``if``. Returns True on the first hit, so a deep
178
+ misroute is caught before the upsert reaches HA.
179
+ """
180
+ if not isinstance(action, dict):
181
+ return False
182
+ # 'service:' is the legacy key, 'action:' the modern HA service-call
183
+ # key (HA 2024.8+). Both reach scene.create.
184
+ if "scene.create" in (action.get("service"), action.get("action")):
185
+ return True
186
+ # Wrappers whose value is a list of nested actions.
187
+ for nested_key in ("sequence", "parallel", "default", "then", "else"):
188
+ nested = action.get(nested_key)
189
+ if isinstance(nested, list):
190
+ for sub in nested:
191
+ if _action_contains_scene_create(sub):
192
+ return True
193
+ # ``choose``: list of ``{conditions, sequence}`` options.
194
+ if isinstance(action.get("choose"), list):
195
+ for opt in action["choose"]:
196
+ if isinstance(opt, dict) and isinstance(opt.get("sequence"), list):
197
+ for sub in opt["sequence"]:
198
+ if _action_contains_scene_create(sub):
199
+ return True
200
+ return False
201
+
202
+
171
203
  def _normalize_config_for_roundtrip(config: dict[str, Any]) -> dict[str, Any]:
172
204
  """
173
205
  Normalize automation config from GET response for direct use in SET.
@@ -371,6 +403,17 @@ class AutomationConfigTools:
371
403
  """
372
404
  Create or update a Home Assistant automation.
373
405
 
406
+ Before reaching for ``ha_config_set_automation``, consider whether a
407
+ dedicated tool fits the use case better:
408
+
409
+ - State snapshot of one or more entities (capture-then-replay,
410
+ no trigger needed) -> ha_config_set_scene
411
+ - State-derived value that recomputes when its inputs change
412
+ (template sensor / binary sensor / number / select)
413
+ -> ha_config_set_helper(helper_type='template')
414
+ - Stateful counter / timer / schedule / boolean / etc.
415
+ -> ha_config_set_helper(helper_type='counter' | 'timer' | ...)
416
+
374
417
  PREFER NATIVE SOLUTIONS OVER TEMPLATES (read this before writing any `{{ ... }}`):
375
418
  Native triggers/conditions/actions are validated at config load, fail loudly, and
376
419
  do not bypass HA's schema. Templates fail silently at runtime and obscure intent.
@@ -824,6 +867,55 @@ class AutomationConfigTools:
824
867
  missing_fields=missing_fields,
825
868
  ))
826
869
 
870
+ # Issue #1169: reject configs that wrap ``scene.create`` in an
871
+ # automation with no functional trigger. Models occasionally produce
872
+ # these when they want a state snapshot but pattern-match to
873
+ # ``ha_config_set_automation`` instead of ``ha_config_set_scene``.
874
+ # HA's REST endpoint accepts ``trigger: []`` (or ``null``/missing)
875
+ # and stores a never-firing automation — corruption marker, not a
876
+ # draft. Only the narrow misroute pattern is rejected so legitimate
877
+ # empty-trigger drafts paired with other actions still pass.
878
+ trigger_value = config_dict.get("trigger")
879
+ trigger_empty = trigger_value is None or (
880
+ isinstance(trigger_value, list) and not trigger_value
881
+ )
882
+ if trigger_empty:
883
+ actions_list = coerce_to_list(config_dict.get("action"))
884
+ # Walks the standard HA wrappers (``sequence`` / ``parallel`` /
885
+ # ``choose`` / ``if``-``then``/``else``) so a nested
886
+ # ``scene.create`` is caught alongside the top-level case.
887
+ scene_create_indices = [
888
+ i
889
+ for i, a in enumerate(actions_list)
890
+ if _action_contains_scene_create(a)
891
+ ]
892
+ if scene_create_indices:
893
+ raise_tool_error(create_error_response(
894
+ code=ErrorCode.VALIDATION_INVALID_PARAMETER,
895
+ message=(
896
+ "Empty trigger paired with a scene.create action — "
897
+ "this automation can never fire. For a state snapshot "
898
+ "of one or more entities, use ha_config_set_scene "
899
+ "directly instead of wrapping scene.create in an "
900
+ "automation."
901
+ ),
902
+ suggestions=[
903
+ "ha_config_set_scene(scene_id='...', config={'name': "
904
+ "'...', 'entities': {'<entity_id>': {...}}}) creates "
905
+ "a scene without a trigger.",
906
+ "If the snapshot really should be the result of an "
907
+ "event, add the trigger that should fire it and keep "
908
+ "the automation.",
909
+ "For a state-derived value that recomputes when its "
910
+ "inputs change, use "
911
+ "ha_config_set_helper(helper_type='template') instead.",
912
+ ],
913
+ context={
914
+ "scene_create_action_indices": scene_create_indices,
915
+ "identifier": identifier,
916
+ },
917
+ ))
918
+
827
919
  # HA accepts conditions with 'platform' (trigger syntax) but then crashes
828
920
  # with an unhelpful 500 rather than a 400 validation error.
829
921
  for idx, cond in enumerate(coerce_to_list(config_dict.get("condition"))):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ha-mcp-dev
3
- Version: 7.4.1.dev462
3
+ Version: 7.4.1.dev463
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-85-blue" alt="95+ Tools">
41
+ <img src="https://img.shields.io/badge/tools-88-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 (85 tools)</b></summary>
184
+ <summary><b>Complete Tool List (88 tools)</b></summary>
185
185
 
186
186
  | Category | Tools |
187
187
  |----------|-------|
@@ -202,6 +202,7 @@ Spend less time configuring, more time enjoying your smart home.
202
202
  | **History & Statistics** | `ha_get_automation_traces`, `ha_get_history`, `ha_get_logs` |
203
203
  | **Integrations** | `ha_get_integration`, `ha_set_integration_enabled` |
204
204
  | **Labels & Categories** | `ha_config_get_category`, `ha_config_get_label`, `ha_config_remove_category`, `ha_config_remove_label`, `ha_config_set_category`, `ha_config_set_label` |
205
+ | **Scenes** | `ha_config_get_scene`, `ha_config_remove_scene`, `ha_config_set_scene` |
205
206
  | **Scripts** | `ha_config_get_script`, `ha_config_remove_script`, `ha_config_set_script` |
206
207
  | **Search & Discovery** | `ha_deep_search`, `ha_get_overview`, `ha_get_state`, `ha_search_entities` |
207
208
  | **Service & Device Control** | `ha_bulk_control`, `ha_call_service`, `ha_get_operation_status`, `ha_list_services` |