ha-mcp-dev 7.4.1.dev466__tar.gz → 7.4.1.dev468__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.4.1.dev466/src/ha_mcp_dev.egg-info → ha_mcp_dev-7.4.1.dev468}/PKG-INFO +1 -1
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/pyproject.toml +1 -1
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/server.py +8 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/tools_addons.py +10 -8
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/tools_config_dashboards.py +59 -22
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468/src/ha_mcp_dev.egg-info}/PKG-INFO +1 -1
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/LICENSE +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/MANIFEST.in +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/README.md +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/setup.cfg +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/__init__.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/__main__.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/_pypi_marker +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/_version.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/auth/__init__.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/auth/consent_form.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/auth/provider.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/client/__init__.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/client/rest_client.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/client/websocket_client.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/client/websocket_listener.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/config.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/errors.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/py.typed +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/resources/skills-vendor/.claude/settings.json +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/resources/skills-vendor/.claude-plugin/marketplace.json +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/resources/skills-vendor/.claude-plugin/plugin.json +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/resources/skills-vendor/.github/ISSUE_TEMPLATE/skill-rca.md +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/resources/skills-vendor/AGENTS.md +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/resources/skills-vendor/CLAUDE.md +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/resources/skills-vendor/CONTRIBUTING.md +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/resources/skills-vendor/LICENSE +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/resources/skills-vendor/README.md +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/SKILL.md +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/evals/evals.json +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/automation-patterns.md +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-cards.md +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-guide.md +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/device-control.md +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/domain-docs.md +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/examples.yaml +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/helper-selection.md +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/safe-refactoring.md +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/template-guidelines.md +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/settings_ui.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/smoke_test.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/__init__.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/backup.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/best_practice_checker.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/device_control.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/enhanced.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/helpers.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/reference_validator.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/registry.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/smart_search.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/tools_areas.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/tools_blueprints.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/tools_bug_report.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/tools_calendar.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/tools_camera.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/tools_categories.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/tools_code.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/tools_config_automations.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/tools_config_entry_flow.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/tools_config_helpers.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/tools_config_scenes.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/tools_config_scripts.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/tools_energy.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/tools_entities.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/tools_filesystem.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/tools_groups.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/tools_hacs.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/tools_history.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/tools_integrations.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/tools_labels.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/tools_mcp_component.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/tools_registry.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/tools_resources.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/tools_search.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/tools_service.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/tools_services.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/tools_system.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/tools_todo.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/tools_traces.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/tools_updates.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/tools_utility.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/tools_voice_assistant.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/tools_yaml_config.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/tools_zones.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/util_helpers.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/transforms/__init__.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/transforms/categorized_search.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/utils/__init__.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/utils/config_hash.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/utils/data_paths.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/utils/domain_handlers.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/utils/fuzzy_search.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/utils/kill_signal_diagnostics.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/utils/operation_manager.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/utils/python_sandbox.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/utils/usage_logger.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp_dev.egg-info/SOURCES.txt +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp_dev.egg-info/dependency_links.txt +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp_dev.egg-info/entry_points.txt +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp_dev.egg-info/requires.txt +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp_dev.egg-info/top_level.txt +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/tests/__init__.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/tests/test_constants.py +0 -0
- {ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/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.4.1.
|
|
7
|
+
version = "7.4.1.dev468"
|
|
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"
|
|
@@ -525,6 +525,14 @@ class HomeAssistantSmartMCPServer(EnhancedToolsMixin):
|
|
|
525
525
|
"binary_sensor command_line rest mqtt platform yaml-only "
|
|
526
526
|
"config file modify add remove replace"
|
|
527
527
|
),
|
|
528
|
+
"ha_manage_addon": (
|
|
529
|
+
"manage addon add-on configure settings options port network boot "
|
|
530
|
+
"watchdog auto_update supervisor ingress proxy websocket api rest "
|
|
531
|
+
"esphome nodered node-red frigate mosquitto mqtt zigbee2mqtt zigbee "
|
|
532
|
+
"z-wave zwave appdaemon hacs studio code server file editor terminal "
|
|
533
|
+
"ssh samba grafana influxdb deconz motioneye compile validate upload "
|
|
534
|
+
"deploy firmware ota flash yaml device logs flows events stats"
|
|
535
|
+
),
|
|
528
536
|
}
|
|
529
537
|
|
|
530
538
|
# Description overrides that REPLACE the original description for BM25.
|
|
@@ -507,7 +507,7 @@ async def get_addon_info(client: HomeAssistantClient, slug: str) -> dict[str, An
|
|
|
507
507
|
|
|
508
508
|
Args:
|
|
509
509
|
client: Home Assistant REST client
|
|
510
|
-
slug: Add-on slug (e.g., "
|
|
510
|
+
slug: Add-on slug (e.g., "<prefix>_nodered")
|
|
511
511
|
|
|
512
512
|
Returns:
|
|
513
513
|
Dictionary with add-on details including ingress info, state, options, etc.
|
|
@@ -740,7 +740,7 @@ async def _call_addon_ws(
|
|
|
740
740
|
|
|
741
741
|
Args:
|
|
742
742
|
client: Home Assistant REST client
|
|
743
|
-
slug: Add-on slug (e.g., "
|
|
743
|
+
slug: Add-on slug (e.g., "<prefix>_esphome")
|
|
744
744
|
path: WebSocket endpoint path (e.g., "/compile", "/validate")
|
|
745
745
|
body: Message to send after connecting (JSON-encoded if dict, raw if string)
|
|
746
746
|
timeout: Max seconds to wait for messages (default 60)
|
|
@@ -1081,7 +1081,7 @@ async def _call_addon_api(
|
|
|
1081
1081
|
|
|
1082
1082
|
Args:
|
|
1083
1083
|
client: Home Assistant REST client
|
|
1084
|
-
slug: Add-on slug (e.g., "
|
|
1084
|
+
slug: Add-on slug (e.g., "<prefix>_nodered")
|
|
1085
1085
|
path: API path relative to add-on root (e.g., "/flows")
|
|
1086
1086
|
method: HTTP method (GET, POST, PUT, DELETE, PATCH)
|
|
1087
1087
|
body: Request body for POST/PUT/PATCH
|
|
@@ -1349,8 +1349,9 @@ def register_addon_tools(mcp: Any, client: HomeAssistantClient, **kwargs: Any) -
|
|
|
1349
1349
|
slug: Annotated[
|
|
1350
1350
|
str | None,
|
|
1351
1351
|
Field(
|
|
1352
|
-
description="Add-on slug for detailed info (e.g., '
|
|
1353
|
-
"
|
|
1352
|
+
description="Add-on slug for detailed info (e.g., '<prefix>_nodered'). "
|
|
1353
|
+
"Slug prefixes vary by add-on repository — omit to list all add-ons "
|
|
1354
|
+
"and discover the actual installed slug.",
|
|
1354
1355
|
default=None,
|
|
1355
1356
|
),
|
|
1356
1357
|
] = None,
|
|
@@ -1402,7 +1403,7 @@ def register_addon_tools(mcp: Any, client: HomeAssistantClient, **kwargs: Any) -
|
|
|
1402
1403
|
|
|
1403
1404
|
**Example Usage:**
|
|
1404
1405
|
- List installed add-ons: ha_get_addon()
|
|
1405
|
-
- Get Node-RED details: ha_get_addon(slug="
|
|
1406
|
+
- Get Node-RED details: ha_get_addon(slug="<prefix>_nodered")
|
|
1406
1407
|
- List with resource usage: ha_get_addon(include_stats=True)
|
|
1407
1408
|
- List available add-ons: ha_get_addon(source="available")
|
|
1408
1409
|
- Search for MQTT: ha_get_addon(source="available", query="mqtt")
|
|
@@ -1448,8 +1449,9 @@ def register_addon_tools(mcp: Any, client: HomeAssistantClient, **kwargs: Any) -
|
|
|
1448
1449
|
slug: Annotated[
|
|
1449
1450
|
str,
|
|
1450
1451
|
Field(
|
|
1451
|
-
description="Add-on slug (e.g., '
|
|
1452
|
-
"
|
|
1452
|
+
description="Add-on slug (e.g., '<prefix>_nodered', '<prefix>_frigate'). "
|
|
1453
|
+
"Slug prefixes vary by add-on repository — call ha_get_addon() "
|
|
1454
|
+
"to discover the actual installed slug.",
|
|
1453
1455
|
),
|
|
1454
1456
|
],
|
|
1455
1457
|
path: Annotated[
|
{ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/tools_config_dashboards.py
RENAMED
|
@@ -265,22 +265,37 @@ def _should_lazy_resolve(error_msg: str) -> bool:
|
|
|
265
265
|
return _LAZY_RESOLVE_TRIGGER in error_msg
|
|
266
266
|
|
|
267
267
|
|
|
268
|
-
async def _resolve_dashboard(
|
|
268
|
+
async def _resolve_dashboard(
|
|
269
|
+
client: Any, identifier: str
|
|
270
|
+
) -> tuple[dict[str, str] | None, list[dict[str, Any]] | None]:
|
|
269
271
|
"""Resolve a dashboard identifier (url_path or internal id) to both forms.
|
|
270
272
|
|
|
271
|
-
Calls ``lovelace/dashboards/list`` and returns
|
|
272
|
-
``
|
|
273
|
-
on a registry entry that has both fields populated; otherwise returns
|
|
274
|
-
``None``. Always pays the round-trip when called.
|
|
273
|
+
Calls ``lovelace/dashboards/list`` and returns a 2-tuple
|
|
274
|
+
``(match, dashboards)``:
|
|
275
275
|
|
|
276
|
-
|
|
276
|
+
- ``match`` is ``{"url_path": ..., "id": ...}`` when the identifier
|
|
277
|
+
matches either field on a registry entry that has both fields
|
|
278
|
+
populated; otherwise ``None``.
|
|
279
|
+
- ``dashboards`` is the raw list as returned by HA when the
|
|
280
|
+
response shape is recognised (dict-with-``result`` or bare list);
|
|
281
|
+
``None`` when the shape was unexpected and a warning was logged.
|
|
282
|
+
|
|
283
|
+
Returning ``dashboards`` alongside ``match`` lets callers reuse the
|
|
284
|
+
list for follow-on checks (existence, id lookup) instead of paying
|
|
285
|
+
a second ``lovelace/dashboards/list`` round-trip.
|
|
286
|
+
|
|
287
|
+
Three call sites:
|
|
277
288
|
- **Lazy fallback** (``_lazy_resolve_and_retry``): only invoked after
|
|
278
289
|
``lovelace/config`` rejected the identifier with
|
|
279
290
|
``_LAZY_RESOLVE_TRIGGER`` — the round-trip is gated by the caller.
|
|
291
|
+
Discards ``dashboards``.
|
|
280
292
|
- **Eager pre-resolve** (``ha_config_set_dashboard``): invoked before
|
|
281
293
|
hyphen validation so callers may pass either form; gated on a
|
|
282
294
|
cheap heuristic ("no hyphen, not 'lovelace'") rather than an error
|
|
283
|
-
from HA.
|
|
295
|
+
from HA. Reuses ``dashboards`` for the existence-check below.
|
|
296
|
+
- **Delete** (``ha_config_delete_dashboard``): resolves either form
|
|
297
|
+
to the registry id before issuing the delete. Discards
|
|
298
|
+
``dashboards``.
|
|
284
299
|
"""
|
|
285
300
|
result = await client.send_websocket_message({"type": "lovelace/dashboards/list"})
|
|
286
301
|
if isinstance(result, dict) and "result" in result:
|
|
@@ -297,7 +312,7 @@ async def _resolve_dashboard(client: Any, identifier: str) -> dict[str, str] | N
|
|
|
297
312
|
"treating as no-match",
|
|
298
313
|
type(result).__name__,
|
|
299
314
|
)
|
|
300
|
-
return None
|
|
315
|
+
return None, None
|
|
301
316
|
|
|
302
317
|
for d in dashboards:
|
|
303
318
|
if d.get("id") == identifier or d.get("url_path") == identifier:
|
|
@@ -309,8 +324,8 @@ async def _resolve_dashboard(client: Any, identifier: str) -> dict[str, str] | N
|
|
|
309
324
|
# would be silently used by callers (e.g.
|
|
310
325
|
# ``delete_dashboard`` would forward ``resolved_id=""``).
|
|
311
326
|
continue
|
|
312
|
-
return {"url_path": url_path, "id": entry_id}
|
|
313
|
-
return None
|
|
327
|
+
return {"url_path": url_path, "id": entry_id}, dashboards
|
|
328
|
+
return None, dashboards
|
|
314
329
|
|
|
315
330
|
|
|
316
331
|
@overload
|
|
@@ -376,7 +391,7 @@ async def _lazy_resolve_and_retry(
|
|
|
376
391
|
return url_path, response
|
|
377
392
|
|
|
378
393
|
try:
|
|
379
|
-
resolved = await _resolve_dashboard(client, url_path)
|
|
394
|
+
resolved, _ = await _resolve_dashboard(client, url_path)
|
|
380
395
|
except Exception as resolver_exc:
|
|
381
396
|
# Resolver itself raised (timeout, network blip, etc.). Don't let
|
|
382
397
|
# this exception escape and replace the original HA error with
|
|
@@ -941,12 +956,18 @@ def register_config_dashboard_tools(mcp: Any, client: Any, **kwargs: Any) -> Non
|
|
|
941
956
|
# ``resolved_from`` on the success response so callers can
|
|
942
957
|
# detect this redirect.
|
|
943
958
|
pre_resolved_from: str | None = None
|
|
959
|
+
# When the pre-resolver fires and finds a match, ``_resolve_dashboard``
|
|
960
|
+
# has already fetched ``lovelace/dashboards/list``. Capture that list
|
|
961
|
+
# so the existence-check site below can reuse it instead of paying
|
|
962
|
+
# a second round-trip.
|
|
963
|
+
pre_fetched_dashboards: list[dict[str, Any]] | None = None
|
|
944
964
|
if "-" not in url_path and url_path != "lovelace":
|
|
945
|
-
resolved = await _resolve_dashboard(client, url_path)
|
|
965
|
+
resolved, dashboards = await _resolve_dashboard(client, url_path)
|
|
946
966
|
if resolved is not None and resolved["url_path"]:
|
|
947
967
|
original_url_path = url_path
|
|
948
968
|
url_path = resolved["url_path"]
|
|
949
969
|
pre_resolved_from = original_url_path
|
|
970
|
+
pre_fetched_dashboards = dashboards
|
|
950
971
|
logger.info(
|
|
951
972
|
"ha_config_set_dashboard pre-resolver mapped %r -> %r",
|
|
952
973
|
original_url_path,
|
|
@@ -1129,16 +1150,32 @@ def register_config_dashboard_tools(mcp: Any, client: Any, **kwargs: Any) -> Non
|
|
|
1129
1150
|
transform_result["resolved_from"] = pre_resolved_from
|
|
1130
1151
|
return transform_result
|
|
1131
1152
|
|
|
1132
|
-
# Check if dashboard exists
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
existing_dashboards = result
|
|
1153
|
+
# Check if dashboard exists. When the pre-resolver fired
|
|
1154
|
+
# and matched (internal-id branch), reuse its already-fetched
|
|
1155
|
+
# ``lovelace/dashboards/list`` response to skip a redundant
|
|
1156
|
+
# round-trip — the matched dashboard is guaranteed present in
|
|
1157
|
+
# that list.
|
|
1158
|
+
if pre_fetched_dashboards is not None:
|
|
1159
|
+
existing_dashboards = pre_fetched_dashboards
|
|
1140
1160
|
else:
|
|
1141
|
-
|
|
1161
|
+
result = await client.send_websocket_message(
|
|
1162
|
+
{"type": "lovelace/dashboards/list"}
|
|
1163
|
+
)
|
|
1164
|
+
if isinstance(result, dict) and "result" in result:
|
|
1165
|
+
existing_dashboards = result["result"]
|
|
1166
|
+
elif isinstance(result, list):
|
|
1167
|
+
existing_dashboards = result
|
|
1168
|
+
else:
|
|
1169
|
+
# Mirror the warning emitted by ``_resolve_dashboard`` on
|
|
1170
|
+
# the same response-shape failure, so a future HA shape
|
|
1171
|
+
# change shows up at every fetch site rather than going
|
|
1172
|
+
# silent on this one.
|
|
1173
|
+
logger.warning(
|
|
1174
|
+
"lovelace/dashboards/list returned an unexpected shape "
|
|
1175
|
+
"(type=%s); treating as no-match",
|
|
1176
|
+
type(result).__name__,
|
|
1177
|
+
)
|
|
1178
|
+
existing_dashboards = []
|
|
1142
1179
|
dashboard_exists = any(
|
|
1143
1180
|
d.get("url_path") == url_path for d in existing_dashboards
|
|
1144
1181
|
)
|
|
@@ -1407,7 +1444,7 @@ def register_config_dashboard_tools(mcp: Any, client: Any, **kwargs: Any) -> Non
|
|
|
1407
1444
|
Note: The default dashboard cannot be deleted via this method.
|
|
1408
1445
|
"""
|
|
1409
1446
|
try:
|
|
1410
|
-
resolved = await _resolve_dashboard(client, url_path)
|
|
1447
|
+
resolved, _ = await _resolve_dashboard(client, url_path)
|
|
1411
1448
|
if resolved is None:
|
|
1412
1449
|
raise_tool_error(
|
|
1413
1450
|
create_resource_not_found_error(
|
|
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.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/resources/skills-vendor/AGENTS.md
RENAMED
|
File without changes
|
{ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/resources/skills-vendor/CLAUDE.md
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/resources/skills-vendor/LICENSE
RENAMED
|
File without changes
|
{ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/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
|
{ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/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
|
{ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/tools_config_automations.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/tools_config_entry_flow.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/tools/tools_config_helpers.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/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.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/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.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp/transforms/categorized_search.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/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.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/src/ha_mcp_dev.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{ha_mcp_dev-7.4.1.dev466 → ha_mcp_dev-7.4.1.dev468}/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
|