ha-mcp-dev 7.1.0.dev308__tar.gz → 7.1.0.dev309__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.1.0.dev308/src/ha_mcp_dev.egg-info → ha_mcp_dev-7.1.0.dev309}/PKG-INFO +1 -1
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/pyproject.toml +1 -1
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/config.py +14 -3
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/server.py +5 -0
- ha_mcp_dev-7.1.0.dev309/src/ha_mcp/tools/tools_yaml_config.py +205 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/transforms/categorized_search.py +1 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309/src/ha_mcp_dev.egg-info}/PKG-INFO +1 -1
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp_dev.egg-info/SOURCES.txt +1 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/LICENSE +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/MANIFEST.in +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/README.md +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/setup.cfg +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/__init__.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/__main__.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/_pypi_marker +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/auth/__init__.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/auth/consent_form.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/auth/provider.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/client/__init__.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/client/rest_client.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/client/websocket_client.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/client/websocket_listener.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/errors.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/py.typed +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/resources/skills-vendor/.claude/settings.json +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/resources/skills-vendor/.claude-plugin/marketplace.json +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/resources/skills-vendor/.claude-plugin/plugin.json +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/resources/skills-vendor/.github/ISSUE_TEMPLATE/skill-rca.md +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/resources/skills-vendor/AGENTS.md +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/resources/skills-vendor/CLAUDE.md +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/resources/skills-vendor/CONTRIBUTING.md +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/resources/skills-vendor/LICENSE +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/resources/skills-vendor/README.md +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/SKILL.md +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/evals/evals.json +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/automation-patterns.md +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-cards.md +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-guide.md +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/device-control.md +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/domain-docs.md +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/examples.yaml +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/helper-selection.md +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/safe-refactoring.md +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/template-guidelines.md +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/smoke_test.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/tools/__init__.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/tools/backup.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/tools/best_practice_checker.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/tools/device_control.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/tools/enhanced.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/tools/helpers.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/tools/registry.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/tools/smart_search.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/tools/tools_addons.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/tools/tools_areas.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/tools/tools_blueprints.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/tools/tools_bug_report.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/tools/tools_calendar.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/tools/tools_camera.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/tools/tools_categories.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/tools/tools_config_automations.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/tools/tools_config_dashboards.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/tools/tools_config_entry_flow.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/tools/tools_config_helpers.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/tools/tools_config_scripts.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/tools/tools_entities.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/tools/tools_filesystem.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/tools/tools_groups.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/tools/tools_hacs.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/tools/tools_history.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/tools/tools_integrations.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/tools/tools_labels.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/tools/tools_mcp_component.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/tools/tools_registry.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/tools/tools_resources.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/tools/tools_search.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/tools/tools_service.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/tools/tools_services.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/tools/tools_system.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/tools/tools_todo.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/tools/tools_traces.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/tools/tools_updates.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/tools/tools_utility.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/tools/tools_voice_assistant.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/tools/tools_zones.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/tools/util_helpers.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/transforms/__init__.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/utils/__init__.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/utils/domain_handlers.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/utils/fuzzy_search.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/utils/operation_manager.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/utils/python_sandbox.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/utils/usage_logger.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp_dev.egg-info/dependency_links.txt +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp_dev.egg-info/entry_points.txt +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp_dev.egg-info/requires.txt +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp_dev.egg-info/top_level.txt +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/tests/__init__.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/tests/test_constants.py +0 -0
- {ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/tests/test_env_manager.py +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "ha-mcp-dev"
|
|
7
|
-
version = "7.1.0.
|
|
7
|
+
version = "7.1.0.dev309"
|
|
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"
|
|
@@ -48,7 +48,9 @@ class Settings(BaseSettings):
|
|
|
48
48
|
# Home Assistant connection
|
|
49
49
|
# In OAuth mode, these are optional and provided per-request
|
|
50
50
|
homeassistant_url: str = Field(default=OAUTH_MODE_URL, alias="HOMEASSISTANT_URL")
|
|
51
|
-
homeassistant_token: str = Field(
|
|
51
|
+
homeassistant_token: str = Field(
|
|
52
|
+
default=OAUTH_MODE_TOKEN, alias="HOMEASSISTANT_TOKEN"
|
|
53
|
+
)
|
|
52
54
|
|
|
53
55
|
# Server configuration
|
|
54
56
|
timeout: int = Field(30, alias="HA_TIMEOUT")
|
|
@@ -70,7 +72,9 @@ class Settings(BaseSettings):
|
|
|
70
72
|
|
|
71
73
|
# MCP Server configuration
|
|
72
74
|
mcp_server_name: str = Field("ha-mcp", alias="MCP_SERVER_NAME")
|
|
73
|
-
mcp_server_version: str = Field(
|
|
75
|
+
mcp_server_version: str = Field(
|
|
76
|
+
default=_PACKAGE_VERSION, alias="MCP_SERVER_VERSION"
|
|
77
|
+
)
|
|
74
78
|
|
|
75
79
|
# Environment configuration
|
|
76
80
|
environment: str = Field("development", alias="ENVIRONMENT")
|
|
@@ -83,7 +87,9 @@ class Settings(BaseSettings):
|
|
|
83
87
|
# Dashboard partial update tools (python_transform, find_card)
|
|
84
88
|
# These are token-efficient alternatives to full config replacement.
|
|
85
89
|
# Disable when using clients with programmatic tool use (future).
|
|
86
|
-
enable_dashboard_partial_tools: bool = Field(
|
|
90
|
+
enable_dashboard_partial_tools: bool = Field(
|
|
91
|
+
True, alias="ENABLE_DASHBOARD_PARTIAL_TOOLS"
|
|
92
|
+
)
|
|
87
93
|
|
|
88
94
|
# Skills configuration
|
|
89
95
|
# Serve bundled HA best-practice skills as MCP resources (skill:// URIs).
|
|
@@ -101,6 +107,11 @@ class Settings(BaseSettings):
|
|
|
101
107
|
# Dramatically reduces idle context token usage for LLMs.
|
|
102
108
|
enable_tool_search: bool = Field(False, alias="ENABLE_TOOL_SEARCH")
|
|
103
109
|
|
|
110
|
+
# Managed YAML config editing — allows ha_config_set_yaml to add,
|
|
111
|
+
# replace, or remove top-level keys in configuration.yaml and package
|
|
112
|
+
# files. Disabled by default; only for YAML-only features with no UI/API path.
|
|
113
|
+
enable_yaml_config_editing: bool = Field(False, alias="ENABLE_YAML_CONFIG_EDITING")
|
|
114
|
+
|
|
104
115
|
@model_validator(mode="after")
|
|
105
116
|
def _skills_dependency(self) -> "Settings":
|
|
106
117
|
"""Auto-enable skills (resources) when skills-as-tools is on.
|
|
@@ -380,6 +380,11 @@ class HomeAssistantSmartMCPServer(EnhancedToolsMixin):
|
|
|
380
380
|
"create update modify edit script sequence actions "
|
|
381
381
|
"new script write save"
|
|
382
382
|
),
|
|
383
|
+
"ha_config_set_yaml": (
|
|
384
|
+
"edit yaml configuration.yaml packages template sensor "
|
|
385
|
+
"binary_sensor command_line rest mqtt platform yaml-only "
|
|
386
|
+
"config file modify add remove replace"
|
|
387
|
+
),
|
|
383
388
|
}
|
|
384
389
|
|
|
385
390
|
# Description overrides that REPLACE the original description for BM25.
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Managed YAML configuration editing tools for Home Assistant MCP Server.
|
|
3
|
+
|
|
4
|
+
Provides a structured, validated tool for editing YAML configuration files
|
|
5
|
+
(configuration.yaml and package files) for Home Assistant features that exist
|
|
6
|
+
only in YAML and have no REST/WebSocket API equivalent.
|
|
7
|
+
|
|
8
|
+
**Dependency:** Requires the ha_mcp_tools custom component to be installed.
|
|
9
|
+
The tools will gracefully fail with installation instructions if the component is not available.
|
|
10
|
+
|
|
11
|
+
Feature Flag: Set ENABLE_YAML_CONFIG_EDITING=true to enable.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import logging
|
|
15
|
+
from typing import Annotated, Any
|
|
16
|
+
|
|
17
|
+
from fastmcp.exceptions import ToolError
|
|
18
|
+
from pydantic import Field
|
|
19
|
+
|
|
20
|
+
from ..config import get_global_settings
|
|
21
|
+
from ..errors import ErrorCode, create_error_response
|
|
22
|
+
from .helpers import exception_to_structured_error, log_tool_usage, raise_tool_error
|
|
23
|
+
from .tools_filesystem import (
|
|
24
|
+
MCP_TOOLS_DOMAIN,
|
|
25
|
+
_assert_mcp_tools_available,
|
|
26
|
+
)
|
|
27
|
+
from .util_helpers import add_timezone_metadata, coerce_bool_param
|
|
28
|
+
|
|
29
|
+
logger = logging.getLogger(__name__)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def register_yaml_config_tools(mcp: Any, client: Any, **kwargs: Any) -> None:
|
|
33
|
+
"""Register YAML config editing tools with the MCP server.
|
|
34
|
+
|
|
35
|
+
Requires ENABLE_YAML_CONFIG_EDITING=true.
|
|
36
|
+
"""
|
|
37
|
+
settings = get_global_settings()
|
|
38
|
+
if not settings.enable_yaml_config_editing:
|
|
39
|
+
logger.debug(
|
|
40
|
+
"YAML config tools disabled (set ENABLE_YAML_CONFIG_EDITING=true to enable)"
|
|
41
|
+
)
|
|
42
|
+
return
|
|
43
|
+
|
|
44
|
+
logger.info("YAML config editing tools enabled")
|
|
45
|
+
|
|
46
|
+
@mcp.tool(
|
|
47
|
+
annotations={
|
|
48
|
+
"destructiveHint": True,
|
|
49
|
+
"idempotentHint": False,
|
|
50
|
+
"tags": ["filesystem", "config", "yaml"],
|
|
51
|
+
"title": "Set YAML Config",
|
|
52
|
+
}
|
|
53
|
+
)
|
|
54
|
+
@log_tool_usage
|
|
55
|
+
async def ha_config_set_yaml(
|
|
56
|
+
yaml_path: Annotated[
|
|
57
|
+
str,
|
|
58
|
+
Field(
|
|
59
|
+
description=(
|
|
60
|
+
"Top-level YAML key to modify (e.g., 'template', 'sensor', "
|
|
61
|
+
"'input_boolean'). Only whitelisted keys are allowed."
|
|
62
|
+
),
|
|
63
|
+
),
|
|
64
|
+
],
|
|
65
|
+
action: Annotated[
|
|
66
|
+
str,
|
|
67
|
+
Field(
|
|
68
|
+
description=(
|
|
69
|
+
"Action to perform: 'add' (insert/merge content under key), "
|
|
70
|
+
"'replace' (overwrite key with new content), or "
|
|
71
|
+
"'remove' (delete the key entirely)."
|
|
72
|
+
),
|
|
73
|
+
),
|
|
74
|
+
],
|
|
75
|
+
content: Annotated[
|
|
76
|
+
str | None,
|
|
77
|
+
Field(
|
|
78
|
+
default=None,
|
|
79
|
+
description=(
|
|
80
|
+
"YAML content for the value under yaml_path. Required for "
|
|
81
|
+
"'add' and 'replace' actions. Must be valid YAML."
|
|
82
|
+
),
|
|
83
|
+
),
|
|
84
|
+
] = None,
|
|
85
|
+
file: Annotated[
|
|
86
|
+
str,
|
|
87
|
+
Field(
|
|
88
|
+
default="configuration.yaml",
|
|
89
|
+
description=(
|
|
90
|
+
"Relative path to the YAML config file. Defaults to "
|
|
91
|
+
"'configuration.yaml'. Also supports 'packages/*.yaml'."
|
|
92
|
+
),
|
|
93
|
+
),
|
|
94
|
+
] = "configuration.yaml",
|
|
95
|
+
backup: Annotated[
|
|
96
|
+
bool | str,
|
|
97
|
+
Field(
|
|
98
|
+
default=True,
|
|
99
|
+
description=(
|
|
100
|
+
"Create a backup before editing. Defaults to True. "
|
|
101
|
+
"Backups are saved to www/yaml_backups/."
|
|
102
|
+
),
|
|
103
|
+
),
|
|
104
|
+
] = True,
|
|
105
|
+
) -> dict[str, Any]:
|
|
106
|
+
"""Add, replace, or remove a top-level key in configuration.yaml or package files.
|
|
107
|
+
|
|
108
|
+
IMPORTANT: Only use when NO UI or API alternative exists. Prefer:
|
|
109
|
+
- Template sensors -> ha_config_set_helper (Template Helper)
|
|
110
|
+
- Automations -> ha_config_set_automation
|
|
111
|
+
- Scripts -> ha_config_set_script
|
|
112
|
+
- Input helpers -> ha_config_set_helper
|
|
113
|
+
- Scenes -> ha_config_set_scene
|
|
114
|
+
|
|
115
|
+
This tool is for YAML-only features with no UI/API path (e.g.,
|
|
116
|
+
command_line sensors, platform-based MQTT sensors in YAML, rest
|
|
117
|
+
sensors defined in packages).
|
|
118
|
+
|
|
119
|
+
Safeguards: file backup, YAML validation, top-level key whitelist,
|
|
120
|
+
path traversal blocking, post-edit config check.
|
|
121
|
+
|
|
122
|
+
IMPORTANT: Check 'post_action' in the response. Most keys require
|
|
123
|
+
a full HA restart ('restart_required'). Only template, mqtt, and
|
|
124
|
+
group support reload ('reload_available' with 'reload_service').
|
|
125
|
+
|
|
126
|
+
Note: YAML comments are not preserved after editing. The backup
|
|
127
|
+
retains the original file with comments intact.
|
|
128
|
+
"""
|
|
129
|
+
try:
|
|
130
|
+
# Validate action
|
|
131
|
+
valid_actions = ("add", "replace", "remove")
|
|
132
|
+
if action not in valid_actions:
|
|
133
|
+
raise_tool_error(
|
|
134
|
+
create_error_response(
|
|
135
|
+
ErrorCode.VALIDATION_INVALID_PARAMETER,
|
|
136
|
+
f"Invalid action '{action}'. Must be one of: {', '.join(valid_actions)}",
|
|
137
|
+
suggestions=[
|
|
138
|
+
"Use action='add' to insert content under a key",
|
|
139
|
+
"Use action='replace' to overwrite a key's content",
|
|
140
|
+
"Use action='remove' to delete a key entirely",
|
|
141
|
+
],
|
|
142
|
+
)
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
# Validate content is provided for add/replace
|
|
146
|
+
if action in ("add", "replace") and not content:
|
|
147
|
+
raise_tool_error(
|
|
148
|
+
create_error_response(
|
|
149
|
+
ErrorCode.VALIDATION_INVALID_PARAMETER,
|
|
150
|
+
f"'content' is required for action '{action}'.",
|
|
151
|
+
suggestions=[
|
|
152
|
+
"Provide valid YAML content to insert or replace."
|
|
153
|
+
],
|
|
154
|
+
)
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
# Coerce boolean parameter
|
|
158
|
+
backup_bool = coerce_bool_param(backup, "backup", default=True)
|
|
159
|
+
|
|
160
|
+
# Check if custom component is available
|
|
161
|
+
await _assert_mcp_tools_available(client)
|
|
162
|
+
|
|
163
|
+
# Build service data
|
|
164
|
+
service_data: dict[str, Any] = {
|
|
165
|
+
"file": file,
|
|
166
|
+
"action": action,
|
|
167
|
+
"yaml_path": yaml_path,
|
|
168
|
+
"backup": backup_bool,
|
|
169
|
+
}
|
|
170
|
+
if content is not None:
|
|
171
|
+
service_data["content"] = content
|
|
172
|
+
|
|
173
|
+
# Call the custom component service
|
|
174
|
+
result = await client.call_service(
|
|
175
|
+
MCP_TOOLS_DOMAIN,
|
|
176
|
+
"edit_yaml_config",
|
|
177
|
+
service_data,
|
|
178
|
+
return_response=True,
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
if isinstance(result, dict):
|
|
182
|
+
if not result.get("success", True):
|
|
183
|
+
raise_tool_error(result)
|
|
184
|
+
return await add_timezone_metadata(client, result)
|
|
185
|
+
|
|
186
|
+
raise_tool_error(
|
|
187
|
+
create_error_response(
|
|
188
|
+
ErrorCode.SERVICE_CALL_FAILED,
|
|
189
|
+
"Unexpected response format from YAML config service",
|
|
190
|
+
context={"file": file},
|
|
191
|
+
)
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
except ToolError:
|
|
195
|
+
raise
|
|
196
|
+
except Exception as e:
|
|
197
|
+
exception_to_structured_error(
|
|
198
|
+
e,
|
|
199
|
+
context={
|
|
200
|
+
"tool": "ha_config_set_yaml",
|
|
201
|
+
"file": file,
|
|
202
|
+
"action": action,
|
|
203
|
+
"yaml_path": yaml_path,
|
|
204
|
+
},
|
|
205
|
+
)
|
|
@@ -76,6 +76,7 @@ src/ha_mcp/tools/tools_traces.py
|
|
|
76
76
|
src/ha_mcp/tools/tools_updates.py
|
|
77
77
|
src/ha_mcp/tools/tools_utility.py
|
|
78
78
|
src/ha_mcp/tools/tools_voice_assistant.py
|
|
79
|
+
src/ha_mcp/tools/tools_yaml_config.py
|
|
79
80
|
src/ha_mcp/tools/tools_zones.py
|
|
80
81
|
src/ha_mcp/tools/util_helpers.py
|
|
81
82
|
src/ha_mcp/transforms/__init__.py
|
|
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.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/resources/skills-vendor/AGENTS.md
RENAMED
|
File without changes
|
{ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/resources/skills-vendor/CLAUDE.md
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/resources/skills-vendor/LICENSE
RENAMED
|
File without changes
|
{ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/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
|
{ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/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
|
{ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/tools/tools_config_automations.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/tools/tools_config_dashboards.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/tools/tools_config_entry_flow.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/tools/tools_config_helpers.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/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
|
{ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp/tools/tools_voice_assistant.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
|
{ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/src/ha_mcp_dev.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{ha_mcp_dev-7.1.0.dev308 → ha_mcp_dev-7.1.0.dev309}/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
|