ha-mcp-dev 7.1.0.dev308__tar.gz → 7.1.0.dev310__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 (100) hide show
  1. {ha_mcp_dev-7.1.0.dev308/src/ha_mcp_dev.egg-info → ha_mcp_dev-7.1.0.dev310}/PKG-INFO +5 -5
  2. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/README.md +3 -3
  3. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/pyproject.toml +2 -2
  4. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/config.py +14 -3
  5. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/server.py +5 -0
  6. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/tools/tools_traces.py +97 -7
  7. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/tools/tools_utility.py +32 -0
  8. ha_mcp_dev-7.1.0.dev310/src/ha_mcp/tools/tools_yaml_config.py +205 -0
  9. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/transforms/categorized_search.py +1 -0
  10. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310/src/ha_mcp_dev.egg-info}/PKG-INFO +5 -5
  11. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp_dev.egg-info/SOURCES.txt +1 -0
  12. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp_dev.egg-info/requires.txt +1 -1
  13. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/LICENSE +0 -0
  14. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/MANIFEST.in +0 -0
  15. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/setup.cfg +0 -0
  16. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/__init__.py +0 -0
  17. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/__main__.py +0 -0
  18. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/_pypi_marker +0 -0
  19. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/auth/__init__.py +0 -0
  20. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/auth/consent_form.py +0 -0
  21. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/auth/provider.py +0 -0
  22. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/client/__init__.py +0 -0
  23. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/client/rest_client.py +0 -0
  24. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/client/websocket_client.py +0 -0
  25. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/client/websocket_listener.py +0 -0
  26. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/errors.py +0 -0
  27. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/py.typed +0 -0
  28. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/resources/skills-vendor/.claude/settings.json +0 -0
  29. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/resources/skills-vendor/.claude-plugin/marketplace.json +0 -0
  30. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/resources/skills-vendor/.claude-plugin/plugin.json +0 -0
  31. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/resources/skills-vendor/.github/ISSUE_TEMPLATE/skill-rca.md +0 -0
  32. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/resources/skills-vendor/AGENTS.md +0 -0
  33. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/resources/skills-vendor/CLAUDE.md +0 -0
  34. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/resources/skills-vendor/CONTRIBUTING.md +0 -0
  35. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/resources/skills-vendor/LICENSE +0 -0
  36. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/resources/skills-vendor/README.md +0 -0
  37. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/SKILL.md +0 -0
  38. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/evals/evals.json +0 -0
  39. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/automation-patterns.md +0 -0
  40. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-cards.md +0 -0
  41. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-guide.md +0 -0
  42. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/device-control.md +0 -0
  43. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/domain-docs.md +0 -0
  44. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/examples.yaml +0 -0
  45. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/helper-selection.md +0 -0
  46. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/safe-refactoring.md +0 -0
  47. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/template-guidelines.md +0 -0
  48. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/smoke_test.py +0 -0
  49. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/tools/__init__.py +0 -0
  50. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/tools/backup.py +0 -0
  51. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/tools/best_practice_checker.py +0 -0
  52. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/tools/device_control.py +0 -0
  53. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/tools/enhanced.py +0 -0
  54. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/tools/helpers.py +0 -0
  55. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/tools/registry.py +0 -0
  56. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/tools/smart_search.py +0 -0
  57. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/tools/tools_addons.py +0 -0
  58. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/tools/tools_areas.py +0 -0
  59. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/tools/tools_blueprints.py +0 -0
  60. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/tools/tools_bug_report.py +0 -0
  61. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/tools/tools_calendar.py +0 -0
  62. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/tools/tools_camera.py +0 -0
  63. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/tools/tools_categories.py +0 -0
  64. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/tools/tools_config_automations.py +0 -0
  65. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/tools/tools_config_dashboards.py +0 -0
  66. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/tools/tools_config_entry_flow.py +0 -0
  67. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/tools/tools_config_helpers.py +0 -0
  68. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/tools/tools_config_scripts.py +0 -0
  69. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/tools/tools_entities.py +0 -0
  70. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/tools/tools_filesystem.py +0 -0
  71. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/tools/tools_groups.py +0 -0
  72. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/tools/tools_hacs.py +0 -0
  73. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/tools/tools_history.py +0 -0
  74. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/tools/tools_integrations.py +0 -0
  75. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/tools/tools_labels.py +0 -0
  76. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/tools/tools_mcp_component.py +0 -0
  77. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/tools/tools_registry.py +0 -0
  78. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/tools/tools_resources.py +0 -0
  79. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/tools/tools_search.py +0 -0
  80. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/tools/tools_service.py +0 -0
  81. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/tools/tools_services.py +0 -0
  82. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/tools/tools_system.py +0 -0
  83. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/tools/tools_todo.py +0 -0
  84. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/tools/tools_updates.py +0 -0
  85. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/tools/tools_voice_assistant.py +0 -0
  86. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/tools/tools_zones.py +0 -0
  87. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/tools/util_helpers.py +0 -0
  88. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/transforms/__init__.py +0 -0
  89. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/utils/__init__.py +0 -0
  90. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/utils/domain_handlers.py +0 -0
  91. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/utils/fuzzy_search.py +0 -0
  92. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/utils/operation_manager.py +0 -0
  93. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/utils/python_sandbox.py +0 -0
  94. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp/utils/usage_logger.py +0 -0
  95. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp_dev.egg-info/dependency_links.txt +0 -0
  96. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp_dev.egg-info/entry_points.txt +0 -0
  97. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/src/ha_mcp_dev.egg-info/top_level.txt +0 -0
  98. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/tests/__init__.py +0 -0
  99. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/tests/test_constants.py +0 -0
  100. {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev310}/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.1.0.dev308
3
+ Version: 7.1.0.dev310
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
@@ -18,7 +18,7 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
18
18
  Requires-Python: <3.14,>=3.13
19
19
  Description-Content-Type: text/markdown
20
20
  License-File: LICENSE
21
- Requires-Dist: fastmcp==3.1.1
21
+ Requires-Dist: fastmcp==3.2.0
22
22
  Requires-Dist: httpx[socks]==0.28.1
23
23
  Requires-Dist: pydantic==2.12.5
24
24
  Requires-Dist: python-dotenv==1.2.2
@@ -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-93-blue" alt="95+ Tools">
40
+ <img src="https://img.shields.io/badge/tools-94-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>
@@ -160,7 +160,7 @@ Spend less time configuring, more time enjoying your smart home.
160
160
  <details>
161
161
  <!-- TOOLS_TABLE_START -->
162
162
 
163
- <summary><b>Complete Tool List (93 tools)</b></summary>
163
+ <summary><b>Complete Tool List (94 tools)</b></summary>
164
164
 
165
165
  | Category | Tools |
166
166
  |----------|-------|
@@ -183,7 +183,7 @@ Spend less time configuring, more time enjoying your smart home.
183
183
  | **Scripts** | `ha_config_get_script`, `ha_config_remove_script`, `ha_config_set_script` |
184
184
  | **Search & Discovery** | `ha_deep_search`, `ha_get_overview`, `ha_get_state`, `ha_get_states`, `ha_search_entities` |
185
185
  | **Service & Device Control** | `ha_bulk_control`, `ha_call_service`, `ha_get_bulk_status`, `ha_get_operation_status`, `ha_list_services` |
186
- | **System** | `ha_backup_create`, `ha_backup_restore`, `ha_check_config`, `ha_get_system_health`, `ha_get_updates`, `ha_reload_core`, `ha_restart` |
186
+ | **System** | `ha_backup_create`, `ha_backup_restore`, `ha_check_config`, `ha_config_set_yaml`, `ha_get_system_health`, `ha_get_updates`, `ha_reload_core`, `ha_restart` |
187
187
  | **Todo Lists** | `ha_add_todo_item`, `ha_get_todo`, `ha_remove_todo_item`, `ha_update_todo_item` |
188
188
  | **Utilities** | `ha_eval_template`, `ha_install_mcp_tools`, `ha_report_issue` |
189
189
  | **Zones** | `ha_get_zone`, `ha_remove_zone`, `ha_set_zone` |
@@ -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-93-blue" alt="95+ Tools">
11
+ <img src="https://img.shields.io/badge/tools-94-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>
@@ -131,7 +131,7 @@ Spend less time configuring, more time enjoying your smart home.
131
131
  <details>
132
132
  <!-- TOOLS_TABLE_START -->
133
133
 
134
- <summary><b>Complete Tool List (93 tools)</b></summary>
134
+ <summary><b>Complete Tool List (94 tools)</b></summary>
135
135
 
136
136
  | Category | Tools |
137
137
  |----------|-------|
@@ -154,7 +154,7 @@ Spend less time configuring, more time enjoying your smart home.
154
154
  | **Scripts** | `ha_config_get_script`, `ha_config_remove_script`, `ha_config_set_script` |
155
155
  | **Search & Discovery** | `ha_deep_search`, `ha_get_overview`, `ha_get_state`, `ha_get_states`, `ha_search_entities` |
156
156
  | **Service & Device Control** | `ha_bulk_control`, `ha_call_service`, `ha_get_bulk_status`, `ha_get_operation_status`, `ha_list_services` |
157
- | **System** | `ha_backup_create`, `ha_backup_restore`, `ha_check_config`, `ha_get_system_health`, `ha_get_updates`, `ha_reload_core`, `ha_restart` |
157
+ | **System** | `ha_backup_create`, `ha_backup_restore`, `ha_check_config`, `ha_config_set_yaml`, `ha_get_system_health`, `ha_get_updates`, `ha_reload_core`, `ha_restart` |
158
158
  | **Todo Lists** | `ha_add_todo_item`, `ha_get_todo`, `ha_remove_todo_item`, `ha_update_todo_item` |
159
159
  | **Utilities** | `ha_eval_template`, `ha_install_mcp_tools`, `ha_report_issue` |
160
160
  | **Zones** | `ha_get_zone`, `ha_remove_zone`, `ha_set_zone` |
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "ha-mcp-dev"
7
- version = "7.1.0.dev308"
7
+ version = "7.1.0.dev310"
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"
@@ -24,7 +24,7 @@ classifiers = [
24
24
  ]
25
25
 
26
26
  dependencies = [
27
- "fastmcp==3.1.1",
27
+ "fastmcp==3.2.0",
28
28
  "httpx[socks]==0.28.1",
29
29
  "pydantic==2.12.5",
30
30
  "python-dotenv==1.2.2",
@@ -48,7 +48,9 @@ class Settings(BaseSettings):
48
48
  # Home Assistant connection
49
49
  # In OAuth mode, these are optional and provided per-request
50
50
  homeassistant_url: str = Field(default=OAUTH_MODE_URL, alias="HOMEASSISTANT_URL")
51
- homeassistant_token: str = Field(default=OAUTH_MODE_TOKEN, alias="HOMEASSISTANT_TOKEN")
51
+ homeassistant_token: str = Field(
52
+ default=OAUTH_MODE_TOKEN, alias="HOMEASSISTANT_TOKEN"
53
+ )
52
54
 
53
55
  # Server configuration
54
56
  timeout: int = Field(30, alias="HA_TIMEOUT")
@@ -70,7 +72,9 @@ class Settings(BaseSettings):
70
72
 
71
73
  # MCP Server configuration
72
74
  mcp_server_name: str = Field("ha-mcp", alias="MCP_SERVER_NAME")
73
- mcp_server_version: str = Field(default=_PACKAGE_VERSION, alias="MCP_SERVER_VERSION")
75
+ mcp_server_version: str = Field(
76
+ default=_PACKAGE_VERSION, alias="MCP_SERVER_VERSION"
77
+ )
74
78
 
75
79
  # Environment configuration
76
80
  environment: str = Field("development", alias="ENVIRONMENT")
@@ -83,7 +87,9 @@ class Settings(BaseSettings):
83
87
  # Dashboard partial update tools (python_transform, find_card)
84
88
  # These are token-efficient alternatives to full config replacement.
85
89
  # Disable when using clients with programmatic tool use (future).
86
- enable_dashboard_partial_tools: bool = Field(True, alias="ENABLE_DASHBOARD_PARTIAL_TOOLS")
90
+ enable_dashboard_partial_tools: bool = Field(
91
+ True, alias="ENABLE_DASHBOARD_PARTIAL_TOOLS"
92
+ )
87
93
 
88
94
  # Skills configuration
89
95
  # Serve bundled HA best-practice skills as MCP resources (skill:// URIs).
@@ -101,6 +107,11 @@ class Settings(BaseSettings):
101
107
  # Dramatically reduces idle context token usage for LLMs.
102
108
  enable_tool_search: bool = Field(False, alias="ENABLE_TOOL_SEARCH")
103
109
 
110
+ # Managed YAML config editing — allows ha_config_set_yaml to add,
111
+ # replace, or remove top-level keys in configuration.yaml and package
112
+ # files. Disabled by default; only for YAML-only features with no UI/API path.
113
+ enable_yaml_config_editing: bool = Field(False, alias="ENABLE_YAML_CONFIG_EDITING")
114
+
104
115
  @model_validator(mode="after")
105
116
  def _skills_dependency(self) -> "Settings":
106
117
  """Auto-enable skills (resources) when skills-as-tools is on.
@@ -380,6 +380,11 @@ class HomeAssistantSmartMCPServer(EnhancedToolsMixin):
380
380
  "create update modify edit script sequence actions "
381
381
  "new script write save"
382
382
  ),
383
+ "ha_config_set_yaml": (
384
+ "edit yaml configuration.yaml packages template sensor "
385
+ "binary_sensor command_line rest mqtt platform yaml-only "
386
+ "config file modify add remove replace"
387
+ ),
383
388
  }
384
389
 
385
390
  # Description overrides that REPLACE the original description for BM25.
@@ -5,6 +5,7 @@ This module provides tools for retrieving execution traces from Home Assistant
5
5
  to help debug automation and script issues.
6
6
  """
7
7
 
8
+ import json
8
9
  import logging
9
10
  from typing import Annotated, Any
10
11
 
@@ -51,6 +52,31 @@ def register_trace_tools(mcp: Any, client: Any, **kwargs: Any) -> None:
51
52
  le=50,
52
53
  ),
53
54
  ] = 10,
55
+ deduplicate: Annotated[
56
+ bool,
57
+ Field(
58
+ description="Deduplicate variables across action steps (default: True). Set to False to include full variables at every step.",
59
+ default=True,
60
+ ),
61
+ ] = True,
62
+ detailed: Annotated[
63
+ bool,
64
+ Field(
65
+ description="Include extra diagnostic data: logbook entries and context metadata (default: False). Use when standard trace lacks detail for debugging.",
66
+ default=False,
67
+ ),
68
+ ] = False,
69
+ sections: Annotated[
70
+ str | None,
71
+ Field(
72
+ description=(
73
+ "Comma-separated list of trace sections to return. "
74
+ "Valid values: trigger, conditions, actions, config, error, logbook, context. "
75
+ "Omit to return all sections. Example: 'actions' or 'trigger,conditions'."
76
+ ),
77
+ default=None,
78
+ ),
79
+ ] = None,
54
80
  ) -> dict[str, Any]:
55
81
  """
56
82
  Retrieve execution traces for automations and scripts to debug issues.
@@ -73,6 +99,17 @@ def register_trace_tools(mcp: Any, client: Any, **kwargs: Any) -> None:
73
99
  Returns full execution details including trigger info, condition results,
74
100
  action trace with timing, and context variables.
75
101
 
102
+ 3. Get detailed trace with logbook (provide run_id and detailed=True):
103
+ ha_get_automation_traces("automation.motion_light", run_id="1705312800.123456", detailed=True)
104
+ Returns the formatted trace plus logbook entries and context metadata.
105
+ Useful when the standard trace summary doesn't reveal enough for debugging.
106
+ Note: script-style action paths (sequence/, numeric) are always matched
107
+ regardless of this flag.
108
+
109
+ 4. Get full variables without deduplication (provide run_id and deduplicate=False):
110
+ ha_get_automation_traces("automation.motion_light", run_id="1705312800.123456", deduplicate=False)
111
+ Returns the formatted trace with full variables at every action step.
112
+
76
113
  DEBUGGING EXAMPLES:
77
114
 
78
115
  Automation not triggering:
@@ -152,7 +189,11 @@ def register_trace_tools(mcp: Any, client: Any, **kwargs: Any) -> None:
152
189
  ))
153
190
 
154
191
  trace_data = result.get("result", {})
155
- return _format_detailed_trace(automation_id, run_id, trace_data)
192
+ return _format_detailed_trace(
193
+ automation_id, run_id, trace_data,
194
+ deduplicate=deduplicate, detailed=detailed,
195
+ sections=sections,
196
+ )
156
197
  else:
157
198
  # List recent traces
158
199
  result = await ws_client.send_command(
@@ -412,9 +453,12 @@ def _format_trace_list(
412
453
 
413
454
 
414
455
  def _format_detailed_trace(
415
- automation_id: str, run_id: str, trace: dict[str, Any]
456
+ automation_id: str, run_id: str, trace: dict[str, Any],
457
+ *, deduplicate: bool = True, detailed: bool = False,
458
+ sections: str | None = None,
416
459
  ) -> dict[str, Any]:
417
460
  """Format detailed trace for AI consumption."""
461
+ domain = "automation" if automation_id.startswith("automation.") else "script"
418
462
  result: dict[str, Any] = {
419
463
  "success": True,
420
464
  "automation_id": automation_id,
@@ -445,7 +489,11 @@ def _format_detailed_trace(
445
489
  triggers.append(step_info)
446
490
  elif path == "condition" or path.startswith("condition/"):
447
491
  conditions.append(step_info)
448
- elif path == "action" or path.startswith("action/"):
492
+ elif (
493
+ path == "action" or path.startswith("action/")
494
+ or path.startswith("sequence/")
495
+ or (domain == "script" and (path.split("/")[0].isdigit()))
496
+ ):
449
497
  actions.append(step_info)
450
498
 
451
499
  # Sort by timestamp (if available) or path to maintain execution order
@@ -494,9 +542,15 @@ def _format_detailed_trace(
494
542
  condition_results.append(cond_result)
495
543
  result["condition_results"] = condition_results
496
544
 
497
- # Extract action trace
545
+ # Extract action trace with optional variable deduplication.
546
+ # Home Assistant includes the full variable context at every trace step,
547
+ # but variables rarely change between steps. For complex automations with
548
+ # hundreds of steps (e.g., blueprint choose actions), this can produce
549
+ # 100KB+ of duplicated data. When deduplicate=True (default), we only
550
+ # include variables at steps where they actually changed.
498
551
  if actions:
499
552
  action_results = []
553
+ last_vars_fingerprint: str | None = None
500
554
  for action in actions:
501
555
  action_info: dict[str, Any] = {
502
556
  "path": action.get("path"),
@@ -515,14 +569,24 @@ def _format_detailed_trace(
515
569
  if "error" in action:
516
570
  action_info["error"] = action["error"]
517
571
 
518
- # Extract variables if they contain useful debugging info
572
+ # Extract variables, optionally deduplicating across steps.
519
573
  # Check both 'variables' and 'changed_variables'
520
574
  variables = action.get("variables") or action.get("changed_variables", {})
521
575
  if variables and "trigger" not in variables: # Skip trigger vars (already shown)
522
- # Only include non-empty variable sets
523
576
  useful_vars = {k: v for k, v in variables.items() if v is not None}
524
577
  if useful_vars:
525
- action_info["variables"] = useful_vars
578
+ if deduplicate:
579
+ # Compare with previous step using JSON fingerprint
580
+ try:
581
+ fingerprint = json.dumps(useful_vars, sort_keys=True, default=str)
582
+ except (TypeError, ValueError):
583
+ fingerprint = str(useful_vars)
584
+
585
+ if fingerprint != last_vars_fingerprint:
586
+ action_info["variables"] = useful_vars
587
+ last_vars_fingerprint = fingerprint
588
+ else:
589
+ action_info["variables"] = useful_vars
526
590
 
527
591
  # Add child execution info (for nested scripts/automations)
528
592
  if "child_id" in action:
@@ -549,4 +613,30 @@ def _format_detailed_trace(
549
613
  if trace.get("script_execution"):
550
614
  result["script_execution"] = trace["script_execution"]
551
615
 
616
+ # In detailed mode, include logbook entries and context metadata
617
+ # that are essential for debugging but omitted by default to save context.
618
+ if detailed:
619
+ if "logbook_entries" in trace:
620
+ result["logbook_entries"] = trace["logbook_entries"]
621
+ if trace.get("context"):
622
+ result["context"] = trace["context"]
623
+
624
+ # Filter to requested sections if specified.
625
+ # Maps user-facing section names to result dict keys.
626
+ if sections:
627
+ section_key_map = {
628
+ "trigger": "trigger",
629
+ "conditions": "condition_results",
630
+ "actions": "action_trace",
631
+ "config": "config_summary",
632
+ "error": "error",
633
+ "logbook": "logbook_entries",
634
+ "context": "context",
635
+ }
636
+ requested = {s.strip().lower() for s in sections.split(",")}
637
+ keep_keys = {section_key_map[s] for s in requested if s in section_key_map}
638
+ # Always keep metadata keys
639
+ keep_keys |= {"success", "automation_id", "run_id", "timestamp", "state", "script_execution"}
640
+ result = {k: v for k, v in result.items() if k in keep_keys}
641
+
552
642
  return result
@@ -17,6 +17,23 @@ from .util_helpers import add_timezone_metadata, coerce_bool_param, coerce_int_p
17
17
 
18
18
  logger = logging.getLogger(__name__)
19
19
 
20
+ # Fields to keep in compact logbook mode (strips attribute dictionaries
21
+ # and other bulky fields that can cause context exhaustion — see #683)
22
+ COMPACT_LOGBOOK_FIELDS = {"when", "entity_id", "state", "name", "message", "domain", "context_id", "source"}
23
+
24
+
25
+ def _compact_logbook_entries(entries: list[Any]) -> list[dict[str, Any]]:
26
+ """Strip logbook entries to essential fields only.
27
+
28
+ Returns entries with only the fields in COMPACT_LOGBOOK_FIELDS,
29
+ filtering out any non-dict entries.
30
+ """
31
+ return [
32
+ {k: v for k, v in entry.items() if k in COMPACT_LOGBOOK_FIELDS}
33
+ for entry in entries
34
+ if isinstance(entry, dict)
35
+ ]
36
+
20
37
 
21
38
  def register_utility_tools(mcp: Any, client: Any, **kwargs: Any) -> None:
22
39
  """Register Home Assistant utility tools."""
@@ -40,6 +57,7 @@ def register_utility_tools(mcp: Any, client: Any, **kwargs: Any) -> None:
40
57
  end_time: str | None = None,
41
58
  limit: int | str | None = None,
42
59
  offset: int | str = 0,
60
+ compact: bool | str = True,
43
61
  ) -> dict[str, Any]:
44
62
  """
45
63
  Get Home Assistant logbook entries for the specified time period.
@@ -52,6 +70,9 @@ def register_utility_tools(mcp: Any, client: Any, **kwargs: Any) -> None:
52
70
  - end_time: Optional end time in ISO format (defaults to now)
53
71
  - limit: Maximum number of entries to return (default: 50, max: 500)
54
72
  - offset: Number of entries to skip for pagination (default: 0)
73
+ - compact: Return only essential fields per entry (default: True).
74
+ When True, each entry contains only: when, entity_id, state, name, message, domain, context_id.
75
+ Set to False to include full attribute dictionaries and all fields.
55
76
 
56
77
  **Pagination:**
57
78
  When the logbook has more entries than the limit, use offset to get
@@ -68,9 +89,12 @@ def register_utility_tools(mcp: Any, client: Any, **kwargs: Any) -> None:
68
89
  **Example:**
69
90
  - First page: ha_get_logbook(hours_back=24, limit=50, offset=0)
70
91
  - Second page: ha_get_logbook(hours_back=24, limit=50, offset=50)
92
+ - Full details: ha_get_logbook(hours_back=1, compact=False)
71
93
  """
72
94
 
73
95
  # Coerce parameters with string handling for AI tools
96
+ compact_bool = coerce_bool_param(compact, "compact", default=True)
97
+
74
98
  try:
75
99
  hours_back_int = coerce_int_param(
76
100
  hours_back,
@@ -145,6 +169,12 @@ def register_utility_tools(mcp: Any, client: Any, **kwargs: Any) -> None:
145
169
  paginated_entries = response
146
170
  has_more = False
147
171
 
172
+ # In compact mode, strip entries to essential fields only.
173
+ # This prevents full attribute dictionaries from exhausting
174
+ # the LLM context window during debugging workflows.
175
+ if compact_bool and isinstance(paginated_entries, list):
176
+ paginated_entries = _compact_logbook_entries(paginated_entries)
177
+
148
178
  logbook_data = {
149
179
  "success": True,
150
180
  "entries": paginated_entries,
@@ -174,6 +204,8 @@ def register_utility_tools(mcp: Any, client: Any, **kwargs: Any) -> None:
174
204
  param_parts.append(f"entity_id={entity_id}")
175
205
  if end_time:
176
206
  param_parts.append(f"end_time={end_time}")
207
+ if not compact_bool:
208
+ param_parts.append("compact=False")
177
209
 
178
210
  param_str = ", ".join(param_parts)
179
211
  logbook_data["pagination_hint"] = (
@@ -0,0 +1,205 @@
1
+ """
2
+ Managed YAML configuration editing tools for Home Assistant MCP Server.
3
+
4
+ Provides a structured, validated tool for editing YAML configuration files
5
+ (configuration.yaml and package files) for Home Assistant features that exist
6
+ only in YAML and have no REST/WebSocket API equivalent.
7
+
8
+ **Dependency:** Requires the ha_mcp_tools custom component to be installed.
9
+ The tools will gracefully fail with installation instructions if the component is not available.
10
+
11
+ Feature Flag: Set ENABLE_YAML_CONFIG_EDITING=true to enable.
12
+ """
13
+
14
+ import logging
15
+ from typing import Annotated, Any
16
+
17
+ from fastmcp.exceptions import ToolError
18
+ from pydantic import Field
19
+
20
+ from ..config import get_global_settings
21
+ from ..errors import ErrorCode, create_error_response
22
+ from .helpers import exception_to_structured_error, log_tool_usage, raise_tool_error
23
+ from .tools_filesystem import (
24
+ MCP_TOOLS_DOMAIN,
25
+ _assert_mcp_tools_available,
26
+ )
27
+ from .util_helpers import add_timezone_metadata, coerce_bool_param
28
+
29
+ logger = logging.getLogger(__name__)
30
+
31
+
32
+ def register_yaml_config_tools(mcp: Any, client: Any, **kwargs: Any) -> None:
33
+ """Register YAML config editing tools with the MCP server.
34
+
35
+ Requires ENABLE_YAML_CONFIG_EDITING=true.
36
+ """
37
+ settings = get_global_settings()
38
+ if not settings.enable_yaml_config_editing:
39
+ logger.debug(
40
+ "YAML config tools disabled (set ENABLE_YAML_CONFIG_EDITING=true to enable)"
41
+ )
42
+ return
43
+
44
+ logger.info("YAML config editing tools enabled")
45
+
46
+ @mcp.tool(
47
+ tags={"System"},
48
+ annotations={
49
+ "destructiveHint": True,
50
+ "idempotentHint": False,
51
+ "title": "Set YAML Config",
52
+ },
53
+ )
54
+ @log_tool_usage
55
+ async def ha_config_set_yaml(
56
+ yaml_path: Annotated[
57
+ str,
58
+ Field(
59
+ description=(
60
+ "Top-level YAML key to modify (e.g., 'template', 'sensor', "
61
+ "'input_boolean'). Only whitelisted keys are allowed."
62
+ ),
63
+ ),
64
+ ],
65
+ action: Annotated[
66
+ str,
67
+ Field(
68
+ description=(
69
+ "Action to perform: 'add' (insert/merge content under key), "
70
+ "'replace' (overwrite key with new content), or "
71
+ "'remove' (delete the key entirely)."
72
+ ),
73
+ ),
74
+ ],
75
+ content: Annotated[
76
+ str | None,
77
+ Field(
78
+ default=None,
79
+ description=(
80
+ "YAML content for the value under yaml_path. Required for "
81
+ "'add' and 'replace' actions. Must be valid YAML."
82
+ ),
83
+ ),
84
+ ] = None,
85
+ file: Annotated[
86
+ str,
87
+ Field(
88
+ default="configuration.yaml",
89
+ description=(
90
+ "Relative path to the YAML config file. Defaults to "
91
+ "'configuration.yaml'. Also supports 'packages/*.yaml'."
92
+ ),
93
+ ),
94
+ ] = "configuration.yaml",
95
+ backup: Annotated[
96
+ bool | str,
97
+ Field(
98
+ default=True,
99
+ description=(
100
+ "Create a backup before editing. Defaults to True. "
101
+ "Backups are saved to www/yaml_backups/."
102
+ ),
103
+ ),
104
+ ] = True,
105
+ ) -> dict[str, Any]:
106
+ """Add, replace, or remove a top-level key in configuration.yaml or package files.
107
+
108
+ IMPORTANT: Only use when NO UI or API alternative exists. Prefer:
109
+ - Template sensors -> ha_config_set_helper (Template Helper)
110
+ - Automations -> ha_config_set_automation
111
+ - Scripts -> ha_config_set_script
112
+ - Input helpers -> ha_config_set_helper
113
+ - Scenes -> ha_config_set_scene
114
+
115
+ This tool is for YAML-only features with no UI/API path (e.g.,
116
+ command_line sensors, platform-based MQTT sensors in YAML, rest
117
+ sensors defined in packages).
118
+
119
+ Safeguards: file backup, YAML validation, top-level key whitelist,
120
+ path traversal blocking, post-edit config check.
121
+
122
+ IMPORTANT: Check 'post_action' in the response. Most keys require
123
+ a full HA restart ('restart_required'). Only template, mqtt, and
124
+ group support reload ('reload_available' with 'reload_service').
125
+
126
+ Note: YAML comments are not preserved after editing. The backup
127
+ retains the original file with comments intact.
128
+ """
129
+ try:
130
+ # Validate action
131
+ valid_actions = ("add", "replace", "remove")
132
+ if action not in valid_actions:
133
+ raise_tool_error(
134
+ create_error_response(
135
+ ErrorCode.VALIDATION_INVALID_PARAMETER,
136
+ f"Invalid action '{action}'. Must be one of: {', '.join(valid_actions)}",
137
+ suggestions=[
138
+ "Use action='add' to insert content under a key",
139
+ "Use action='replace' to overwrite a key's content",
140
+ "Use action='remove' to delete a key entirely",
141
+ ],
142
+ )
143
+ )
144
+
145
+ # Validate content is provided for add/replace
146
+ if action in ("add", "replace") and not content:
147
+ raise_tool_error(
148
+ create_error_response(
149
+ ErrorCode.VALIDATION_INVALID_PARAMETER,
150
+ f"'content' is required for action '{action}'.",
151
+ suggestions=[
152
+ "Provide valid YAML content to insert or replace."
153
+ ],
154
+ )
155
+ )
156
+
157
+ # Coerce boolean parameter
158
+ backup_bool = coerce_bool_param(backup, "backup", default=True)
159
+
160
+ # Check if custom component is available
161
+ await _assert_mcp_tools_available(client)
162
+
163
+ # Build service data
164
+ service_data: dict[str, Any] = {
165
+ "file": file,
166
+ "action": action,
167
+ "yaml_path": yaml_path,
168
+ "backup": backup_bool,
169
+ }
170
+ if content is not None:
171
+ service_data["content"] = content
172
+
173
+ # Call the custom component service
174
+ result = await client.call_service(
175
+ MCP_TOOLS_DOMAIN,
176
+ "edit_yaml_config",
177
+ service_data,
178
+ return_response=True,
179
+ )
180
+
181
+ if isinstance(result, dict):
182
+ if not result.get("success", True):
183
+ raise_tool_error(result)
184
+ return await add_timezone_metadata(client, result)
185
+
186
+ raise_tool_error(
187
+ create_error_response(
188
+ ErrorCode.SERVICE_CALL_FAILED,
189
+ "Unexpected response format from YAML config service",
190
+ context={"file": file},
191
+ )
192
+ )
193
+
194
+ except ToolError:
195
+ raise
196
+ except Exception as e:
197
+ exception_to_structured_error(
198
+ e,
199
+ context={
200
+ "tool": "ha_config_set_yaml",
201
+ "file": file,
202
+ "action": action,
203
+ "yaml_path": yaml_path,
204
+ },
205
+ )
@@ -46,6 +46,7 @@ DEFAULT_PINNED_TOOLS: tuple[str, ...] = (
46
46
  "ha_search_entities",
47
47
  "ha_config_get_automation",
48
48
  "ha_config_set_automation",
49
+ "ha_config_set_yaml",
49
50
  )
50
51
 
51
52
  # Tool name patterns that indicate delete/remove operations
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ha-mcp-dev
3
- Version: 7.1.0.dev308
3
+ Version: 7.1.0.dev310
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
@@ -18,7 +18,7 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
18
18
  Requires-Python: <3.14,>=3.13
19
19
  Description-Content-Type: text/markdown
20
20
  License-File: LICENSE
21
- Requires-Dist: fastmcp==3.1.1
21
+ Requires-Dist: fastmcp==3.2.0
22
22
  Requires-Dist: httpx[socks]==0.28.1
23
23
  Requires-Dist: pydantic==2.12.5
24
24
  Requires-Dist: python-dotenv==1.2.2
@@ -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-93-blue" alt="95+ Tools">
40
+ <img src="https://img.shields.io/badge/tools-94-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>
@@ -160,7 +160,7 @@ Spend less time configuring, more time enjoying your smart home.
160
160
  <details>
161
161
  <!-- TOOLS_TABLE_START -->
162
162
 
163
- <summary><b>Complete Tool List (93 tools)</b></summary>
163
+ <summary><b>Complete Tool List (94 tools)</b></summary>
164
164
 
165
165
  | Category | Tools |
166
166
  |----------|-------|
@@ -183,7 +183,7 @@ Spend less time configuring, more time enjoying your smart home.
183
183
  | **Scripts** | `ha_config_get_script`, `ha_config_remove_script`, `ha_config_set_script` |
184
184
  | **Search & Discovery** | `ha_deep_search`, `ha_get_overview`, `ha_get_state`, `ha_get_states`, `ha_search_entities` |
185
185
  | **Service & Device Control** | `ha_bulk_control`, `ha_call_service`, `ha_get_bulk_status`, `ha_get_operation_status`, `ha_list_services` |
186
- | **System** | `ha_backup_create`, `ha_backup_restore`, `ha_check_config`, `ha_get_system_health`, `ha_get_updates`, `ha_reload_core`, `ha_restart` |
186
+ | **System** | `ha_backup_create`, `ha_backup_restore`, `ha_check_config`, `ha_config_set_yaml`, `ha_get_system_health`, `ha_get_updates`, `ha_reload_core`, `ha_restart` |
187
187
  | **Todo Lists** | `ha_add_todo_item`, `ha_get_todo`, `ha_remove_todo_item`, `ha_update_todo_item` |
188
188
  | **Utilities** | `ha_eval_template`, `ha_install_mcp_tools`, `ha_report_issue` |
189
189
  | **Zones** | `ha_get_zone`, `ha_remove_zone`, `ha_set_zone` |
@@ -76,6 +76,7 @@ src/ha_mcp/tools/tools_traces.py
76
76
  src/ha_mcp/tools/tools_updates.py
77
77
  src/ha_mcp/tools/tools_utility.py
78
78
  src/ha_mcp/tools/tools_voice_assistant.py
79
+ src/ha_mcp/tools/tools_yaml_config.py
79
80
  src/ha_mcp/tools/tools_zones.py
80
81
  src/ha_mcp/tools/util_helpers.py
81
82
  src/ha_mcp/transforms/__init__.py
@@ -1,4 +1,4 @@
1
- fastmcp==3.1.1
1
+ fastmcp==3.2.0
2
2
  httpx[socks]==0.28.1
3
3
  pydantic==2.12.5
4
4
  python-dotenv==1.2.2