ha-mcp-dev 7.5.0.dev532__tar.gz → 7.5.0.dev534__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 (111) hide show
  1. {ha_mcp_dev-7.5.0.dev532/src/ha_mcp_dev.egg-info → ha_mcp_dev-7.5.0.dev534}/PKG-INFO +1 -1
  2. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/pyproject.toml +1 -1
  3. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/tools/smart_search.py +3 -7
  4. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/tools/tools_config_dashboards.py +4 -6
  5. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/tools/tools_config_scripts.py +19 -1
  6. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/tools/tools_yaml_config.py +2 -15
  7. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534/src/ha_mcp_dev.egg-info}/PKG-INFO +1 -1
  8. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/LICENSE +0 -0
  9. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/MANIFEST.in +0 -0
  10. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/README.md +0 -0
  11. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/setup.cfg +0 -0
  12. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/__init__.py +0 -0
  13. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/__main__.py +0 -0
  14. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/_pypi_marker +0 -0
  15. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/_version.py +0 -0
  16. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/auth/__init__.py +0 -0
  17. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/auth/consent_form.py +0 -0
  18. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/auth/provider.py +0 -0
  19. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/client/__init__.py +0 -0
  20. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/client/rest_client.py +0 -0
  21. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/client/supervisor_client.py +0 -0
  22. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/client/websocket_client.py +0 -0
  23. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/client/websocket_listener.py +0 -0
  24. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/config.py +0 -0
  25. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/errors.py +0 -0
  26. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/py.typed +0 -0
  27. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/resources/skills-vendor/.claude/settings.json +0 -0
  28. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/resources/skills-vendor/.claude-plugin/marketplace.json +0 -0
  29. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/resources/skills-vendor/.claude-plugin/plugin.json +0 -0
  30. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/resources/skills-vendor/.github/ISSUE_TEMPLATE/skill-rca.md +0 -0
  31. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/resources/skills-vendor/AGENTS.md +0 -0
  32. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/resources/skills-vendor/CLAUDE.md +0 -0
  33. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/resources/skills-vendor/CONTRIBUTING.md +0 -0
  34. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/resources/skills-vendor/LICENSE +0 -0
  35. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/resources/skills-vendor/README.md +0 -0
  36. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/SKILL.md +0 -0
  37. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/evals/evals.json +0 -0
  38. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/automation-patterns.md +0 -0
  39. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-cards.md +0 -0
  40. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-guide.md +0 -0
  41. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/device-control.md +0 -0
  42. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/domain-docs.md +0 -0
  43. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/examples.yaml +0 -0
  44. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/helper-selection.md +0 -0
  45. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/safe-refactoring.md +0 -0
  46. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/template-guidelines.md +0 -0
  47. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/server.py +0 -0
  48. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/settings_ui.py +0 -0
  49. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/smoke_test.py +0 -0
  50. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/tools/__init__.py +0 -0
  51. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/tools/backup.py +0 -0
  52. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/tools/best_practice_checker.py +0 -0
  53. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/tools/device_control.py +0 -0
  54. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/tools/enhanced.py +0 -0
  55. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/tools/helpers.py +0 -0
  56. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/tools/reference_validator.py +0 -0
  57. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/tools/registry.py +0 -0
  58. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/tools/tools_addons.py +0 -0
  59. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/tools/tools_areas.py +0 -0
  60. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/tools/tools_blueprints.py +0 -0
  61. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/tools/tools_bug_report.py +0 -0
  62. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/tools/tools_calendar.py +0 -0
  63. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/tools/tools_camera.py +0 -0
  64. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/tools/tools_categories.py +0 -0
  65. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/tools/tools_code.py +0 -0
  66. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/tools/tools_config_automations.py +0 -0
  67. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/tools/tools_config_entry_flow.py +0 -0
  68. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/tools/tools_config_helpers.py +0 -0
  69. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/tools/tools_config_scenes.py +0 -0
  70. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/tools/tools_energy.py +0 -0
  71. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/tools/tools_entities.py +0 -0
  72. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/tools/tools_filesystem.py +0 -0
  73. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/tools/tools_groups.py +0 -0
  74. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/tools/tools_hacs.py +0 -0
  75. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/tools/tools_history.py +0 -0
  76. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/tools/tools_integrations.py +0 -0
  77. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/tools/tools_labels.py +0 -0
  78. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/tools/tools_mcp_component.py +0 -0
  79. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/tools/tools_registry.py +0 -0
  80. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/tools/tools_resources.py +0 -0
  81. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/tools/tools_search.py +0 -0
  82. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/tools/tools_service.py +0 -0
  83. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/tools/tools_services.py +0 -0
  84. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/tools/tools_system.py +0 -0
  85. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/tools/tools_todo.py +0 -0
  86. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/tools/tools_traces.py +0 -0
  87. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/tools/tools_updates.py +0 -0
  88. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/tools/tools_utility.py +0 -0
  89. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/tools/tools_voice_assistant.py +0 -0
  90. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/tools/tools_zones.py +0 -0
  91. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/tools/util_helpers.py +0 -0
  92. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/transforms/__init__.py +0 -0
  93. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/transforms/categorized_search.py +0 -0
  94. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/transforms/lite_docstrings.py +0 -0
  95. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/utils/__init__.py +0 -0
  96. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/utils/config_hash.py +0 -0
  97. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/utils/data_paths.py +0 -0
  98. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/utils/domain_handlers.py +0 -0
  99. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/utils/fuzzy_search.py +0 -0
  100. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/utils/kill_signal_diagnostics.py +0 -0
  101. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/utils/operation_manager.py +0 -0
  102. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/utils/python_sandbox.py +0 -0
  103. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp/utils/usage_logger.py +0 -0
  104. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp_dev.egg-info/SOURCES.txt +0 -0
  105. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp_dev.egg-info/dependency_links.txt +0 -0
  106. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp_dev.egg-info/entry_points.txt +0 -0
  107. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp_dev.egg-info/requires.txt +0 -0
  108. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/src/ha_mcp_dev.egg-info/top_level.txt +0 -0
  109. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/tests/__init__.py +0 -0
  110. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/tests/test_constants.py +0 -0
  111. {ha_mcp_dev-7.5.0.dev532 → ha_mcp_dev-7.5.0.dev534}/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.5.0.dev532
3
+ Version: 7.5.0.dev534
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.5.0.dev532"
7
+ version = "7.5.0.dev534"
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"
@@ -22,6 +22,7 @@ from ..utils.fuzzy_search import (
22
22
  tokenize,
23
23
  )
24
24
  from .helpers import exception_to_structured_error, safe_info, safe_progress
25
+ from .tools_config_dashboards import fetch_dashboards_list
25
26
 
26
27
  logger = logging.getLogger(__name__)
27
28
 
@@ -1773,14 +1774,9 @@ class SmartSearchTools:
1773
1774
  if "dashboard" in search_types:
1774
1775
  try:
1775
1776
  # List all storage-mode dashboards
1776
- dash_list_resp = await self.client.send_websocket_message(
1777
- {"type": "lovelace/dashboards/list"}
1777
+ dashboard_entries: list[dict[str, Any]] = (
1778
+ await fetch_dashboards_list(self.client) or []
1778
1779
  )
1779
- dashboard_entries: list[dict[str, Any]] = []
1780
- if isinstance(dash_list_resp, dict) and dash_list_resp.get(
1781
- "success"
1782
- ):
1783
- dashboard_entries = dash_list_resp.get("result", [])
1784
1780
 
1785
1781
  # Build list of dashboards to search (include default)
1786
1782
  dashboards_to_search: list[tuple[str, str]] = [
@@ -323,7 +323,7 @@ def _should_lazy_resolve(error_msg: str) -> bool:
323
323
  return _LAZY_RESOLVE_TRIGGER in error_msg
324
324
 
325
325
 
326
- async def _fetch_dashboards_list(
326
+ async def fetch_dashboards_list(
327
327
  client: Any,
328
328
  ) -> list[dict[str, Any]] | None:
329
329
  """Fetch and normalise the lovelace/dashboards/list WebSocket response.
@@ -381,7 +381,7 @@ async def _resolve_dashboard(
381
381
  to the registry id before issuing the delete. Discards
382
382
  ``dashboards``.
383
383
  """
384
- dashboards = await _fetch_dashboards_list(client)
384
+ dashboards = await fetch_dashboards_list(client)
385
385
  if dashboards is None:
386
386
  return None, None
387
387
 
@@ -598,7 +598,7 @@ def register_config_dashboard_tools(mcp: Any, client: Any, **kwargs: Any) -> Non
598
598
  try:
599
599
  # List mode
600
600
  if list_only:
601
- dashboards = await _fetch_dashboards_list(client) or []
601
+ dashboards = await fetch_dashboards_list(client) or []
602
602
  return {
603
603
  "success": True,
604
604
  "action": "list",
@@ -1249,9 +1249,7 @@ def register_config_dashboard_tools(mcp: Any, client: Any, **kwargs: Any) -> Non
1249
1249
  if pre_fetched_dashboards is not None:
1250
1250
  existing_dashboards = pre_fetched_dashboards
1251
1251
  else:
1252
- existing_dashboards = (
1253
- await _fetch_dashboards_list(client) or []
1254
- )
1252
+ existing_dashboards = await fetch_dashboards_list(client) or []
1255
1253
  dashboard_exists = any(
1256
1254
  d.get("url_path") == url_path for d in existing_dashboards
1257
1255
  )
@@ -96,6 +96,8 @@ class ConfigScriptTools:
96
96
 
97
97
  The returned `config_hash` is stable across consecutive reads of an unchanged config — `compute_config_hash` documents the underlying contract.
98
98
 
99
+ The returned `script_id` is the canonical storage key resolved by the REST client (matching what `ha_config_set_script` / `ha_config_remove_script` expect), falling back to the input identifier on the rare path where the REST envelope omits it.
100
+
99
101
  EXAMPLES:
100
102
  - Get script: ha_config_get_script("morning_routine")
101
103
  - Get script: ha_config_get_script("backup_script")
@@ -128,10 +130,26 @@ class ConfigScriptTools:
128
130
  if cat_id:
129
131
  config_result["category"] = cat_id
130
132
 
133
+ # Issue #1334: return the canonical storage key from the
134
+ # rest_client envelope so callers can thread the result into
135
+ # subsequent ha_config_*_script calls without re-resolving.
136
+ # Falls back to the input when the rest_client response omits
137
+ # the key — a contract violation that we surface via warning
138
+ # rather than mask silently.
139
+ canonical_id = config_result.get("script_id")
140
+ if canonical_id is None:
141
+ logger.warning(
142
+ "get_script_config envelope missing 'script_id' for "
143
+ "input %r; falling back to caller input. This indicates "
144
+ "a rest_client contract violation.",
145
+ script_id,
146
+ )
147
+ canonical_id = script_id
148
+
131
149
  return {
132
150
  "success": True,
133
151
  "action": "get",
134
- "script_id": script_id,
152
+ "script_id": canonical_id,
135
153
  "config": config_result,
136
154
  "config_hash": config_hash_value,
137
155
  }
@@ -20,6 +20,7 @@ from pydantic import Field
20
20
  from ..config import get_global_settings
21
21
  from ..errors import ErrorCode, create_error_response
22
22
  from .helpers import exception_to_structured_error, log_tool_usage, raise_tool_error
23
+ from .tools_config_dashboards import fetch_dashboards_list
23
24
  from .tools_filesystem import (
24
25
  MCP_TOOLS_DOMAIN,
25
26
  _assert_mcp_tools_available,
@@ -45,9 +46,7 @@ async def _check_storage_mode_dashboard_collision(
45
46
  return
46
47
  url_path = yaml_path[len(_LOVELACE_DASHBOARD_PREFIX):]
47
48
  try:
48
- result = await client.send_websocket_message(
49
- {"type": "lovelace/dashboards/list"}
50
- )
49
+ dashboards = await fetch_dashboards_list(client)
51
50
  except Exception as exc:
52
51
  logger.warning(
53
52
  "lovelace/dashboards/list WS query failed (%s); skipping collision check",
@@ -55,18 +54,6 @@ async def _check_storage_mode_dashboard_collision(
55
54
  )
56
55
  return
57
56
 
58
- if isinstance(result, dict) and "result" in result:
59
- dashboards = result["result"]
60
- elif isinstance(result, list):
61
- dashboards = result
62
- else:
63
- logger.warning(
64
- "lovelace/dashboards/list returned unexpected shape (%s); "
65
- "skipping collision check",
66
- type(result).__name__,
67
- )
68
- return
69
-
70
57
  for entry in dashboards or []:
71
58
  if (
72
59
  isinstance(entry, dict)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ha-mcp-dev
3
- Version: 7.5.0.dev532
3
+ Version: 7.5.0.dev534
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