ha-mcp-dev 7.6.0.dev641__tar.gz → 7.6.0.dev643__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.dev641/src/ha_mcp_dev.egg-info → ha_mcp_dev-7.6.0.dev643}/PKG-INFO +1 -1
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/pyproject.toml +1 -1
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/__main__.py +23 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/settings_ui.py +23 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/tools_bug_report.py +29 -9
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/tools_search.py +29 -4
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643/src/ha_mcp_dev.egg-info}/PKG-INFO +1 -1
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/LICENSE +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/MANIFEST.in +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/README.md +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/setup.cfg +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/__init__.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/_pypi_marker +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/_version.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/auth/__init__.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/auth/consent_form.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/auth/provider.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/backup_manager.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/client/__init__.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/client/rest_client.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/client/supervisor_client.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/client/websocket_client.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/client/websocket_listener.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/config.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/errors.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/policy/__init__.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/policy/approval_queue.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/policy/evaluator.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/policy/handlers.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/policy/middleware.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/policy/model.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/policy/persistence.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/policy/value_sources.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/py.typed +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/resources/skills-vendor/.claude/settings.json +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/resources/skills-vendor/.claude-plugin/marketplace.json +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/resources/skills-vendor/.claude-plugin/plugin.json +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/resources/skills-vendor/.github/ISSUE_TEMPLATE/skill-rca.md +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/resources/skills-vendor/.github/pull_request_template.md +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/resources/skills-vendor/AGENTS.md +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/resources/skills-vendor/CLAUDE.md +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/resources/skills-vendor/CONTRIBUTING.md +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/resources/skills-vendor/LICENSE +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/resources/skills-vendor/README.md +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/SKILL.md +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/evals/evals.json +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/automation-patterns.md +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-cards.md +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-guide.md +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/device-control.md +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/domain-docs.md +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/examples.yaml +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/helper-selection.md +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/safe-refactoring.md +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/template-guidelines.md +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/yaml-only-integrations.md +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/server.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/settings.css +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/settings.js +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/smoke_test.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/stdio_settings_sidecar.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/__init__.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/auto_backup.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/backup.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/best_practice_checker.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/device_control.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/enhanced.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/helpers.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/reference_validator.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/registry.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/smart_search/__init__.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/smart_search/_base.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/smart_search/_config.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/smart_search/_deep.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/smart_search/_entities.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/smart_search/_fetch.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/smart_search/_overview.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/smart_search/_scenes.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/smart_search/_scoring.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/tools_addons.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/tools_areas.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/tools_blueprints.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/tools_calendar.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/tools_camera.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/tools_categories.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/tools_code.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/tools_config_automations.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/tools_config_dashboards.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/tools_config_entry_flow.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/tools_config_helpers.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/tools_config_scenes.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/tools_config_scripts.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/tools_energy.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/tools_entities.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/tools_filesystem.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/tools_groups.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/tools_hacs.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/tools_history.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/tools_integrations.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/tools_labels.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/tools_mcp_component.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/tools_registry.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/tools_resources.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/tools_service.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/tools_services.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/tools_system.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/tools_todo.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/tools_traces.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/tools_updates.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/tools_utility.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/tools_voice_assistant.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/tools_yaml_config.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/tools_zones.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/util_helpers.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/validation_middleware.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/transforms/__init__.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/transforms/categorized_search.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/transforms/lite_docstrings.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/utils/__init__.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/utils/config_hash.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/utils/data_paths.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/utils/domain_handlers.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/utils/fuzzy_search.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/utils/kill_signal_diagnostics.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/utils/operation_manager.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/utils/python_sandbox.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/utils/skill_loader.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/utils/usage_logger.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp_dev.egg-info/SOURCES.txt +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp_dev.egg-info/dependency_links.txt +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp_dev.egg-info/entry_points.txt +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp_dev.egg-info/requires.txt +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp_dev.egg-info/top_level.txt +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/tests/__init__.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/tests/test_constants.py +0 -0
- {ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/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.dev643"
|
|
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"
|
|
@@ -825,6 +825,27 @@ def register_browser_landing(mcp_instance: "FastMCP | _DeferredMCP", path: str)
|
|
|
825
825
|
)
|
|
826
826
|
|
|
827
827
|
|
|
828
|
+
def _log_settings_url(host: str, port: int, path: str) -> None:
|
|
829
|
+
"""Log the web settings-UI URL at HTTP startup.
|
|
830
|
+
|
|
831
|
+
Non-add-on operators (Docker / standalone) otherwise have no easy way to
|
|
832
|
+
discover the settings page or its secret-path URL (issue #1458). When the
|
|
833
|
+
bind host is the wildcard (``0.0.0.0`` / ``::``) the process can't know its
|
|
834
|
+
externally reachable address, so we log a ``<host>`` placeholder.
|
|
835
|
+
"""
|
|
836
|
+
is_wildcard = host in ("0.0.0.0", "::")
|
|
837
|
+
if is_wildcard:
|
|
838
|
+
display_host = "<host>"
|
|
839
|
+
elif ":" in host:
|
|
840
|
+
# IPv6 literal (e.g. ::1, 2001:db8::1) needs brackets in a URL.
|
|
841
|
+
display_host = f"[{host}]"
|
|
842
|
+
else:
|
|
843
|
+
display_host = host
|
|
844
|
+
url = f"http://{display_host}:{port}{path.rstrip('/')}/settings"
|
|
845
|
+
note = " (substitute this server's address for <host>)" if is_wildcard else ""
|
|
846
|
+
logger.info(f"Settings UI available at: {url}{note}")
|
|
847
|
+
|
|
848
|
+
|
|
828
849
|
def _run_http_server(transport: str, default_port: int = 8086) -> None:
|
|
829
850
|
"""Common runner for HTTP-based transports.
|
|
830
851
|
|
|
@@ -837,6 +858,7 @@ def _run_http_server(transport: str, default_port: int = 8086) -> None:
|
|
|
837
858
|
host, port, path = _get_http_runtime(default_port)
|
|
838
859
|
register_browser_landing(_get_mcp(), path)
|
|
839
860
|
register_settings_routes(_get_mcp(), _get_server(), secret_path=path)
|
|
861
|
+
_log_settings_url(host, port, path)
|
|
840
862
|
|
|
841
863
|
_run_entrypoint(
|
|
842
864
|
_run_http_with_graceful_shutdown(transport, host, port, path),
|
|
@@ -984,6 +1006,7 @@ async def _run_oauth_server(
|
|
|
984
1006
|
from ha_mcp.settings_ui import register_settings_routes
|
|
985
1007
|
|
|
986
1008
|
register_settings_routes(mcp, _server, secret_path=path)
|
|
1009
|
+
_log_settings_url(host, port, path)
|
|
987
1010
|
|
|
988
1011
|
tools = await mcp.list_tools()
|
|
989
1012
|
logger.info(
|
|
@@ -3017,6 +3017,25 @@ def _ingress_only(handler: _SettingsRoute) -> _SettingsRoute:
|
|
|
3017
3017
|
return _guarded
|
|
3018
3018
|
|
|
3019
3019
|
|
|
3020
|
+
# Mount prefix the settings UI is served under in long-lived HTTP transports
|
|
3021
|
+
# (Docker / standalone ha-mcp-web / OAuth / the add-on's secret-path mount).
|
|
3022
|
+
# Recorded by register_settings_routes so ha_get_overview can point users at
|
|
3023
|
+
# the settings page in modes that have no stdio sidecar URL file to surface
|
|
3024
|
+
# (issue #1458). Stays None in pure stdio mode, where the sidecar writes
|
|
3025
|
+
# ~/.ha-mcp/ui.url instead.
|
|
3026
|
+
_http_settings_prefix: str | None = None
|
|
3027
|
+
|
|
3028
|
+
|
|
3029
|
+
def get_http_settings_prefix() -> str | None:
|
|
3030
|
+
"""Return the settings-UI mount prefix for HTTP transports, or None.
|
|
3031
|
+
|
|
3032
|
+
Set by :func:`register_settings_routes` when the page is mounted on a
|
|
3033
|
+
long-lived HTTP server. ``ha_get_overview`` reads it to hint at the
|
|
3034
|
+
settings page when there is no stdio sidecar URL to hand the user.
|
|
3035
|
+
"""
|
|
3036
|
+
return _http_settings_prefix
|
|
3037
|
+
|
|
3038
|
+
|
|
3020
3039
|
def register_settings_routes(
|
|
3021
3040
|
mcp: FastMCP,
|
|
3022
3041
|
server: HomeAssistantSmartMCPServer,
|
|
@@ -3117,3 +3136,7 @@ def register_settings_routes(
|
|
|
3117
3136
|
# need the same secret to reach the UI as they do for the MCP
|
|
3118
3137
|
# endpoint.
|
|
3119
3138
|
_mount(secret_prefix)
|
|
3139
|
+
# Record the mount so ha_get_overview can point users at the settings
|
|
3140
|
+
# page in HTTP transports that have no stdio sidecar URL file (#1458).
|
|
3141
|
+
global _http_settings_prefix
|
|
3142
|
+
_http_settings_prefix = secret_prefix
|
|
@@ -293,7 +293,8 @@ def _sanitize_log_text(text: str) -> str:
|
|
|
293
293
|
review (see ``_generate_anonymization_guide``). Rules cover the most common
|
|
294
294
|
leak shapes seen in HA add-on logs:
|
|
295
295
|
JWTs, bearer tokens, long hex tokens, ``key=value`` style credentials,
|
|
296
|
-
URL userinfo,
|
|
296
|
+
URL userinfo, IPv4 addresses with network context, and the MCP connect-URL
|
|
297
|
+
secret path (the add-on's LAN auth).
|
|
297
298
|
"""
|
|
298
299
|
# JWT tokens (header.payload.signature)
|
|
299
300
|
text = re.sub(
|
|
@@ -338,6 +339,20 @@ def _sanitize_log_text(text: str) -> str:
|
|
|
338
339
|
text = _IPV4_WITH_PORT_OR_CIDR_RE.sub("[IP]", text)
|
|
339
340
|
text = _IPV4_IN_URL_RE.sub(r"\1[IP]", text)
|
|
340
341
|
text = _IPV4_AFTER_KEYWORD_RE.sub(r"\1[IP]", text)
|
|
342
|
+
# MCP connect-URL secret path — the add-on's LAN auth. Redact by the
|
|
343
|
+
# configured value (catches custom paths) and the generated
|
|
344
|
+
# ``/private_<token>`` convention. Only bug-report output is scrubbed here;
|
|
345
|
+
# the raw logs this text is copied from are left intact.
|
|
346
|
+
configured = os.getenv("MCP_SECRET_PATH", "").rstrip("/")
|
|
347
|
+
if configured and configured != "/mcp":
|
|
348
|
+
# Anchor on a path-segment boundary so a short/substring-prone configured
|
|
349
|
+
# value (e.g. "/ha") cannot corrupt unrelated text (e.g. "/happy").
|
|
350
|
+
text = re.sub(
|
|
351
|
+
re.escape(configured) + r"(?![A-Za-z0-9_-])",
|
|
352
|
+
"[REDACTED_SECRET_PATH]",
|
|
353
|
+
text,
|
|
354
|
+
)
|
|
355
|
+
text = re.sub(r"/private_[A-Za-z0-9_-]+", "[REDACTED_SECRET_PATH]", text)
|
|
341
356
|
return text
|
|
342
357
|
|
|
343
358
|
|
|
@@ -508,8 +523,7 @@ class BugReportTools:
|
|
|
508
523
|
**OUTPUT:**
|
|
509
524
|
Returns both templates plus diagnostic data. Key fields:
|
|
510
525
|
- `runtime_bug_template`, `agent_behavior_template` — pick based on context
|
|
511
|
-
- `recent_logs` —
|
|
512
|
-
startup log entries are summarised in `formatted_report`, not returned raw
|
|
526
|
+
- `recent_logs`, `startup_logs` — captured ha-mcp tool/server log entries
|
|
513
527
|
- `addon_logs` — addon container stdout/stderr (HA add-on installs only;
|
|
514
528
|
empty string otherwise)
|
|
515
529
|
- `suggested_title`, `duplicate_check_urls`, `anonymization_guide`
|
|
@@ -623,13 +637,19 @@ class BugReportTools:
|
|
|
623
637
|
return {
|
|
624
638
|
"success": True,
|
|
625
639
|
"diagnostic_info": diagnostic_info,
|
|
626
|
-
# ``recent_logs`` entries are redacted at the logging chokepoint
|
|
627
|
-
# (UsageLogger.log_tool_usage), so the tool parameters here carry no
|
|
628
|
-
# secrets. ``startup_logs`` come from a separate StartupLogCollector
|
|
629
|
-
# that is NOT redacted at source, so the raw entries are
|
|
630
|
-
# intentionally omitted — the sanitized view lives in
|
|
631
|
-
# ``formatted_report`` (via ``_format_startup_logs``).
|
|
632
640
|
"recent_logs": recent_logs,
|
|
641
|
+
# Scrub the startup-log *messages* — they aren't sanitized at source,
|
|
642
|
+
# so the connect-URL secret path can otherwise surface here.
|
|
643
|
+
# recent_logs is also returned, but its sensitive *parameters* are
|
|
644
|
+
# key-masked at the logging chokepoint and its error_message is
|
|
645
|
+
# returned as-is to the trusted client by design (see SECURITY.md);
|
|
646
|
+
# formatted_report and addon_logs already route through
|
|
647
|
+
# _sanitize_log_text. This copies entries — the underlying log
|
|
648
|
+
# records stay raw.
|
|
649
|
+
"startup_logs": [
|
|
650
|
+
{**entry, "message": _sanitize_log_text(entry.get("message", ""))}
|
|
651
|
+
for entry in startup_logs
|
|
652
|
+
],
|
|
633
653
|
"addon_logs": addon_logs,
|
|
634
654
|
"log_count": len(recent_logs),
|
|
635
655
|
"startup_log_count": len(startup_logs),
|
|
@@ -1136,10 +1136,11 @@ def register_search_tools(mcp: Any, client: Any, **kwargs: Any) -> None:
|
|
|
1136
1136
|
"device_types, service_availability, system_info, "
|
|
1137
1137
|
"notification_count, notifications, repair_count, "
|
|
1138
1138
|
"dismissed_repair_count, repairs, repairs_error, "
|
|
1139
|
-
"tool_discovery, settings_url. Note:
|
|
1140
|
-
"(stdio mode
|
|
1141
|
-
"
|
|
1142
|
-
"
|
|
1139
|
+
"tool_discovery, settings_url, settings_url_hint. Note: "
|
|
1140
|
+
"``settings_url`` (stdio mode) and ``settings_url_hint`` "
|
|
1141
|
+
"(HTTP/Docker/OAuth mode) are emitted regardless of "
|
|
1142
|
+
"``fields=`` projection so the settings page stays "
|
|
1143
|
+
"discoverable; see the tool description."
|
|
1143
1144
|
),
|
|
1144
1145
|
),
|
|
1145
1146
|
] = None,
|
|
@@ -1167,6 +1168,12 @@ def register_search_tools(mcp: Any, client: Any, **kwargs: Any) -> None:
|
|
|
1167
1168
|
projection (so it stays discoverable even when callers
|
|
1168
1169
|
minimize the response) but only when the sidecar URL file
|
|
1169
1170
|
actually exists.
|
|
1171
|
+
|
|
1172
|
+
In HTTP / Docker / OAuth modes there is no sidecar URL file and the
|
|
1173
|
+
server can't know its externally reachable host, so the response
|
|
1174
|
+
instead carries a ``settings_url_hint`` string telling the user where
|
|
1175
|
+
the page is mounted and to read the full URL from the startup logs.
|
|
1176
|
+
Hand whichever of the two fields is present to the user.
|
|
1170
1177
|
"""
|
|
1171
1178
|
# Validate fields= early so a malformed value returns VALIDATION_FAILED
|
|
1172
1179
|
# with parameter="fields" (ha_get_overview has no outer try/except, so
|
|
@@ -1368,6 +1375,24 @@ def register_search_tools(mcp: Any, client: Any, **kwargs: Any) -> None:
|
|
|
1368
1375
|
sidecar_url = read_sidecar_url()
|
|
1369
1376
|
if sidecar_url:
|
|
1370
1377
|
projected["settings_url"] = sidecar_url
|
|
1378
|
+
else:
|
|
1379
|
+
# No stdio sidecar URL file. In HTTP / Docker / OAuth modes the
|
|
1380
|
+
# settings page is mounted on this server, but the process binds
|
|
1381
|
+
# 0.0.0.0 and can't know its externally reachable host — so hint
|
|
1382
|
+
# at the page (and the startup-log URL) instead of guessing a
|
|
1383
|
+
# wrong absolute URL (issue #1458).
|
|
1384
|
+
from ..settings_ui import get_http_settings_prefix
|
|
1385
|
+
|
|
1386
|
+
http_prefix = get_http_settings_prefix()
|
|
1387
|
+
if http_prefix:
|
|
1388
|
+
settings_path = f"{http_prefix.rstrip('/')}/settings"
|
|
1389
|
+
projected["settings_url_hint"] = (
|
|
1390
|
+
"The settings page (enable/disable/pin tools, feature "
|
|
1391
|
+
"flags, advanced settings, backups, tool-approval) is "
|
|
1392
|
+
f"served at '{settings_path}' on this MCP server. Find the "
|
|
1393
|
+
"full URL in the ha-mcp startup logs, or append it to the "
|
|
1394
|
+
"base URL your client connects to."
|
|
1395
|
+
)
|
|
1371
1396
|
|
|
1372
1397
|
return projected
|
|
1373
1398
|
|
|
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.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/resources/skills-vendor/AGENTS.md
RENAMED
|
File without changes
|
{ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/resources/skills-vendor/CLAUDE.md
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/resources/skills-vendor/LICENSE
RENAMED
|
File without changes
|
{ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/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.dev641 → ha_mcp_dev-7.6.0.dev643}/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
|
{ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/smart_search/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/smart_search/_config.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/smart_search/_entities.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/smart_search/_overview.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/smart_search/_scenes.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/smart_search/_scoring.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
|
{ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/tools_config_automations.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/tools_config_dashboards.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/tools_config_entry_flow.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/tools_config_helpers.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/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.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/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.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/tools/validation_middleware.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp/transforms/categorized_search.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/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.dev641 → ha_mcp_dev-7.6.0.dev643}/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.dev641 → ha_mcp_dev-7.6.0.dev643}/src/ha_mcp_dev.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{ha_mcp_dev-7.6.0.dev641 → ha_mcp_dev-7.6.0.dev643}/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
|