ha-mcp-dev 7.6.0.dev637__tar.gz → 7.6.0.dev638__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.6.0.dev637/src/ha_mcp_dev.egg-info → ha_mcp_dev-7.6.0.dev638}/PKG-INFO +1 -1
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/pyproject.toml +1 -1
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/settings_ui.py +79 -10
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638/src/ha_mcp_dev.egg-info}/PKG-INFO +1 -1
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/LICENSE +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/MANIFEST.in +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/README.md +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/setup.cfg +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/__init__.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/__main__.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/_pypi_marker +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/_version.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/auth/__init__.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/auth/consent_form.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/auth/provider.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/backup_manager.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/client/__init__.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/client/rest_client.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/client/supervisor_client.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/client/websocket_client.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/client/websocket_listener.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/config.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/errors.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/policy/__init__.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/policy/approval_queue.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/policy/evaluator.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/policy/handlers.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/policy/middleware.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/policy/model.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/policy/persistence.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/policy/value_sources.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/py.typed +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/resources/skills-vendor/.claude/settings.json +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/resources/skills-vendor/.claude-plugin/marketplace.json +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/resources/skills-vendor/.claude-plugin/plugin.json +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/resources/skills-vendor/.github/ISSUE_TEMPLATE/skill-rca.md +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/resources/skills-vendor/.github/pull_request_template.md +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/resources/skills-vendor/AGENTS.md +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/resources/skills-vendor/CLAUDE.md +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/resources/skills-vendor/CONTRIBUTING.md +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/resources/skills-vendor/LICENSE +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/resources/skills-vendor/README.md +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/SKILL.md +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/evals/evals.json +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/automation-patterns.md +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-cards.md +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-guide.md +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/device-control.md +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/domain-docs.md +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/examples.yaml +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/helper-selection.md +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/safe-refactoring.md +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/template-guidelines.md +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/yaml-only-integrations.md +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/server.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/settings.css +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/settings.js +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/smoke_test.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/stdio_settings_sidecar.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/__init__.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/auto_backup.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/backup.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/best_practice_checker.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/device_control.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/enhanced.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/helpers.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/reference_validator.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/registry.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/smart_search.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/tools_addons.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/tools_areas.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/tools_blueprints.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/tools_bug_report.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/tools_calendar.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/tools_camera.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/tools_categories.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/tools_code.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/tools_config_automations.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/tools_config_dashboards.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/tools_config_entry_flow.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/tools_config_helpers.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/tools_config_scenes.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/tools_config_scripts.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/tools_energy.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/tools_entities.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/tools_filesystem.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/tools_groups.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/tools_hacs.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/tools_history.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/tools_integrations.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/tools_labels.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/tools_mcp_component.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/tools_registry.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/tools_resources.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/tools_search.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/tools_service.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/tools_services.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/tools_system.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/tools_todo.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/tools_traces.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/tools_updates.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/tools_utility.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/tools_voice_assistant.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/tools_yaml_config.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/tools_zones.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/util_helpers.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/validation_middleware.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/transforms/__init__.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/transforms/categorized_search.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/transforms/lite_docstrings.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/utils/__init__.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/utils/config_hash.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/utils/data_paths.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/utils/domain_handlers.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/utils/fuzzy_search.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/utils/kill_signal_diagnostics.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/utils/operation_manager.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/utils/python_sandbox.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/utils/skill_loader.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/utils/usage_logger.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp_dev.egg-info/SOURCES.txt +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp_dev.egg-info/dependency_links.txt +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp_dev.egg-info/entry_points.txt +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp_dev.egg-info/requires.txt +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp_dev.egg-info/top_level.txt +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/tests/__init__.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/tests/test_constants.py +0 -0
- {ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/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.6.0.
|
|
7
|
+
version = "7.6.0.dev638"
|
|
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"
|
|
@@ -11,17 +11,19 @@ from __future__ import annotations
|
|
|
11
11
|
|
|
12
12
|
import asyncio
|
|
13
13
|
import contextlib
|
|
14
|
+
import functools
|
|
14
15
|
import json
|
|
15
16
|
import logging
|
|
16
17
|
import os
|
|
17
18
|
import time
|
|
18
19
|
import uuid
|
|
20
|
+
from collections.abc import Awaitable, Callable
|
|
19
21
|
from pathlib import Path
|
|
20
22
|
from typing import TYPE_CHECKING, Any, Literal, NamedTuple, NotRequired, TypedDict
|
|
21
23
|
|
|
22
24
|
import httpx
|
|
23
25
|
from starlette.requests import Request
|
|
24
|
-
from starlette.responses import HTMLResponse, JSONResponse
|
|
26
|
+
from starlette.responses import HTMLResponse, JSONResponse, Response
|
|
25
27
|
|
|
26
28
|
from ._version import get_version, is_running_in_addon
|
|
27
29
|
from .backup_manager import get_backup_manager
|
|
@@ -2956,6 +2958,65 @@ def build_settings_handlers(
|
|
|
2956
2958
|
return handlers
|
|
2957
2959
|
|
|
2958
2960
|
|
|
2961
|
+
# Home Assistant proxies every ingress request ("Open Web UI") from the
|
|
2962
|
+
# Supervisor's fixed network address. Per the add-on ingress contract
|
|
2963
|
+
# (https://developers.home-assistant.io/docs/add-ons/presentation/#ingress —
|
|
2964
|
+
# "Only connections from 172.30.32.2 must be allowed") the app must reject
|
|
2965
|
+
# every other source. This holds under host_network too: ingress proxies to
|
|
2966
|
+
# http://{app.ip_address}:{ingress_port}/, and for a host-network add-on
|
|
2967
|
+
# app.ip_address is the hassio bridge gateway 172.30.32.1 — the DESTINATION the
|
|
2968
|
+
# Supervisor dials (supervisor/docker/app.py ip_address(): host_network ->
|
|
2969
|
+
# network.gateway). The Supervisor opens that connection from its own container
|
|
2970
|
+
# address 172.30.32.2, so the transport peer the add-on sees is 172.30.32.2 for
|
|
2971
|
+
# genuine ingress and some other address (a LAN host, the cloudflared tunnel at
|
|
2972
|
+
# 172.30.33.x, another add-on) for a direct port-9583 hit. Verified live via
|
|
2973
|
+
# netstat during an "Open Web UI" click.
|
|
2974
|
+
SUPERVISOR_INGRESS_IP = "172.30.32.2"
|
|
2975
|
+
|
|
2976
|
+
# A settings-UI route handler: async (Request) -> Response.
|
|
2977
|
+
_SettingsRoute = Callable[[Request], Awaitable[Response]]
|
|
2978
|
+
|
|
2979
|
+
|
|
2980
|
+
def _ingress_only(handler: _SettingsRoute) -> _SettingsRoute:
|
|
2981
|
+
"""Wrap a root-mounted add-on route so only HA ingress can reach it.
|
|
2982
|
+
|
|
2983
|
+
Add-on root routes carry no MCP secret, so without this guard a direct
|
|
2984
|
+
caller on the published port — a LAN peer, a reverse proxy / tunnel
|
|
2985
|
+
forwarding the bare root, or a CSRF POST from a LAN browser — could
|
|
2986
|
+
rewrite tool config, flip the tool-security-policy, or restart the
|
|
2987
|
+
add-on with no authentication. We gate on the *transport* peer
|
|
2988
|
+
(``request.client.host``), never ``X-Forwarded-For`` (which a caller can
|
|
2989
|
+
forge). The same handlers stay reachable under ``secret_prefix``, where
|
|
2990
|
+
the MCP secret path is the auth for direct/remote access.
|
|
2991
|
+
"""
|
|
2992
|
+
|
|
2993
|
+
@functools.wraps(handler)
|
|
2994
|
+
async def _guarded(request: Request) -> Response:
|
|
2995
|
+
peer = request.client.host if request.client else None
|
|
2996
|
+
if peer != SUPERVISOR_INGRESS_IP:
|
|
2997
|
+
logger.warning(
|
|
2998
|
+
"Blocked non-ingress request to add-on root route %s from "
|
|
2999
|
+
"peer %r (only the Supervisor at %s may reach root routes; "
|
|
3000
|
+
"use the MCP secret path for direct/remote access).",
|
|
3001
|
+
request.url.path,
|
|
3002
|
+
peer,
|
|
3003
|
+
SUPERVISOR_INGRESS_IP,
|
|
3004
|
+
)
|
|
3005
|
+
return JSONResponse(
|
|
3006
|
+
{
|
|
3007
|
+
"error": (
|
|
3008
|
+
"This endpoint is only reachable through Home "
|
|
3009
|
+
"Assistant ingress. For direct or remote access, use "
|
|
3010
|
+
"the settings UI under your MCP secret path."
|
|
3011
|
+
)
|
|
3012
|
+
},
|
|
3013
|
+
status_code=403,
|
|
3014
|
+
)
|
|
3015
|
+
return await handler(request)
|
|
3016
|
+
|
|
3017
|
+
return _guarded
|
|
3018
|
+
|
|
3019
|
+
|
|
2959
3020
|
def register_settings_routes(
|
|
2960
3021
|
mcp: FastMCP,
|
|
2961
3022
|
server: HomeAssistantSmartMCPServer,
|
|
@@ -3030,18 +3091,26 @@ def register_settings_routes(
|
|
|
3030
3091
|
("/api/policy/value-source", ["GET"], "policy_get_value_source"),
|
|
3031
3092
|
]
|
|
3032
3093
|
|
|
3033
|
-
def _mount(prefix: str) -> None:
|
|
3094
|
+
def _mount(prefix: str, *, guard: bool = False) -> None:
|
|
3095
|
+
# guard=True wraps each handler in _ingress_only so the route only
|
|
3096
|
+
# answers HA ingress (the Supervisor) — used for the add-on root
|
|
3097
|
+
# mount, whose port 9583 is reachable without the MCP secret.
|
|
3034
3098
|
for path, methods, handler_key in routes:
|
|
3035
|
-
|
|
3099
|
+
handler = handlers[handler_key]
|
|
3100
|
+
if guard:
|
|
3101
|
+
handler = _ingress_only(handler)
|
|
3102
|
+
mcp.custom_route(f"{prefix}{path}", methods=methods)(handler)
|
|
3036
3103
|
|
|
3037
3104
|
if is_addon:
|
|
3038
|
-
# Root mount lets HA ingress proxy localhost:9583/ → settings UI
|
|
3039
|
-
#
|
|
3040
|
-
#
|
|
3041
|
-
#
|
|
3042
|
-
#
|
|
3043
|
-
|
|
3044
|
-
|
|
3105
|
+
# Root mount lets HA ingress proxy localhost:9583/ → the settings UI
|
|
3106
|
+
# ("Open Web UI" button). The published port 9583 also makes these
|
|
3107
|
+
# routes reachable by direct callers that present no MCP secret, so
|
|
3108
|
+
# the root mount is gated with _ingress_only: only the Supervisor
|
|
3109
|
+
# (HA ingress, 172.30.32.2) may reach root; every other caller gets
|
|
3110
|
+
# 403 and must use the secret-path mount below. The "Open Web UI"
|
|
3111
|
+
# button is unaffected — its traffic arrives from the Supervisor.
|
|
3112
|
+
mcp.custom_route("/", methods=["GET"])(_ingress_only(handlers["root_page"]))
|
|
3113
|
+
_mount("", guard=True)
|
|
3045
3114
|
|
|
3046
3115
|
if secret_prefix:
|
|
3047
3116
|
# Mount under the MCP secret path so Docker / standalone clients
|
|
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
|
|
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.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/resources/skills-vendor/AGENTS.md
RENAMED
|
File without changes
|
{ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/resources/skills-vendor/CLAUDE.md
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/resources/skills-vendor/LICENSE
RENAMED
|
File without changes
|
{ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/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.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/tools_config_automations.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/tools_config_dashboards.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/tools_config_entry_flow.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/tools_config_helpers.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/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.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/tools_voice_assistant.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/tools/validation_middleware.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/transforms/categorized_search.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/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.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp/utils/kill_signal_diagnostics.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/src/ha_mcp_dev.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{ha_mcp_dev-7.6.0.dev637 → ha_mcp_dev-7.6.0.dev638}/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
|