ha-mcp-dev 7.6.0.dev621__tar.gz → 7.6.0.dev622__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 (125) hide show
  1. {ha_mcp_dev-7.6.0.dev621/src/ha_mcp_dev.egg-info → ha_mcp_dev-7.6.0.dev622}/PKG-INFO +1 -1
  2. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/pyproject.toml +1 -1
  3. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/config.py +18 -0
  4. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/server.py +28 -10
  5. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/settings_ui.py +4 -0
  6. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/tools/best_practice_checker.py +265 -129
  7. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/tools/tools_config_automations.py +84 -30
  8. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/tools/tools_config_dashboards.py +61 -10
  9. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/tools/tools_config_helpers.py +60 -13
  10. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/tools/tools_config_scenes.py +44 -6
  11. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/tools/tools_config_scripts.py +50 -9
  12. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/tools/tools_yaml_config.py +34 -7
  13. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/tools/util_helpers.py +285 -0
  14. ha_mcp_dev-7.6.0.dev622/src/ha_mcp/utils/skill_loader.py +271 -0
  15. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622/src/ha_mcp_dev.egg-info}/PKG-INFO +1 -1
  16. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp_dev.egg-info/SOURCES.txt +1 -0
  17. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/LICENSE +0 -0
  18. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/MANIFEST.in +0 -0
  19. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/README.md +0 -0
  20. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/setup.cfg +0 -0
  21. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/__init__.py +0 -0
  22. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/__main__.py +0 -0
  23. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/_pypi_marker +0 -0
  24. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/_version.py +0 -0
  25. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/auth/__init__.py +0 -0
  26. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/auth/consent_form.py +0 -0
  27. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/auth/provider.py +0 -0
  28. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/backup_manager.py +0 -0
  29. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/client/__init__.py +0 -0
  30. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/client/rest_client.py +0 -0
  31. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/client/supervisor_client.py +0 -0
  32. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/client/websocket_client.py +0 -0
  33. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/client/websocket_listener.py +0 -0
  34. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/errors.py +0 -0
  35. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/policy/__init__.py +0 -0
  36. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/policy/approval_queue.py +0 -0
  37. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/policy/evaluator.py +0 -0
  38. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/policy/handlers.py +0 -0
  39. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/policy/middleware.py +0 -0
  40. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/policy/model.py +0 -0
  41. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/policy/persistence.py +0 -0
  42. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/policy/value_sources.py +0 -0
  43. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/py.typed +0 -0
  44. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/resources/skills-vendor/.claude/settings.json +0 -0
  45. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/resources/skills-vendor/.claude-plugin/marketplace.json +0 -0
  46. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/resources/skills-vendor/.claude-plugin/plugin.json +0 -0
  47. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/resources/skills-vendor/.github/ISSUE_TEMPLATE/skill-rca.md +0 -0
  48. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/resources/skills-vendor/.github/pull_request_template.md +0 -0
  49. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/resources/skills-vendor/AGENTS.md +0 -0
  50. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/resources/skills-vendor/CLAUDE.md +0 -0
  51. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/resources/skills-vendor/CONTRIBUTING.md +0 -0
  52. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/resources/skills-vendor/LICENSE +0 -0
  53. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/resources/skills-vendor/README.md +0 -0
  54. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/SKILL.md +0 -0
  55. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/evals/evals.json +0 -0
  56. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/automation-patterns.md +0 -0
  57. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-cards.md +0 -0
  58. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-guide.md +0 -0
  59. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/device-control.md +0 -0
  60. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/domain-docs.md +0 -0
  61. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/examples.yaml +0 -0
  62. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/helper-selection.md +0 -0
  63. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/safe-refactoring.md +0 -0
  64. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/template-guidelines.md +0 -0
  65. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/yaml-only-integrations.md +0 -0
  66. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/smoke_test.py +0 -0
  67. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/stdio_settings_sidecar.py +0 -0
  68. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/tools/__init__.py +0 -0
  69. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/tools/auto_backup.py +0 -0
  70. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/tools/backup.py +0 -0
  71. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/tools/device_control.py +0 -0
  72. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/tools/enhanced.py +0 -0
  73. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/tools/helpers.py +0 -0
  74. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/tools/reference_validator.py +0 -0
  75. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/tools/registry.py +0 -0
  76. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/tools/smart_search.py +0 -0
  77. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/tools/tools_addons.py +0 -0
  78. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/tools/tools_areas.py +0 -0
  79. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/tools/tools_blueprints.py +0 -0
  80. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/tools/tools_bug_report.py +0 -0
  81. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/tools/tools_calendar.py +0 -0
  82. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/tools/tools_camera.py +0 -0
  83. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/tools/tools_categories.py +0 -0
  84. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/tools/tools_code.py +0 -0
  85. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/tools/tools_config_entry_flow.py +0 -0
  86. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/tools/tools_energy.py +0 -0
  87. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/tools/tools_entities.py +0 -0
  88. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/tools/tools_filesystem.py +0 -0
  89. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/tools/tools_groups.py +0 -0
  90. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/tools/tools_hacs.py +0 -0
  91. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/tools/tools_history.py +0 -0
  92. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/tools/tools_integrations.py +0 -0
  93. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/tools/tools_labels.py +0 -0
  94. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/tools/tools_mcp_component.py +0 -0
  95. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/tools/tools_registry.py +0 -0
  96. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/tools/tools_resources.py +0 -0
  97. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/tools/tools_search.py +0 -0
  98. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/tools/tools_service.py +0 -0
  99. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/tools/tools_services.py +0 -0
  100. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/tools/tools_system.py +0 -0
  101. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/tools/tools_todo.py +0 -0
  102. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/tools/tools_traces.py +0 -0
  103. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/tools/tools_updates.py +0 -0
  104. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/tools/tools_utility.py +0 -0
  105. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/tools/tools_voice_assistant.py +0 -0
  106. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/tools/tools_zones.py +0 -0
  107. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/transforms/__init__.py +0 -0
  108. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/transforms/categorized_search.py +0 -0
  109. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/transforms/lite_docstrings.py +0 -0
  110. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/utils/__init__.py +0 -0
  111. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/utils/config_hash.py +0 -0
  112. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/utils/data_paths.py +0 -0
  113. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/utils/domain_handlers.py +0 -0
  114. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/utils/fuzzy_search.py +0 -0
  115. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/utils/kill_signal_diagnostics.py +0 -0
  116. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/utils/operation_manager.py +0 -0
  117. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/utils/python_sandbox.py +0 -0
  118. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp/utils/usage_logger.py +0 -0
  119. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp_dev.egg-info/dependency_links.txt +0 -0
  120. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp_dev.egg-info/entry_points.txt +0 -0
  121. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp_dev.egg-info/requires.txt +0 -0
  122. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/src/ha_mcp_dev.egg-info/top_level.txt +0 -0
  123. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/tests/__init__.py +0 -0
  124. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/tests/test_constants.py +0 -0
  125. {ha_mcp_dev-7.6.0.dev621 → ha_mcp_dev-7.6.0.dev622}/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.6.0.dev621
3
+ Version: 7.6.0.dev622
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.6.0.dev621"
7
+ version = "7.6.0.dev622"
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"
@@ -144,6 +144,18 @@ class Settings(BaseSettings):
144
144
  # env-var users see the trade-off in their logs.
145
145
  enable_lite_docstrings: bool = Field(False, alias="ENABLE_LITE_DOCSTRINGS")
146
146
 
147
+ # Mandatory best-practice skills — server-side master switch for the
148
+ # write-tool skill_content delivery feature (issue #1182). When True
149
+ # (default), the six write tools (automations / scripts / scenes /
150
+ # helpers / dashboards / yaml) attach the canonical best-practice
151
+ # reference files under ``skill_content`` on every successful write,
152
+ # plus auto-embed any sections cited by best-practice warnings. The
153
+ # per-call ``MandatoryBPS`` parameter on each tool controls whether
154
+ # the canonical files ship for that one call. This setting is the
155
+ # master gate above that — when False, NO skill_content goes out
156
+ # regardless of the per-call param or BP warnings. Default on.
157
+ enable_mandatory_bps: bool = Field(True, alias="ENABLE_MANDATORY_BPS")
158
+
147
159
  # Filesystem tools — read/write/delete/list under the HA config dir.
148
160
  # Previously gated by a direct ``os.getenv`` call in
149
161
  # ``tools/tools_filesystem.py`` so callers (and the settings UI)
@@ -412,6 +424,12 @@ FEATURE_FLAG_FIELDS: tuple[FeatureFlagField, ...] = (
412
424
  FeatureFlagField(
413
425
  "enable_tool_security_policies", "ENABLE_TOOL_SECURITY_POLICIES", bool
414
426
  ),
427
+ # Non-beta, default-ON master switch for write-tool skill_content
428
+ # delivery (#1182). Grouped with the non-beta flags above the beta
429
+ # run below; intentionally NOT in BETA_FEATURE_FIELDS (it must not be
430
+ # gated by the beta master) nor in ADVANCED_SETTINGS_FIELDS (registries
431
+ # are name-disjoint per _validate_registries()).
432
+ FeatureFlagField("enable_mandatory_bps", "ENABLE_MANDATORY_BPS", bool),
415
433
  FeatureFlagField("enable_yaml_config_editing", "ENABLE_YAML_CONFIG_EDITING", bool),
416
434
  FeatureFlagField("enable_lite_docstrings", "ENABLE_LITE_DOCSTRINGS", bool),
417
435
  FeatureFlagField("enable_filesystem_tools", "HAMCP_ENABLE_FILESYSTEM_TOOLS", bool),
@@ -200,10 +200,13 @@ class HomeAssistantSmartMCPServer(EnhancedToolsMixin):
200
200
 
201
201
  Skills are vendored via a git submodule at resources/skills-vendor/.
202
202
  The actual skill directories live under the skills/ subdirectory
203
- within that repo.
203
+ within that repo. Delegates to
204
+ :func:`ha_mcp.utils.skill_loader.get_skills_dir` so the write-tool
205
+ ``MandatoryBPS`` parameter resolves the same path.
204
206
  """
205
- skills_dir = Path(__file__).parent / "resources" / "skills-vendor" / "skills"
206
- return skills_dir if skills_dir.exists() else None
207
+ from .utils.skill_loader import get_skills_dir
208
+
209
+ return get_skills_dir()
207
210
 
208
211
  def _build_skills_instructions(self) -> str | None:
209
212
  """Build server instructions from bundled skill frontmatter.
@@ -1434,13 +1437,28 @@ class HomeAssistantSmartMCPServer(EnhancedToolsMixin):
1434
1437
  )
1435
1438
  )
1436
1439
 
1437
- return {
1438
- "success": True,
1439
- "skill": skill,
1440
- "file": file,
1441
- "uri": f"skill://{skill}/{file}",
1442
- "content": content,
1443
- }
1440
+ # Hint goes at the top of the response so the LLM sees it before
1441
+ # parsing the (potentially large) content body. Scoped to the
1442
+ # best-practice skill because that's the one the write-tool
1443
+ # MandatoryBPS param gates; other skills (if any) are unrelated.
1444
+ from .tools.util_helpers import (
1445
+ _HA_BEST_PRACTICES_SKILL_NAME,
1446
+ _SKILL_GUIDE_MANDATORYBPS_HINT,
1447
+ )
1448
+
1449
+ response: dict[str, Any] = {}
1450
+ if skill == _HA_BEST_PRACTICES_SKILL_NAME:
1451
+ response["skill_content_hint"] = _SKILL_GUIDE_MANDATORYBPS_HINT
1452
+ response.update(
1453
+ {
1454
+ "success": True,
1455
+ "skill": skill,
1456
+ "file": file,
1457
+ "uri": f"skill://{skill}/{file}",
1458
+ "content": content,
1459
+ }
1460
+ )
1461
+ return response
1444
1462
 
1445
1463
  # Helper methods required by EnhancedToolsMixin
1446
1464
 
@@ -2165,6 +2165,10 @@ const FEATURE_META = {
2165
2165
  label: "Enable Tool Security Policies",
2166
2166
  help: "Opt-in middleware that gates high-stakes MCP tool calls behind user approval. When enabled, tools that match a rule in the Tool Security Policies tab require you to click Approve in the web UI before they run. Off by default. Per-tool rules with optional argument conditions are configured in the Tool Security Policies tab. Requires restart to take effect.",
2167
2167
  },
2168
+ enable_mandatory_bps: {
2169
+ label: "Attach best-practice skills on writes",
2170
+ help: "Master switch for the write-tool skill content delivery feature (issue #1182). When enabled (default), the six config write tools (automations, scripts, scenes, helpers, dashboards, raw YAML) attach the canonical Home Assistant best-practice reference files under skill_content on every successful write, plus auto-embed any reference sections cited by best-practice warnings. Each tool also exposes a per-call MandatoryBPS parameter the agent can set to false on subsequent calls once it has the content. When this master switch is off, NO skill_content goes out regardless of the per-call parameter or BP warnings. Leave on if your LLM benefits from inline guidance; turn off to minimise tokens when using an LLM that has the best-practice files indexed via skills or another retrieval path. Requires restart to take effect.",
2171
+ },
2168
2172
  // Master beta toggle — gates the 5 sub-flags below at runtime
2169
2173
  // (see config.py:_apply_feature_flag_overrides master gate). UI
2170
2174
  // dims sub-rows when this is off and re-renders live on flip.