ha-mcp-dev 7.7.0.dev695__tar.gz → 7.7.0.dev696__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 (143) hide show
  1. {ha_mcp_dev-7.7.0.dev695/src/ha_mcp_dev.egg-info → ha_mcp_dev-7.7.0.dev696}/PKG-INFO +1 -1
  2. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/pyproject.toml +1 -1
  3. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/tools_config_helpers.py +60 -21
  4. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696/src/ha_mcp_dev.egg-info}/PKG-INFO +1 -1
  5. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/LICENSE +0 -0
  6. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/MANIFEST.in +0 -0
  7. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/README.md +0 -0
  8. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/setup.cfg +0 -0
  9. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/__init__.py +0 -0
  10. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/__main__.py +0 -0
  11. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/_pypi_marker +0 -0
  12. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/_version.py +0 -0
  13. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/auth/__init__.py +0 -0
  14. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/auth/consent_form.py +0 -0
  15. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/auth/provider.py +0 -0
  16. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/backup_manager.py +0 -0
  17. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/client/__init__.py +0 -0
  18. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/client/rest_client.py +0 -0
  19. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/client/supervisor_client.py +0 -0
  20. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/client/websocket_client.py +0 -0
  21. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/client/websocket_listener.py +0 -0
  22. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/config.py +0 -0
  23. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/dashboard_screenshot/__init__.py +0 -0
  24. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/dashboard_screenshot/capture.py +0 -0
  25. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/dashboard_screenshot/provision.py +0 -0
  26. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/errors.py +0 -0
  27. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/policy/__init__.py +0 -0
  28. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/policy/approval_queue.py +0 -0
  29. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/policy/evaluator.py +0 -0
  30. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/policy/handlers.py +0 -0
  31. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/policy/middleware.py +0 -0
  32. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/policy/model.py +0 -0
  33. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/policy/persistence.py +0 -0
  34. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/policy/value_sources.py +0 -0
  35. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/py.typed +0 -0
  36. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/read_only.py +0 -0
  37. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/resources/skills-vendor/.claude/settings.json +0 -0
  38. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/resources/skills-vendor/.claude-plugin/marketplace.json +0 -0
  39. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/resources/skills-vendor/.claude-plugin/plugin.json +0 -0
  40. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/resources/skills-vendor/.github/ISSUE_TEMPLATE/skill-rca.md +0 -0
  41. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/resources/skills-vendor/.github/pull_request_template.md +0 -0
  42. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/resources/skills-vendor/AGENTS.md +0 -0
  43. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/resources/skills-vendor/CLAUDE.md +0 -0
  44. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/resources/skills-vendor/CONTRIBUTING.md +0 -0
  45. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/resources/skills-vendor/LICENSE +0 -0
  46. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/resources/skills-vendor/README.md +0 -0
  47. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/SKILL.md +0 -0
  48. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/evals/evals.json +0 -0
  49. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/automation-patterns.md +0 -0
  50. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-cards.md +0 -0
  51. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-guide.md +0 -0
  52. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/device-control.md +0 -0
  53. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/domain-docs.md +0 -0
  54. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/examples.yaml +0 -0
  55. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/helper-selection.md +0 -0
  56. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/safe-refactoring.md +0 -0
  57. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/template-guidelines.md +0 -0
  58. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/yaml-only-integrations.md +0 -0
  59. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/server.py +0 -0
  60. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/settings.css +0 -0
  61. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/settings.js +0 -0
  62. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/settings_ui.py +0 -0
  63. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/smoke_test.py +0 -0
  64. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/stdio_settings_sidecar.py +0 -0
  65. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/__init__.py +0 -0
  66. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/auto_backup.py +0 -0
  67. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/backup.py +0 -0
  68. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/best_practice_checker.py +0 -0
  69. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/config_entry_flow.py +0 -0
  70. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/device_control.py +0 -0
  71. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/enhanced.py +0 -0
  72. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/helpers.py +0 -0
  73. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/reference_validator.py +0 -0
  74. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/registry.py +0 -0
  75. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/smart_search/__init__.py +0 -0
  76. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/smart_search/_base.py +0 -0
  77. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/smart_search/_config.py +0 -0
  78. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/smart_search/_deep.py +0 -0
  79. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/smart_search/_entities.py +0 -0
  80. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/smart_search/_fetch.py +0 -0
  81. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/smart_search/_overview.py +0 -0
  82. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/smart_search/_scenes.py +0 -0
  83. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/smart_search/_scoring.py +0 -0
  84. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/tool_search_hint_middleware.py +0 -0
  85. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/tools_addons.py +0 -0
  86. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/tools_areas.py +0 -0
  87. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/tools_blueprints.py +0 -0
  88. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/tools_bug_report.py +0 -0
  89. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/tools_calendar.py +0 -0
  90. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/tools_camera.py +0 -0
  91. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/tools_categories.py +0 -0
  92. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/tools_code.py +0 -0
  93. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/tools_config_automations.py +0 -0
  94. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/tools_config_dashboards.py +0 -0
  95. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/tools_config_scenes.py +0 -0
  96. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/tools_config_scripts.py +0 -0
  97. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/tools_dashboard_screenshot.py +0 -0
  98. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/tools_energy.py +0 -0
  99. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/tools_entities.py +0 -0
  100. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/tools_filesystem.py +0 -0
  101. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/tools_groups.py +0 -0
  102. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/tools_hacs.py +0 -0
  103. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/tools_history.py +0 -0
  104. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/tools_integrations.py +0 -0
  105. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/tools_labels.py +0 -0
  106. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/tools_mcp_component.py +0 -0
  107. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/tools_registry.py +0 -0
  108. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/tools_resources.py +0 -0
  109. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/tools_search.py +0 -0
  110. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/tools_service.py +0 -0
  111. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/tools_services.py +0 -0
  112. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/tools_system.py +0 -0
  113. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/tools_themes.py +0 -0
  114. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/tools_todo.py +0 -0
  115. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/tools_traces.py +0 -0
  116. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/tools_updates.py +0 -0
  117. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/tools_utility.py +0 -0
  118. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/tools_voice_assistant.py +0 -0
  119. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/tools_yaml_config.py +0 -0
  120. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/tools_zones.py +0 -0
  121. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/util_helpers.py +0 -0
  122. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/tools/validation_middleware.py +0 -0
  123. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/transforms/__init__.py +0 -0
  124. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/transforms/categorized_search.py +0 -0
  125. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/transforms/lite_docstrings.py +0 -0
  126. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/utils/__init__.py +0 -0
  127. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/utils/config_hash.py +0 -0
  128. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/utils/data_paths.py +0 -0
  129. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/utils/domain_handlers.py +0 -0
  130. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/utils/fuzzy_search.py +0 -0
  131. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/utils/kill_signal_diagnostics.py +0 -0
  132. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/utils/operation_manager.py +0 -0
  133. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/utils/python_sandbox.py +0 -0
  134. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/utils/skill_loader.py +0 -0
  135. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp/utils/usage_logger.py +0 -0
  136. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp_dev.egg-info/SOURCES.txt +0 -0
  137. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp_dev.egg-info/dependency_links.txt +0 -0
  138. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp_dev.egg-info/entry_points.txt +0 -0
  139. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp_dev.egg-info/requires.txt +0 -0
  140. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/src/ha_mcp_dev.egg-info/top_level.txt +0 -0
  141. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/tests/__init__.py +0 -0
  142. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/tests/test_constants.py +0 -0
  143. {ha_mcp_dev-7.7.0.dev695 → ha_mcp_dev-7.7.0.dev696}/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.7.0.dev695
3
+ Version: 7.7.0.dev696
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
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "ha-mcp-dev"
7
- version = "7.7.0.dev695"
7
+ version = "7.7.0.dev696"
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"
@@ -737,12 +737,15 @@ def _validate_applicable_params(
737
737
 
738
738
  if helper_type in FLOW_HELPER_TYPES:
739
739
  # Flow types accept `config` (handled before this call) plus
740
- # cross-cutting params (name/helper_id/area_id/labels/category/wait).
741
- # Any simple-helper-typed param passed here is inapplicable.
740
+ # cross-cutting params (name/helper_id/area_id/labels/category/icon/wait).
741
+ # `icon` is applied to the resulting entity(ies) via the entity registry
742
+ # (like area_id/labels), so it is allowed even though the config-flow
743
+ # form has no icon field. Any other simple-helper-typed param passed
744
+ # here is inapplicable.
742
745
  inapplicable.extend(
743
746
  param_name
744
747
  for param_name in _ALL_TYPED_PARAMS
745
- if passed.get(param_name) is not None
748
+ if param_name != "icon" and passed.get(param_name) is not None
746
749
  )
747
750
  else:
748
751
  applicable = _TYPE_TYPED_PARAMS.get(helper_type, frozenset())
@@ -760,7 +763,7 @@ def _validate_applicable_params(
760
763
  if helper_type in FLOW_HELPER_TYPES:
761
764
  applicable_msg = (
762
765
  "config (see data_schema on a validation error for the field set), "
763
- "name, helper_id, area_id, labels, category, wait"
766
+ "name, helper_id, area_id, labels, category, icon, wait"
764
767
  )
765
768
  else:
766
769
  type_specific = sorted(_TYPE_TYPED_PARAMS.get(helper_type, frozenset()))
@@ -1453,7 +1456,11 @@ async def _get_entities_for_config_entry(
1453
1456
 
1454
1457
 
1455
1458
  async def _entity_registry_update_coro(
1456
- client: Any, entity_id: str, area_id: str | None, labels: list[str] | None
1459
+ client: Any,
1460
+ entity_id: str,
1461
+ area_id: str | None,
1462
+ labels: list[str] | None,
1463
+ icon: str | None = None,
1457
1464
  ) -> Any:
1458
1465
  """Build and send a config/entity_registry/update WS message."""
1459
1466
  update_message: dict[str, Any] = {
@@ -1464,6 +1471,8 @@ async def _entity_registry_update_coro(
1464
1471
  update_message["area_id"] = area_id if area_id else None
1465
1472
  if labels is not None:
1466
1473
  update_message["labels"] = labels
1474
+ if icon is not None:
1475
+ update_message["icon"] = icon if icon else None
1467
1476
  return await client.send_websocket_message(update_message)
1468
1477
 
1469
1478
 
@@ -1482,6 +1491,7 @@ def _process_reg_update_result(
1482
1491
  reg_result: Any,
1483
1492
  area_id: str | None,
1484
1493
  labels: list[str] | None,
1494
+ icon: str | None,
1485
1495
  applied: dict[str, Any],
1486
1496
  entity_id: str,
1487
1497
  warnings: list[str],
@@ -1495,9 +1505,21 @@ def _process_reg_update_result(
1495
1505
  applied["area_id"] = area_id if area_id else None
1496
1506
  if labels is not None:
1497
1507
  applied["labels"] = labels
1508
+ if icon is not None:
1509
+ applied["icon"] = icon if icon else None
1498
1510
  else:
1511
+ # area_id/labels/icon share one WS message, so a rejection of any
1512
+ # one sinks the others. Name the batched fields so the caller can
1513
+ # tell which touchups didn't land instead of guessing.
1514
+ sent_fields = [
1515
+ f
1516
+ for f, v in (("area_id", area_id), ("labels", labels), ("icon", icon))
1517
+ if v is not None
1518
+ ]
1519
+ field_note = f" (fields: {', '.join(sent_fields)})" if sent_fields else ""
1499
1520
  warnings.append(
1500
- f"{entity_id}: entity registry update failed: {_ws_error_msg(reg_result)}"
1521
+ f"{entity_id}: entity registry update failed{field_note}: "
1522
+ f"{_ws_error_msg(reg_result)}"
1501
1523
  )
1502
1524
 
1503
1525
 
@@ -1523,9 +1545,10 @@ async def _apply_registry_updates_to_entity(
1523
1545
  area_id: str | None,
1524
1546
  labels: list[str] | None,
1525
1547
  category: str | None,
1548
+ icon: str | None,
1526
1549
  warnings: list[str],
1527
1550
  ) -> dict[str, Any]:
1528
- """Apply area_id/labels (single WS call) and category (shared helper) to one entity.
1551
+ """Apply area_id/labels/icon (single WS call) and category (shared helper) to one entity.
1529
1552
 
1530
1553
  Appends human-readable warning strings to `warnings` on any failure.
1531
1554
  Returns a small dict summarizing what was applied (for result building).
@@ -1536,13 +1559,13 @@ async def _apply_registry_updates_to_entity(
1536
1559
  # `is not None` distinguishes "not provided" from "explicit clear" (empty
1537
1560
  # string / empty list). A transient raise on either call is captured via
1538
1561
  # return_exceptions so a multi-entity flow helper can still report partial success.
1539
- needs_registry = area_id is not None or labels is not None
1562
+ needs_registry = area_id is not None or labels is not None or icon is not None
1540
1563
  needs_category = bool(category)
1541
1564
  if not (needs_registry or needs_category):
1542
1565
  return applied
1543
1566
 
1544
1567
  reg_task = (
1545
- _entity_registry_update_coro(client, entity_id, area_id, labels)
1568
+ _entity_registry_update_coro(client, entity_id, area_id, labels, icon)
1546
1569
  if needs_registry
1547
1570
  else None
1548
1571
  )
@@ -1557,7 +1580,7 @@ async def _apply_registry_updates_to_entity(
1557
1580
  cat_result = raw_results.pop(0) if needs_category else None
1558
1581
 
1559
1582
  _process_reg_update_result(
1560
- reg_result, area_id, labels, applied, entity_id, warnings
1583
+ reg_result, area_id, labels, icon, applied, entity_id, warnings
1561
1584
  )
1562
1585
  _process_cat_apply_result(cat_result, entity_id, applied, warnings)
1563
1586
  return applied
@@ -1772,31 +1795,45 @@ async def _apply_flow_registry_updates(
1772
1795
  area_id: str | None,
1773
1796
  labels_list: list[str] | None,
1774
1797
  category: str | None,
1798
+ icon: str | None,
1775
1799
  extras: dict[str, Any],
1776
1800
  warnings: list[str],
1777
1801
  ) -> None:
1778
- """Apply area/labels/category to every entity from a flow helper, in parallel."""
1802
+ """Apply area/labels/category/icon to every entity from a flow helper, in parallel."""
1779
1803
  if not (
1780
1804
  entity_ids
1781
- and (area_id is not None or labels_list is not None or category is not None)
1805
+ and (
1806
+ area_id is not None
1807
+ or labels_list is not None
1808
+ or category is not None
1809
+ or icon is not None
1810
+ )
1782
1811
  ):
1783
1812
  return
1784
1813
  applied_per_entity = list(
1785
1814
  await asyncio.gather(
1786
1815
  *(
1787
1816
  _apply_registry_updates_to_entity(
1788
- client, eid, area_id, labels_list, category, warnings
1817
+ client, eid, area_id, labels_list, category, icon, warnings
1789
1818
  )
1790
1819
  for eid in entity_ids
1791
1820
  )
1792
1821
  )
1793
1822
  )
1794
- if area_id is not None:
1823
+ # Echo a top-level convenience key only when it was actually applied to at
1824
+ # least one entity. The per-entity ``applied`` dicts are the source of
1825
+ # truth — a failed entity_registry/update leaves its key out and records a
1826
+ # warning instead — so echoing straight from the inputs would assert
1827
+ # success that the accompanying warnings contradict.
1828
+ applied_keys = {k for entry in applied_per_entity for k in entry}
1829
+ if area_id is not None and "area_id" in applied_keys:
1795
1830
  extras["area_id"] = area_id if area_id else None
1796
- if labels_list is not None:
1831
+ if labels_list is not None and "labels" in applied_keys:
1797
1832
  extras["labels"] = labels_list
1798
- if category:
1833
+ if category and "category" in applied_keys:
1799
1834
  extras["category"] = category
1835
+ if icon is not None and "icon" in applied_keys:
1836
+ extras["icon"] = icon if icon else None
1800
1837
  extras["applied"] = applied_per_entity
1801
1838
 
1802
1839
 
@@ -1810,16 +1847,17 @@ async def _handle_flow_helper(
1810
1847
  labels: str | list[str] | None,
1811
1848
  category: str | None,
1812
1849
  wait: bool,
1850
+ icon: str | None = None,
1813
1851
  action: str | None = None,
1814
1852
  ) -> dict[str, Any]:
1815
1853
  """Create or update a flow-based helper and apply registry updates to all entities.
1816
1854
 
1817
1855
  Routes between create_flow_helper and update_flow_helper based on helper_id,
1818
1856
  then resolves the resulting config_entry_id to its entity(ies) and applies
1819
- area_id / labels / category across the full set.
1857
+ area_id / labels / category / icon across the full set.
1820
1858
 
1821
- For utility_meter with tariffs, this means the same label/area is applied
1822
- to every tariff sensor (and the select entity) uniformly.
1859
+ For utility_meter with tariffs, this means the same label/area/icon is
1860
+ applied to every tariff sensor (and the select entity) uniformly.
1823
1861
 
1824
1862
  `action` may be passed by the caller (Bug 11 explicit-intent path) — when
1825
1863
  None, falls back to the legacy implicit discriminator (presence of
@@ -1903,7 +1941,7 @@ async def _handle_flow_helper(
1903
1941
  extras["updated"] = True
1904
1942
 
1905
1943
  await _apply_flow_registry_updates(
1906
- client, entity_ids, area_id, labels_list, category, extras, warnings
1944
+ client, entity_ids, area_id, labels_list, category, icon, extras, warnings
1907
1945
  )
1908
1946
 
1909
1947
  return _helper_response(
@@ -3886,7 +3924,8 @@ class HelperConfigTools:
3886
3924
  labels,
3887
3925
  category,
3888
3926
  wait,
3889
- action,
3927
+ icon=icon,
3928
+ action=action,
3890
3929
  )
3891
3930
  _attach_helper_skill(flow_response, MandatoryBPS)
3892
3931
  return flow_response
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ha-mcp-dev
3
- Version: 7.7.0.dev695
3
+ Version: 7.7.0.dev696
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