ha-mcp-dev 7.5.0.dev515__tar.gz → 7.5.0.dev517__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.
- {ha_mcp_dev-7.5.0.dev515/src/ha_mcp_dev.egg-info → ha_mcp_dev-7.5.0.dev517}/PKG-INFO +3 -3
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/README.md +2 -2
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/pyproject.toml +1 -1
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/tools_config_helpers.py +90 -30
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517/src/ha_mcp_dev.egg-info}/PKG-INFO +3 -3
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/LICENSE +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/MANIFEST.in +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/setup.cfg +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/__init__.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/__main__.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/_pypi_marker +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/_version.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/auth/__init__.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/auth/consent_form.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/auth/provider.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/client/__init__.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/client/rest_client.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/client/supervisor_client.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/client/websocket_client.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/client/websocket_listener.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/config.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/errors.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/py.typed +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/resources/skills-vendor/.claude/settings.json +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/resources/skills-vendor/.claude-plugin/marketplace.json +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/resources/skills-vendor/.claude-plugin/plugin.json +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/resources/skills-vendor/.github/ISSUE_TEMPLATE/skill-rca.md +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/resources/skills-vendor/AGENTS.md +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/resources/skills-vendor/CLAUDE.md +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/resources/skills-vendor/CONTRIBUTING.md +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/resources/skills-vendor/LICENSE +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/resources/skills-vendor/README.md +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/SKILL.md +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/evals/evals.json +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/automation-patterns.md +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-cards.md +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-guide.md +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/device-control.md +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/domain-docs.md +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/examples.yaml +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/helper-selection.md +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/safe-refactoring.md +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/template-guidelines.md +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/server.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/settings_ui.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/smoke_test.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/__init__.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/backup.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/best_practice_checker.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/device_control.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/enhanced.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/helpers.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/reference_validator.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/registry.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/smart_search.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/tools_addons.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/tools_areas.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/tools_blueprints.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/tools_bug_report.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/tools_calendar.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/tools_camera.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/tools_categories.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/tools_code.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/tools_config_automations.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/tools_config_dashboards.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/tools_config_entry_flow.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/tools_config_scenes.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/tools_config_scripts.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/tools_energy.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/tools_entities.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/tools_filesystem.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/tools_groups.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/tools_hacs.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/tools_history.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/tools_integrations.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/tools_labels.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/tools_mcp_component.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/tools_registry.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/tools_resources.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/tools_search.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/tools_service.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/tools_services.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/tools_system.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/tools_todo.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/tools_traces.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/tools_updates.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/tools_utility.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/tools_voice_assistant.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/tools_yaml_config.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/tools_zones.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/util_helpers.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/transforms/__init__.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/transforms/categorized_search.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/transforms/lite_docstrings.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/utils/__init__.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/utils/config_hash.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/utils/data_paths.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/utils/domain_handlers.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/utils/fuzzy_search.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/utils/kill_signal_diagnostics.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/utils/operation_manager.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/utils/python_sandbox.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/utils/usage_logger.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp_dev.egg-info/SOURCES.txt +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp_dev.egg-info/dependency_links.txt +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp_dev.egg-info/entry_points.txt +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp_dev.egg-info/requires.txt +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp_dev.egg-info/top_level.txt +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/tests/__init__.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/tests/test_constants.py +0 -0
- {ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/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.
|
|
3
|
+
Version: 7.5.0.dev517
|
|
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
|
|
@@ -256,9 +256,9 @@ An MCP server can create automations, helpers, and dashboards, but it has no opi
|
|
|
256
256
|
|
|
257
257
|
### Bundled Skills (built-in)
|
|
258
258
|
|
|
259
|
-
Skills from `homeassistant-ai/skills` are bundled and served as [MCP resources](https://modelcontextprotocol.io/docs/concepts/resources) via `skill://` URIs. Any MCP client that supports resources can discover them automatically — no manual installation needed. For tool-only clients, the same skills are
|
|
259
|
+
Skills from `homeassistant-ai/skills` are bundled and served as [MCP resources](https://modelcontextprotocol.io/docs/concepts/resources) via `skill://` URIs. Any MCP client that supports resources can discover them automatically — no manual installation needed. For tool-only clients (claude.ai, etc.), the same skills are reachable through the polymorphic `ha_get_skill_guide` tool — call it with no args to list bundled skills, with a `skill` arg to list its files, or with `skill` + `file` to read content. Resources are not auto-injected into context — clients must explicitly request them, so idle context cost is just the metadata listing.
|
|
260
260
|
|
|
261
|
-
|
|
261
|
+
`ha_get_skill_guide` is mandatory-pinned: the catalog always exposes it so tool-only clients never see a silently missing skill surface.
|
|
262
262
|
|
|
263
263
|
Skills can still be installed manually for clients that prefer local skill files — see the [skills repo](https://github.com/homeassistant-ai/skills) for instructions.
|
|
264
264
|
|
|
@@ -226,9 +226,9 @@ An MCP server can create automations, helpers, and dashboards, but it has no opi
|
|
|
226
226
|
|
|
227
227
|
### Bundled Skills (built-in)
|
|
228
228
|
|
|
229
|
-
Skills from `homeassistant-ai/skills` are bundled and served as [MCP resources](https://modelcontextprotocol.io/docs/concepts/resources) via `skill://` URIs. Any MCP client that supports resources can discover them automatically — no manual installation needed. For tool-only clients, the same skills are
|
|
229
|
+
Skills from `homeassistant-ai/skills` are bundled and served as [MCP resources](https://modelcontextprotocol.io/docs/concepts/resources) via `skill://` URIs. Any MCP client that supports resources can discover them automatically — no manual installation needed. For tool-only clients (claude.ai, etc.), the same skills are reachable through the polymorphic `ha_get_skill_guide` tool — call it with no args to list bundled skills, with a `skill` arg to list its files, or with `skill` + `file` to read content. Resources are not auto-injected into context — clients must explicitly request them, so idle context cost is just the metadata listing.
|
|
230
230
|
|
|
231
|
-
|
|
231
|
+
`ha_get_skill_guide` is mandatory-pinned: the catalog always exposes it so tool-only clients never see a silently missing skill surface.
|
|
232
232
|
|
|
233
233
|
Skills can still be installed manually for clients that prefer local skill files — see the [skills repo](https://github.com/homeassistant-ai/skills) for instructions.
|
|
234
234
|
|
|
@@ -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.
|
|
7
|
+
version = "7.5.0.dev517"
|
|
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"
|
{ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/tools_config_helpers.py
RENAMED
|
@@ -867,6 +867,69 @@ def _validate_numeric_range(
|
|
|
867
867
|
)
|
|
868
868
|
|
|
869
869
|
|
|
870
|
+
def _validate_initial_in_options(
|
|
871
|
+
options: Any, initial: Any, helper_type: str = "input_select"
|
|
872
|
+
) -> None:
|
|
873
|
+
"""Reject ``initial`` values not in ``options``.
|
|
874
|
+
|
|
875
|
+
Called from both create and update branches with the resolved values —
|
|
876
|
+
caller-supplied on create, merged with the existing config on update.
|
|
877
|
+
``initial=None`` is the unset case and passes through. The
|
|
878
|
+
``isinstance(options, list)`` early-return mirrors the defensive shape
|
|
879
|
+
check in ``_validate_input_select_options`` below — both validators are
|
|
880
|
+
invariant gates, not type contracts; a future non-list caller is
|
|
881
|
+
silently skipped rather than raising a confusing ``TypeError`` on
|
|
882
|
+
``initial not in options``.
|
|
883
|
+
"""
|
|
884
|
+
if not isinstance(options, list) or initial is None:
|
|
885
|
+
return
|
|
886
|
+
if initial not in options:
|
|
887
|
+
raise_tool_error(
|
|
888
|
+
create_error_response(
|
|
889
|
+
ErrorCode.VALIDATION_INVALID_PARAMETER,
|
|
890
|
+
f"initial={initial!r} must be one of options "
|
|
891
|
+
f"{options!r} for {helper_type}.",
|
|
892
|
+
context=_simple_helper_error_context(
|
|
893
|
+
helper_type,
|
|
894
|
+
initial=initial,
|
|
895
|
+
options=options,
|
|
896
|
+
),
|
|
897
|
+
suggestions=[
|
|
898
|
+
"Pick an `initial` value that's in `options`.",
|
|
899
|
+
"Or omit `initial` to use the default or existing value.",
|
|
900
|
+
],
|
|
901
|
+
)
|
|
902
|
+
)
|
|
903
|
+
|
|
904
|
+
|
|
905
|
+
def _validate_datetime_has_date_or_time(
|
|
906
|
+
has_date: bool | None, has_time: bool | None
|
|
907
|
+
) -> None:
|
|
908
|
+
"""Reject ``input_datetime`` payloads where both components are False.
|
|
909
|
+
|
|
910
|
+
Treats ``None`` as "not constrained" — only the explicit (False, False)
|
|
911
|
+
case is flagged, since that's what reaches HA as the broken-entity
|
|
912
|
+
payload. Both the create and update branches call this with the
|
|
913
|
+
resolved-after-merge ``has_date`` / ``has_time`` pair.
|
|
914
|
+
"""
|
|
915
|
+
if has_date is False and has_time is False:
|
|
916
|
+
raise_tool_error(
|
|
917
|
+
create_error_response(
|
|
918
|
+
ErrorCode.VALIDATION_INVALID_PARAMETER,
|
|
919
|
+
"At least one of has_date or has_time must be True for input_datetime",
|
|
920
|
+
context=_simple_helper_error_context(
|
|
921
|
+
"input_datetime",
|
|
922
|
+
has_date=has_date,
|
|
923
|
+
has_time=has_time,
|
|
924
|
+
),
|
|
925
|
+
suggestions=[
|
|
926
|
+
"Set has_date=True to keep the date component.",
|
|
927
|
+
"Set has_time=True to keep the time component.",
|
|
928
|
+
],
|
|
929
|
+
)
|
|
930
|
+
)
|
|
931
|
+
|
|
932
|
+
|
|
870
933
|
def _validate_input_select_options(options: Any) -> None:
|
|
871
934
|
"""Reject input_select option lists containing duplicates (Bug 17, issue #1150).
|
|
872
935
|
|
|
@@ -2398,28 +2461,12 @@ def register_config_helper_tools(mcp: Any, client: Any, **kwargs: Any) -> None:
|
|
|
2398
2461
|
)
|
|
2399
2462
|
)
|
|
2400
2463
|
message["options"] = options
|
|
2401
|
-
#
|
|
2402
|
-
#
|
|
2403
|
-
#
|
|
2404
|
-
#
|
|
2464
|
+
# If `initial` was passed but isn't one of the options,
|
|
2465
|
+
# reject explicitly instead of silently dropping. Shared
|
|
2466
|
+
# with the update branch via the helper so the same
|
|
2467
|
+
# invariant fires on both code paths.
|
|
2468
|
+
_validate_initial_in_options(options, initial)
|
|
2405
2469
|
if initial is not None:
|
|
2406
|
-
if initial not in options:
|
|
2407
|
-
raise_tool_error(
|
|
2408
|
-
create_error_response(
|
|
2409
|
-
ErrorCode.VALIDATION_INVALID_PARAMETER,
|
|
2410
|
-
f"initial={initial!r} must be one of options "
|
|
2411
|
-
f"{options!r} for input_select.",
|
|
2412
|
-
context=_simple_helper_error_context(
|
|
2413
|
-
helper_type,
|
|
2414
|
-
initial=initial,
|
|
2415
|
-
options=options,
|
|
2416
|
-
),
|
|
2417
|
-
suggestions=[
|
|
2418
|
-
"Pick an `initial` value that's in `options`.",
|
|
2419
|
-
"Or omit `initial` so the entity starts unset.",
|
|
2420
|
-
],
|
|
2421
|
-
)
|
|
2422
|
-
)
|
|
2423
2470
|
message["initial"] = initial
|
|
2424
2471
|
|
|
2425
2472
|
elif helper_type == "input_number":
|
|
@@ -2477,15 +2524,12 @@ def register_config_helper_tools(mcp: Any, client: Any, **kwargs: Any) -> None:
|
|
|
2477
2524
|
message["has_date"] = has_date
|
|
2478
2525
|
message["has_time"] = has_time
|
|
2479
2526
|
|
|
2480
|
-
# Validate that at least one is True
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
context=_simple_helper_error_context(helper_type),
|
|
2487
|
-
)
|
|
2488
|
-
)
|
|
2527
|
+
# Validate that at least one is True — shared with the
|
|
2528
|
+
# update branch via the helper so the same invariant
|
|
2529
|
+
# fires on both code paths.
|
|
2530
|
+
_validate_datetime_has_date_or_time(
|
|
2531
|
+
message["has_date"], message["has_time"]
|
|
2532
|
+
)
|
|
2489
2533
|
|
|
2490
2534
|
if initial is not None:
|
|
2491
2535
|
message["initial"] = initial
|
|
@@ -3048,6 +3092,14 @@ def register_config_helper_tools(mcp: Any, client: Any, **kwargs: Any) -> None:
|
|
|
3048
3092
|
if initial is not None
|
|
3049
3093
|
else existing.get("initial")
|
|
3050
3094
|
)
|
|
3095
|
+
# Parity with the create-branch guard. Resolves to
|
|
3096
|
+
# (new options, new initial) / (new options, old
|
|
3097
|
+
# initial) / (old options, new initial) — any
|
|
3098
|
+
# combination that excludes initial from the final
|
|
3099
|
+
# options list is caught.
|
|
3100
|
+
_validate_initial_in_options(
|
|
3101
|
+
update_msg["options"], initial_val
|
|
3102
|
+
)
|
|
3051
3103
|
if initial_val is not None:
|
|
3052
3104
|
update_msg["initial"] = initial_val
|
|
3053
3105
|
|
|
@@ -3140,6 +3192,14 @@ def register_config_helper_tools(mcp: Any, client: Any, **kwargs: Any) -> None:
|
|
|
3140
3192
|
if has_time is not None
|
|
3141
3193
|
else existing.get("has_time", False)
|
|
3142
3194
|
)
|
|
3195
|
+
# Parity with the create-branch guard. A merge
|
|
3196
|
+
# that resolves to (False, False) — caller
|
|
3197
|
+
# disabling the one component the existing entity
|
|
3198
|
+
# had — would otherwise write a broken-entity
|
|
3199
|
+
# payload and surface HA's cryptic generic error.
|
|
3200
|
+
_validate_datetime_has_date_or_time(
|
|
3201
|
+
update_msg["has_date"], update_msg["has_time"]
|
|
3202
|
+
)
|
|
3143
3203
|
initial_val = (
|
|
3144
3204
|
initial
|
|
3145
3205
|
if initial is not None
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ha-mcp-dev
|
|
3
|
-
Version: 7.5.0.
|
|
3
|
+
Version: 7.5.0.dev517
|
|
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
|
|
@@ -256,9 +256,9 @@ An MCP server can create automations, helpers, and dashboards, but it has no opi
|
|
|
256
256
|
|
|
257
257
|
### Bundled Skills (built-in)
|
|
258
258
|
|
|
259
|
-
Skills from `homeassistant-ai/skills` are bundled and served as [MCP resources](https://modelcontextprotocol.io/docs/concepts/resources) via `skill://` URIs. Any MCP client that supports resources can discover them automatically — no manual installation needed. For tool-only clients, the same skills are
|
|
259
|
+
Skills from `homeassistant-ai/skills` are bundled and served as [MCP resources](https://modelcontextprotocol.io/docs/concepts/resources) via `skill://` URIs. Any MCP client that supports resources can discover them automatically — no manual installation needed. For tool-only clients (claude.ai, etc.), the same skills are reachable through the polymorphic `ha_get_skill_guide` tool — call it with no args to list bundled skills, with a `skill` arg to list its files, or with `skill` + `file` to read content. Resources are not auto-injected into context — clients must explicitly request them, so idle context cost is just the metadata listing.
|
|
260
260
|
|
|
261
|
-
|
|
261
|
+
`ha_get_skill_guide` is mandatory-pinned: the catalog always exposes it so tool-only clients never see a silently missing skill surface.
|
|
262
262
|
|
|
263
263
|
Skills can still be installed manually for clients that prefer local skill files — see the [skills repo](https://github.com/homeassistant-ai/skills) for instructions.
|
|
264
264
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/resources/skills-vendor/AGENTS.md
RENAMED
|
File without changes
|
{ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/resources/skills-vendor/CLAUDE.md
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/resources/skills-vendor/LICENSE
RENAMED
|
File without changes
|
{ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/resources/skills-vendor/README.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/best_practice_checker.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/tools_config_automations.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/tools_config_dashboards.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/tools_config_entry_flow.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/tools_config_scripts.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/tools/tools_voice_assistant.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/transforms/categorized_search.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/transforms/lite_docstrings.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp/utils/kill_signal_diagnostics.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp_dev.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{ha_mcp_dev-7.5.0.dev515 → ha_mcp_dev-7.5.0.dev517}/src/ha_mcp_dev.egg-info/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|