ha-mcp-dev 7.5.0.dev510__tar.gz → 7.5.0.dev512__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.dev510/src/ha_mcp_dev.egg-info → ha_mcp_dev-7.5.0.dev512}/PKG-INFO +1 -1
  2. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/pyproject.toml +1 -1
  3. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/tools/tools_config_automations.py +10 -39
  4. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/tools/tools_config_dashboards.py +14 -0
  5. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/utils/python_sandbox.py +2 -1
  6. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512/src/ha_mcp_dev.egg-info}/PKG-INFO +1 -1
  7. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/LICENSE +0 -0
  8. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/MANIFEST.in +0 -0
  9. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/README.md +0 -0
  10. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/setup.cfg +0 -0
  11. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/__init__.py +0 -0
  12. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/__main__.py +0 -0
  13. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/_pypi_marker +0 -0
  14. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/_version.py +0 -0
  15. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/auth/__init__.py +0 -0
  16. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/auth/consent_form.py +0 -0
  17. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/auth/provider.py +0 -0
  18. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/client/__init__.py +0 -0
  19. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/client/rest_client.py +0 -0
  20. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/client/supervisor_client.py +0 -0
  21. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/client/websocket_client.py +0 -0
  22. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/client/websocket_listener.py +0 -0
  23. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/config.py +0 -0
  24. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/errors.py +0 -0
  25. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/py.typed +0 -0
  26. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/resources/skills-vendor/.claude/settings.json +0 -0
  27. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/resources/skills-vendor/.claude-plugin/marketplace.json +0 -0
  28. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/resources/skills-vendor/.claude-plugin/plugin.json +0 -0
  29. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/resources/skills-vendor/.github/ISSUE_TEMPLATE/skill-rca.md +0 -0
  30. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/resources/skills-vendor/AGENTS.md +0 -0
  31. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/resources/skills-vendor/CLAUDE.md +0 -0
  32. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/resources/skills-vendor/CONTRIBUTING.md +0 -0
  33. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/resources/skills-vendor/LICENSE +0 -0
  34. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/resources/skills-vendor/README.md +0 -0
  35. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/SKILL.md +0 -0
  36. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/evals/evals.json +0 -0
  37. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/automation-patterns.md +0 -0
  38. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-cards.md +0 -0
  39. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-guide.md +0 -0
  40. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/device-control.md +0 -0
  41. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/domain-docs.md +0 -0
  42. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/examples.yaml +0 -0
  43. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/helper-selection.md +0 -0
  44. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/safe-refactoring.md +0 -0
  45. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/template-guidelines.md +0 -0
  46. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/server.py +0 -0
  47. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/settings_ui.py +0 -0
  48. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/smoke_test.py +0 -0
  49. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/tools/__init__.py +0 -0
  50. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/tools/backup.py +0 -0
  51. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/tools/best_practice_checker.py +0 -0
  52. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/tools/device_control.py +0 -0
  53. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/tools/enhanced.py +0 -0
  54. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/tools/helpers.py +0 -0
  55. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/tools/reference_validator.py +0 -0
  56. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/tools/registry.py +0 -0
  57. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/tools/smart_search.py +0 -0
  58. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/tools/tools_addons.py +0 -0
  59. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/tools/tools_areas.py +0 -0
  60. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/tools/tools_blueprints.py +0 -0
  61. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/tools/tools_bug_report.py +0 -0
  62. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/tools/tools_calendar.py +0 -0
  63. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/tools/tools_camera.py +0 -0
  64. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/tools/tools_categories.py +0 -0
  65. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/tools/tools_code.py +0 -0
  66. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/tools/tools_config_entry_flow.py +0 -0
  67. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/tools/tools_config_helpers.py +0 -0
  68. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/tools/tools_config_scenes.py +0 -0
  69. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/tools/tools_config_scripts.py +0 -0
  70. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/tools/tools_energy.py +0 -0
  71. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/tools/tools_entities.py +0 -0
  72. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/tools/tools_filesystem.py +0 -0
  73. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/tools/tools_groups.py +0 -0
  74. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/tools/tools_hacs.py +0 -0
  75. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/tools/tools_history.py +0 -0
  76. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/tools/tools_integrations.py +0 -0
  77. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/tools/tools_labels.py +0 -0
  78. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/tools/tools_mcp_component.py +0 -0
  79. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/tools/tools_registry.py +0 -0
  80. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/tools/tools_resources.py +0 -0
  81. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/tools/tools_search.py +0 -0
  82. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/tools/tools_service.py +0 -0
  83. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/tools/tools_services.py +0 -0
  84. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/tools/tools_system.py +0 -0
  85. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/tools/tools_todo.py +0 -0
  86. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/tools/tools_traces.py +0 -0
  87. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/tools/tools_updates.py +0 -0
  88. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/tools/tools_utility.py +0 -0
  89. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/tools/tools_voice_assistant.py +0 -0
  90. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/tools/tools_yaml_config.py +0 -0
  91. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/tools/tools_zones.py +0 -0
  92. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/tools/util_helpers.py +0 -0
  93. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/transforms/__init__.py +0 -0
  94. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/transforms/categorized_search.py +0 -0
  95. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/transforms/lite_docstrings.py +0 -0
  96. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/utils/__init__.py +0 -0
  97. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/utils/config_hash.py +0 -0
  98. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/utils/data_paths.py +0 -0
  99. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/utils/domain_handlers.py +0 -0
  100. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/utils/fuzzy_search.py +0 -0
  101. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/utils/kill_signal_diagnostics.py +0 -0
  102. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/utils/operation_manager.py +0 -0
  103. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp/utils/usage_logger.py +0 -0
  104. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp_dev.egg-info/SOURCES.txt +0 -0
  105. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp_dev.egg-info/dependency_links.txt +0 -0
  106. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp_dev.egg-info/entry_points.txt +0 -0
  107. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp_dev.egg-info/requires.txt +0 -0
  108. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/src/ha_mcp_dev.egg-info/top_level.txt +0 -0
  109. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/tests/__init__.py +0 -0
  110. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/tests/test_constants.py +0 -0
  111. {ha_mcp_dev-7.5.0.dev510 → ha_mcp_dev-7.5.0.dev512}/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.dev510
3
+ Version: 7.5.0.dev512
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.dev510"
7
+ version = "7.5.0.dev512"
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"
@@ -16,7 +16,6 @@ from ..errors import (
16
16
  ErrorCode,
17
17
  create_config_error,
18
18
  create_error_response,
19
- create_resource_not_found_error,
20
19
  create_validation_error,
21
20
  )
22
21
  from ..utils.config_hash import compute_config_hash
@@ -304,26 +303,9 @@ class AutomationConfigTools:
304
303
  "config": normalized_config,
305
304
  "config_hash": config_hash,
306
305
  }
306
+ except ToolError:
307
+ raise
307
308
  except Exception as e:
308
- # Handle 404 errors gracefully (often used to verify deletion)
309
- error_str = str(e)
310
- if (
311
- "404" in error_str
312
- or "not found" in error_str.lower()
313
- or "entity not found" in error_str.lower()
314
- ):
315
- logger.debug(
316
- f"Automation {identifier} not found (expected for deletion verification)"
317
- )
318
- error_response = create_resource_not_found_error(
319
- "Automation",
320
- identifier,
321
- details=f"Automation '{identifier}' does not exist in Home Assistant",
322
- )
323
- error_response["action"] = "get"
324
- error_response["reason"] = "not_found"
325
- raise_tool_error(error_response)
326
-
327
309
  logger.error(f"Error getting automation: {e}")
328
310
  exception_to_structured_error(
329
311
  e,
@@ -1003,30 +985,19 @@ class AutomationConfigTools:
1003
985
  result["warning"] = f"Deletion confirmed but removal verification failed: {e}"
1004
986
 
1005
987
  return {"success": True, "action": "delete", **result}
988
+ except ToolError:
989
+ raise
1006
990
  except Exception as e:
1007
991
  logger.error(f"Error deleting automation: {e}")
1008
- error_str = str(e).lower()
1009
- if "404" in error_str or "not found" in error_str:
1010
- error_response = create_resource_not_found_error(
1011
- "Automation",
1012
- identifier,
1013
- details=f"Automation '{identifier}' does not exist",
1014
- )
1015
- else:
1016
- error_response = exception_to_structured_error(
1017
- e,
1018
- context={"identifier": identifier},
1019
- raise_error=False,
1020
- )
1021
- error_response["action"] = "delete"
1022
- # Add automation-specific suggestions
1023
- if "error" in error_response and isinstance(error_response["error"], dict):
1024
- error_response["error"]["suggestions"] = [
992
+ exception_to_structured_error(
993
+ e,
994
+ context={"identifier": identifier, "action": "delete"},
995
+ suggestions=[
1025
996
  "Verify automation exists using ha_search_entities(domain_filter='automation')",
1026
997
  "Use entity_id format: automation.morning_routine or unique_id",
1027
998
  "Check Home Assistant connection",
1028
- ]
1029
- raise_tool_error(error_response)
999
+ ],
1000
+ )
1030
1001
 
1031
1002
 
1032
1003
  def register_config_automation_tools(mcp: Any, client: Any, **kwargs: Any) -> None:
@@ -16,6 +16,7 @@ from ..errors import ErrorCode, create_error_response, create_resource_not_found
16
16
  from ..utils.config_hash import compute_config_hash
17
17
  from ..utils.python_sandbox import (
18
18
  PythonSandboxError,
19
+ PythonSandboxExecutionError,
19
20
  format_sandbox_error,
20
21
  get_security_documentation,
21
22
  safe_execute,
@@ -1096,6 +1097,19 @@ def register_config_dashboard_tools(mcp: Any, client: Any, **kwargs: Any) -> Non
1096
1097
  transformed_config = safe_execute(python_transform, current_config)
1097
1098
  except PythonSandboxError as e:
1098
1099
  message, suggestions = format_sandbox_error(e, python_transform)
1100
+ # A path-shape mismatch (IndexError/KeyError) is almost always
1101
+ # a hallucinated path; steer the retry toward search mode so
1102
+ # the next transform is built from a verified jq_path.
1103
+ if isinstance(e, PythonSandboxExecutionError) and isinstance(
1104
+ e.__cause__, (IndexError, KeyError)
1105
+ ):
1106
+ suggestions = [
1107
+ "Call ha_config_get_dashboard with card_type=..., "
1108
+ "entity_id=..., or heading=... to get the verified "
1109
+ "jq_path for the target card, then build "
1110
+ "python_transform from that path",
1111
+ *suggestions,
1112
+ ]
1099
1113
  raise_tool_error(
1100
1114
  create_error_response(
1101
1115
  ErrorCode.VALIDATION_FAILED,
@@ -192,6 +192,7 @@ SAFE_METHODS = {
192
192
  "strip",
193
193
  "split",
194
194
  "join",
195
+ "replace",
195
196
  }
196
197
 
197
198
  # Blocked function names
@@ -514,7 +515,7 @@ PYTHON TRANSFORM SECURITY:
514
515
  - Dict unpacking (**) in calls and dict literals: {**d, 'k': v}
515
516
  - Keyword arguments: func(key=value)
516
517
  - Lambdas (e.g. for `key=`): sorted(items, key=lambda x: x['score'])
517
- - String methods: startswith, endswith, lower, upper, split, join
518
+ - String methods: startswith, endswith, lower, upper, strip, split, join, replace
518
519
  - Safe builtins: isinstance, len, range, enumerate, zip, sorted, reversed,
519
520
  min, max, sum, abs, any, all, round, str, int, float, bool, list, dict,
520
521
  tuple, set
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ha-mcp-dev
3
- Version: 7.5.0.dev510
3
+ Version: 7.5.0.dev512
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