ha-mcp-dev 7.3.0.dev403__tar.gz → 7.4.0.dev406__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.
- {ha_mcp_dev-7.3.0.dev403/src/ha_mcp_dev.egg-info → ha_mcp_dev-7.4.0.dev406}/PKG-INFO +5 -5
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/README.md +4 -4
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/pyproject.toml +1 -1
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/tools/helpers.py +7 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/tools/tools_config_helpers.py +0 -267
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/tools/tools_groups.py +5 -5
- ha_mcp_dev-7.4.0.dev406/src/ha_mcp/tools/tools_integrations.py +1163 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406/src/ha_mcp_dev.egg-info}/PKG-INFO +5 -5
- ha_mcp_dev-7.3.0.dev403/src/ha_mcp/tools/tools_integrations.py +0 -483
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/LICENSE +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/MANIFEST.in +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/setup.cfg +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/__init__.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/__main__.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/_pypi_marker +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/_version.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/auth/__init__.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/auth/consent_form.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/auth/provider.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/client/__init__.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/client/rest_client.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/client/websocket_client.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/client/websocket_listener.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/config.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/errors.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/py.typed +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/resources/skills-vendor/.claude/settings.json +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/resources/skills-vendor/.claude-plugin/marketplace.json +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/resources/skills-vendor/.claude-plugin/plugin.json +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/resources/skills-vendor/.github/ISSUE_TEMPLATE/skill-rca.md +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/resources/skills-vendor/AGENTS.md +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/resources/skills-vendor/CLAUDE.md +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/resources/skills-vendor/CONTRIBUTING.md +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/resources/skills-vendor/LICENSE +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/resources/skills-vendor/README.md +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/SKILL.md +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/evals/evals.json +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/automation-patterns.md +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-cards.md +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-guide.md +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/device-control.md +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/domain-docs.md +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/examples.yaml +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/helper-selection.md +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/safe-refactoring.md +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/template-guidelines.md +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/server.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/smoke_test.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/tools/__init__.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/tools/backup.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/tools/best_practice_checker.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/tools/device_control.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/tools/enhanced.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/tools/reference_validator.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/tools/registry.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/tools/smart_search.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/tools/tools_addons.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/tools/tools_areas.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/tools/tools_blueprints.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/tools/tools_bug_report.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/tools/tools_calendar.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/tools/tools_camera.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/tools/tools_categories.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/tools/tools_config_automations.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/tools/tools_config_dashboards.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/tools/tools_config_entry_flow.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/tools/tools_config_scripts.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/tools/tools_energy.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/tools/tools_entities.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/tools/tools_filesystem.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/tools/tools_hacs.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/tools/tools_history.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/tools/tools_labels.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/tools/tools_mcp_component.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/tools/tools_registry.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/tools/tools_resources.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/tools/tools_search.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/tools/tools_service.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/tools/tools_services.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/tools/tools_system.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/tools/tools_todo.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/tools/tools_traces.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/tools/tools_updates.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/tools/tools_utility.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/tools/tools_voice_assistant.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/tools/tools_yaml_config.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/tools/tools_zones.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/tools/util_helpers.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/transforms/__init__.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/transforms/categorized_search.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/utils/__init__.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/utils/config_hash.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/utils/domain_handlers.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/utils/fuzzy_search.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/utils/operation_manager.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/utils/python_sandbox.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/utils/usage_logger.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp_dev.egg-info/SOURCES.txt +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp_dev.egg-info/dependency_links.txt +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp_dev.egg-info/entry_points.txt +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp_dev.egg-info/requires.txt +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp_dev.egg-info/top_level.txt +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/tests/__init__.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/tests/test_constants.py +0 -0
- {ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/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.
|
|
3
|
+
Version: 7.4.0.dev406
|
|
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
|
|
@@ -37,7 +37,7 @@ Dynamic: license-file
|
|
|
37
37
|
<!-- mcp-name: io.github.homeassistant-ai/ha-mcp -->
|
|
38
38
|
|
|
39
39
|
<p align="center">
|
|
40
|
-
<img src="https://img.shields.io/badge/tools-
|
|
40
|
+
<img src="https://img.shields.io/badge/tools-86-blue" alt="95+ Tools">
|
|
41
41
|
<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>
|
|
42
42
|
<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>
|
|
43
43
|
<a href="LICENSE.md"><img src="https://img.shields.io/github/license/homeassistant-ai/ha-mcp.svg" alt="License"></a>
|
|
@@ -180,7 +180,7 @@ Spend less time configuring, more time enjoying your smart home.
|
|
|
180
180
|
<details>
|
|
181
181
|
<!-- TOOLS_TABLE_START -->
|
|
182
182
|
|
|
183
|
-
<summary><b>Complete Tool List (
|
|
183
|
+
<summary><b>Complete Tool List (86 tools)</b></summary>
|
|
184
184
|
|
|
185
185
|
| Category | Tools |
|
|
186
186
|
|----------|-------|
|
|
@@ -197,9 +197,9 @@ Spend less time configuring, more time enjoying your smart home.
|
|
|
197
197
|
| **Files** | `ha_delete_file` *(beta)*, `ha_list_files` *(beta)*, `ha_read_file` *(beta)*, `ha_write_file` *(beta)* |
|
|
198
198
|
| **Groups** | `ha_config_list_groups`, `ha_config_remove_group`, `ha_config_set_group` |
|
|
199
199
|
| **HACS** | `ha_hacs_add_repository`, `ha_hacs_download`, `ha_hacs_repository_info`, `ha_hacs_search` |
|
|
200
|
-
| **Helper Entities** | `ha_config_list_helpers`, `
|
|
200
|
+
| **Helper Entities** | `ha_config_list_helpers`, `ha_config_set_helper`, `ha_delete_helpers_integrations`, `ha_get_helper_schema` |
|
|
201
201
|
| **History & Statistics** | `ha_get_automation_traces`, `ha_get_history`, `ha_get_logs` |
|
|
202
|
-
| **Integrations** | `
|
|
202
|
+
| **Integrations** | `ha_get_integration`, `ha_set_integration_enabled` |
|
|
203
203
|
| **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` |
|
|
204
204
|
| **Scripts** | `ha_config_get_script`, `ha_config_remove_script`, `ha_config_set_script` |
|
|
205
205
|
| **Search & Discovery** | `ha_deep_search`, `ha_get_overview`, `ha_get_state`, `ha_search_entities` |
|
|
@@ -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-
|
|
11
|
+
<img src="https://img.shields.io/badge/tools-86-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 (
|
|
154
|
+
<summary><b>Complete Tool List (86 tools)</b></summary>
|
|
155
155
|
|
|
156
156
|
| Category | Tools |
|
|
157
157
|
|----------|-------|
|
|
@@ -168,9 +168,9 @@ Spend less time configuring, more time enjoying your smart home.
|
|
|
168
168
|
| **Files** | `ha_delete_file` *(beta)*, `ha_list_files` *(beta)*, `ha_read_file` *(beta)*, `ha_write_file` *(beta)* |
|
|
169
169
|
| **Groups** | `ha_config_list_groups`, `ha_config_remove_group`, `ha_config_set_group` |
|
|
170
170
|
| **HACS** | `ha_hacs_add_repository`, `ha_hacs_download`, `ha_hacs_repository_info`, `ha_hacs_search` |
|
|
171
|
-
| **Helper Entities** | `ha_config_list_helpers`, `
|
|
171
|
+
| **Helper Entities** | `ha_config_list_helpers`, `ha_config_set_helper`, `ha_delete_helpers_integrations`, `ha_get_helper_schema` |
|
|
172
172
|
| **History & Statistics** | `ha_get_automation_traces`, `ha_get_history`, `ha_get_logs` |
|
|
173
|
-
| **Integrations** | `
|
|
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
175
|
| **Scripts** | `ha_config_get_script`, `ha_config_remove_script`, `ha_config_set_script` |
|
|
176
176
|
| **Search & Discovery** | `ha_deep_search`, `ha_get_overview`, `ha_get_state`, `ha_search_entities` |
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "ha-mcp-dev"
|
|
7
|
-
version = "7.
|
|
7
|
+
version = "7.4.0.dev406"
|
|
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"
|
|
@@ -308,6 +308,13 @@ def exception_to_structured_error(
|
|
|
308
308
|
error_response = _classify_exception(error, error_str, error_msg, context)
|
|
309
309
|
|
|
310
310
|
if suggestions and "error" in error_response and isinstance(error_response["error"], dict):
|
|
311
|
+
# Set both `suggestion` (singular, first item) and `suggestions`
|
|
312
|
+
# (plural, full list). create_error_response (errors.py) sets the
|
|
313
|
+
# singular key; existing tests for exception_to_structured_error
|
|
314
|
+
# rely on the plural key being present even for single-item caller
|
|
315
|
+
# suggestions. Setting both keeps response consumers on both code
|
|
316
|
+
# paths working.
|
|
317
|
+
error_response["error"]["suggestion"] = suggestions[0]
|
|
311
318
|
error_response["error"]["suggestions"] = suggestions
|
|
312
319
|
|
|
313
320
|
# Append macOS-specific hints for connection failures (after all other processing
|
{ha_mcp_dev-7.3.0.dev403 → ha_mcp_dev-7.4.0.dev406}/src/ha_mcp/tools/tools_config_helpers.py
RENAMED
|
@@ -26,7 +26,6 @@ from .util_helpers import (
|
|
|
26
26
|
parse_json_param,
|
|
27
27
|
parse_string_list_param,
|
|
28
28
|
wait_for_entity_registered,
|
|
29
|
-
wait_for_entity_removed,
|
|
30
29
|
)
|
|
31
30
|
|
|
32
31
|
# Simple helper types — managed via {type}/create and {type}/update WebSocket APIs
|
|
@@ -1668,269 +1667,3 @@ def register_config_helper_tools(mcp: Any, client: Any, **kwargs: Any) -> None:
|
|
|
1668
1667
|
"Ensure required parameters are provided for the helper type",
|
|
1669
1668
|
],
|
|
1670
1669
|
)
|
|
1671
|
-
|
|
1672
|
-
@mcp.tool(
|
|
1673
|
-
tags={"Helper Entities"},
|
|
1674
|
-
annotations={
|
|
1675
|
-
"destructiveHint": True,
|
|
1676
|
-
"idempotentHint": True,
|
|
1677
|
-
"title": "Remove Helper",
|
|
1678
|
-
},
|
|
1679
|
-
)
|
|
1680
|
-
@log_tool_usage
|
|
1681
|
-
async def ha_config_remove_helper(
|
|
1682
|
-
helper_type: Annotated[
|
|
1683
|
-
Literal[
|
|
1684
|
-
"input_button",
|
|
1685
|
-
"input_boolean",
|
|
1686
|
-
"input_select",
|
|
1687
|
-
"input_number",
|
|
1688
|
-
"input_text",
|
|
1689
|
-
"input_datetime",
|
|
1690
|
-
"counter",
|
|
1691
|
-
"timer",
|
|
1692
|
-
"schedule",
|
|
1693
|
-
"zone",
|
|
1694
|
-
"person",
|
|
1695
|
-
"tag",
|
|
1696
|
-
],
|
|
1697
|
-
Field(description="Type of helper entity to delete"),
|
|
1698
|
-
],
|
|
1699
|
-
helper_id: Annotated[
|
|
1700
|
-
str,
|
|
1701
|
-
Field(
|
|
1702
|
-
description="Helper ID to delete (e.g., 'my_button' or 'input_button.my_button')"
|
|
1703
|
-
),
|
|
1704
|
-
],
|
|
1705
|
-
wait: Annotated[
|
|
1706
|
-
bool | str,
|
|
1707
|
-
Field(
|
|
1708
|
-
description="Wait for helper entity to be fully removed before returning. Default: True.",
|
|
1709
|
-
default=True,
|
|
1710
|
-
),
|
|
1711
|
-
] = True,
|
|
1712
|
-
) -> dict[str, Any]:
|
|
1713
|
-
"""
|
|
1714
|
-
Delete a Home Assistant helper entity.
|
|
1715
|
-
|
|
1716
|
-
SUPPORTED HELPER TYPES:
|
|
1717
|
-
- input_button, input_boolean, input_select, input_number, input_text, input_datetime
|
|
1718
|
-
- counter, timer, schedule, zone, person, tag
|
|
1719
|
-
|
|
1720
|
-
For flow-based helper types (template, group, utility_meter, derivative,
|
|
1721
|
-
min_max, threshold, integration, statistics, trend, random, filter, tod,
|
|
1722
|
-
generic_thermostat, switch_as_x, generic_hygrostat) use ha_delete_config_entry.
|
|
1723
|
-
|
|
1724
|
-
EXAMPLES:
|
|
1725
|
-
- Delete button: ha_config_remove_helper("input_button", "my_button")
|
|
1726
|
-
- Delete counter: ha_config_remove_helper("counter", "my_counter")
|
|
1727
|
-
- Delete timer: ha_config_remove_helper("timer", "my_timer")
|
|
1728
|
-
- Delete schedule: ha_config_remove_helper("schedule", "work_hours")
|
|
1729
|
-
|
|
1730
|
-
**WARNING:** Deleting a helper that is used by automations or scripts may cause those automations/scripts to fail.
|
|
1731
|
-
Use ha_search_entities() to verify the helper exists before attempting to delete it.
|
|
1732
|
-
"""
|
|
1733
|
-
try:
|
|
1734
|
-
# Convert helper_id to full entity_id if needed
|
|
1735
|
-
entity_id = (
|
|
1736
|
-
helper_id
|
|
1737
|
-
if helper_id.startswith(helper_type)
|
|
1738
|
-
else f"{helper_type}.{helper_id}"
|
|
1739
|
-
)
|
|
1740
|
-
|
|
1741
|
-
# Try to get unique_id with retry logic to handle race conditions
|
|
1742
|
-
unique_id = None
|
|
1743
|
-
registry_result = None
|
|
1744
|
-
max_retries = 3
|
|
1745
|
-
|
|
1746
|
-
for attempt in range(max_retries):
|
|
1747
|
-
logger.info(
|
|
1748
|
-
f"Getting entity registry for: {entity_id} (attempt {attempt + 1}/{max_retries})"
|
|
1749
|
-
)
|
|
1750
|
-
|
|
1751
|
-
# Check if entity exists via state API first (faster check)
|
|
1752
|
-
try:
|
|
1753
|
-
state_check = await client.get_entity_state(entity_id)
|
|
1754
|
-
if not state_check:
|
|
1755
|
-
# Entity doesn't exist in state, wait a bit for registration
|
|
1756
|
-
if attempt < max_retries - 1:
|
|
1757
|
-
wait_time = 0.5 * (
|
|
1758
|
-
2**attempt
|
|
1759
|
-
) # Exponential backoff: 0.5s, 1s, 2s
|
|
1760
|
-
logger.debug(
|
|
1761
|
-
f"Entity {entity_id} not found in state, waiting {wait_time}s before retry..."
|
|
1762
|
-
)
|
|
1763
|
-
await asyncio.sleep(wait_time)
|
|
1764
|
-
continue
|
|
1765
|
-
except Exception as e:
|
|
1766
|
-
logger.debug(f"State check failed for {entity_id}: {e}")
|
|
1767
|
-
|
|
1768
|
-
# Try registry lookup
|
|
1769
|
-
registry_msg: dict[str, Any] = {
|
|
1770
|
-
"type": "config/entity_registry/get",
|
|
1771
|
-
"entity_id": entity_id,
|
|
1772
|
-
}
|
|
1773
|
-
|
|
1774
|
-
try:
|
|
1775
|
-
registry_result = await client.send_websocket_message(registry_msg)
|
|
1776
|
-
|
|
1777
|
-
if registry_result.get("success"):
|
|
1778
|
-
entity_entry = registry_result.get("result", {})
|
|
1779
|
-
unique_id = entity_entry.get("unique_id")
|
|
1780
|
-
if unique_id:
|
|
1781
|
-
logger.info(f"Found unique_id: {unique_id} for {entity_id}")
|
|
1782
|
-
break
|
|
1783
|
-
|
|
1784
|
-
# If registry lookup failed but we haven't exhausted retries, wait and try again
|
|
1785
|
-
if attempt < max_retries - 1:
|
|
1786
|
-
wait_time = 0.5 * (2**attempt) # Exponential backoff
|
|
1787
|
-
logger.debug(
|
|
1788
|
-
f"Registry lookup failed for {entity_id}, waiting {wait_time}s before retry..."
|
|
1789
|
-
)
|
|
1790
|
-
await asyncio.sleep(wait_time)
|
|
1791
|
-
|
|
1792
|
-
except Exception as e:
|
|
1793
|
-
logger.warning(f"Registry lookup attempt {attempt + 1} failed: {e}")
|
|
1794
|
-
if attempt < max_retries - 1:
|
|
1795
|
-
wait_time = 0.5 * (2**attempt)
|
|
1796
|
-
await asyncio.sleep(wait_time)
|
|
1797
|
-
|
|
1798
|
-
# Fallback strategy 1: Try deletion with helper_id directly if unique_id not found
|
|
1799
|
-
if not unique_id:
|
|
1800
|
-
logger.info(
|
|
1801
|
-
f"Could not find unique_id for {entity_id}, trying direct deletion with helper_id"
|
|
1802
|
-
)
|
|
1803
|
-
|
|
1804
|
-
# Try deleting using helper_id directly (fallback approach)
|
|
1805
|
-
delete_msg: dict[str, Any] = {
|
|
1806
|
-
"type": f"{helper_type}/delete",
|
|
1807
|
-
f"{helper_type}_id": helper_id,
|
|
1808
|
-
}
|
|
1809
|
-
|
|
1810
|
-
logger.info(f"Sending fallback WebSocket delete message: {delete_msg}")
|
|
1811
|
-
result = await client.send_websocket_message(delete_msg)
|
|
1812
|
-
|
|
1813
|
-
if result.get("success"):
|
|
1814
|
-
# Wait for entity to be removed
|
|
1815
|
-
wait_bool = coerce_bool_param(wait, "wait", default=True)
|
|
1816
|
-
response: dict[str, Any] = {
|
|
1817
|
-
"success": True,
|
|
1818
|
-
"action": "delete",
|
|
1819
|
-
"helper_type": helper_type,
|
|
1820
|
-
"helper_id": helper_id,
|
|
1821
|
-
"entity_id": entity_id,
|
|
1822
|
-
"method": "fallback_direct_id",
|
|
1823
|
-
"message": f"Successfully deleted {helper_type}: {helper_id} using direct ID (entity: {entity_id})",
|
|
1824
|
-
}
|
|
1825
|
-
if wait_bool:
|
|
1826
|
-
try:
|
|
1827
|
-
removed = await wait_for_entity_removed(client, entity_id)
|
|
1828
|
-
if not removed:
|
|
1829
|
-
response["warning"] = (
|
|
1830
|
-
f"Deletion confirmed but {entity_id} may still appear briefly."
|
|
1831
|
-
)
|
|
1832
|
-
except Exception as e:
|
|
1833
|
-
response["warning"] = (
|
|
1834
|
-
f"Deletion confirmed but removal verification failed: {e}"
|
|
1835
|
-
)
|
|
1836
|
-
return response
|
|
1837
|
-
|
|
1838
|
-
# Fallback strategy 2: Check if entity was already deleted
|
|
1839
|
-
try:
|
|
1840
|
-
final_state_check = await client.get_entity_state(entity_id)
|
|
1841
|
-
if not final_state_check:
|
|
1842
|
-
logger.info(
|
|
1843
|
-
f"Entity {entity_id} no longer exists, considering deletion successful"
|
|
1844
|
-
)
|
|
1845
|
-
return {
|
|
1846
|
-
"success": True,
|
|
1847
|
-
"action": "delete",
|
|
1848
|
-
"helper_type": helper_type,
|
|
1849
|
-
"helper_id": helper_id,
|
|
1850
|
-
"entity_id": entity_id,
|
|
1851
|
-
"method": "already_deleted",
|
|
1852
|
-
"message": f"Helper {helper_id} was already deleted or never properly registered",
|
|
1853
|
-
}
|
|
1854
|
-
except Exception:
|
|
1855
|
-
pass
|
|
1856
|
-
|
|
1857
|
-
# Final fallback failed
|
|
1858
|
-
raise_tool_error(
|
|
1859
|
-
create_error_response(
|
|
1860
|
-
ErrorCode.ENTITY_NOT_FOUND,
|
|
1861
|
-
f"Helper not found in entity registry after {max_retries} attempts: {registry_result.get('error', 'Unknown error') if registry_result else 'No registry response'}",
|
|
1862
|
-
suggestions=[
|
|
1863
|
-
"Helper may not be properly registered or was already deleted. Use ha_search_entities() to verify.",
|
|
1864
|
-
],
|
|
1865
|
-
context={"helper_id": helper_id, "entity_id": entity_id},
|
|
1866
|
-
)
|
|
1867
|
-
)
|
|
1868
|
-
|
|
1869
|
-
# Delete helper using unique_id (correct API from docs)
|
|
1870
|
-
delete_message: dict[str, Any] = {
|
|
1871
|
-
"type": f"{helper_type}/delete",
|
|
1872
|
-
f"{helper_type}_id": unique_id,
|
|
1873
|
-
}
|
|
1874
|
-
|
|
1875
|
-
logger.info(f"Sending WebSocket delete message: {delete_message}")
|
|
1876
|
-
result = await client.send_websocket_message(delete_message)
|
|
1877
|
-
logger.info(f"WebSocket delete response: {result}")
|
|
1878
|
-
|
|
1879
|
-
if result.get("success"):
|
|
1880
|
-
# Wait for entity to be removed
|
|
1881
|
-
wait_bool = coerce_bool_param(wait, "wait", default=True)
|
|
1882
|
-
response = {
|
|
1883
|
-
"success": True,
|
|
1884
|
-
"action": "delete",
|
|
1885
|
-
"helper_type": helper_type,
|
|
1886
|
-
"helper_id": helper_id,
|
|
1887
|
-
"entity_id": entity_id,
|
|
1888
|
-
"unique_id": unique_id,
|
|
1889
|
-
"method": "standard",
|
|
1890
|
-
"message": f"Successfully deleted {helper_type}: {helper_id} (entity: {entity_id})",
|
|
1891
|
-
}
|
|
1892
|
-
if wait_bool:
|
|
1893
|
-
try:
|
|
1894
|
-
removed = await wait_for_entity_removed(client, entity_id)
|
|
1895
|
-
if not removed:
|
|
1896
|
-
response["warning"] = (
|
|
1897
|
-
f"Deletion confirmed but {entity_id} may still appear briefly."
|
|
1898
|
-
)
|
|
1899
|
-
except Exception as e:
|
|
1900
|
-
response["warning"] = (
|
|
1901
|
-
f"Deletion confirmed but removal verification failed: {e}"
|
|
1902
|
-
)
|
|
1903
|
-
return response
|
|
1904
|
-
else:
|
|
1905
|
-
error_msg = result.get("error", "Unknown error")
|
|
1906
|
-
# Handle specific HA error messages
|
|
1907
|
-
if isinstance(error_msg, dict):
|
|
1908
|
-
error_msg = error_msg.get("message", str(error_msg))
|
|
1909
|
-
|
|
1910
|
-
raise_tool_error(
|
|
1911
|
-
create_error_response(
|
|
1912
|
-
ErrorCode.SERVICE_CALL_FAILED,
|
|
1913
|
-
f"Failed to delete helper: {error_msg}",
|
|
1914
|
-
suggestions=[
|
|
1915
|
-
"Make sure the helper exists and is not being used by automations or scripts",
|
|
1916
|
-
],
|
|
1917
|
-
context={
|
|
1918
|
-
"helper_id": helper_id,
|
|
1919
|
-
"entity_id": entity_id,
|
|
1920
|
-
"unique_id": unique_id,
|
|
1921
|
-
},
|
|
1922
|
-
)
|
|
1923
|
-
)
|
|
1924
|
-
|
|
1925
|
-
except ToolError:
|
|
1926
|
-
raise
|
|
1927
|
-
except Exception as e:
|
|
1928
|
-
exception_to_structured_error(
|
|
1929
|
-
e,
|
|
1930
|
-
context={"helper_type": helper_type, "helper_id": helper_id},
|
|
1931
|
-
suggestions=[
|
|
1932
|
-
"Check Home Assistant connection",
|
|
1933
|
-
"Verify helper_id exists using ha_search_entities()",
|
|
1934
|
-
"Ensure helper is not being used by automations or scripts",
|
|
1935
|
-
],
|
|
1936
|
-
)
|
|
@@ -250,12 +250,12 @@ class GroupTools:
|
|
|
250
250
|
**When NOT to use:** for typical "combine these entities into one controllable group"
|
|
251
251
|
requests, prefer `ha_config_set_helper(helper_type="group", ...)`. Config-entry-backed
|
|
252
252
|
groups are registered in the entity registry, so `ha_set_entity` can assign them to
|
|
253
|
-
areas and they are deletable via `
|
|
253
|
+
areas and they are deletable via `ha_delete_helpers_integrations`.
|
|
254
254
|
|
|
255
255
|
**When to use:** compatibility with existing groups already configured via group.set
|
|
256
256
|
or YAML, or the rare case where entity-registry membership is explicitly unwanted.
|
|
257
|
-
Groups created here are only removable via `ha_config_remove_group` —
|
|
258
|
-
`
|
|
257
|
+
Groups created here are only removable via `ha_config_remove_group` —
|
|
258
|
+
`ha_delete_helpers_integrations` will not find them.
|
|
259
259
|
|
|
260
260
|
**For NEW groups:** Provide object_id and entities (required).
|
|
261
261
|
**For EXISTING groups:** Provide object_id and any fields to update.
|
|
@@ -343,8 +343,8 @@ class GroupTools:
|
|
|
343
343
|
Remove a service-based Home Assistant entity group via the group.remove service.
|
|
344
344
|
|
|
345
345
|
**When NOT to use:** for groups created through `ha_config_set_helper(helper_type="group", ...)`,
|
|
346
|
-
use `
|
|
347
|
-
group.remove service
|
|
346
|
+
use `ha_delete_helpers_integrations`. Those config-entry-backed groups are not reachable via the
|
|
347
|
+
group.remove service.
|
|
348
348
|
|
|
349
349
|
**When to use:** removing groups created with `ha_config_set_group` or defined in YAML
|
|
350
350
|
via `group:` configuration. Config-entry-backed deletion tools cannot find these.
|