ha-mcp-dev 7.6.0.dev661__tar.gz → 7.6.0.dev663__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.dev661/src/ha_mcp_dev.egg-info → ha_mcp_dev-7.6.0.dev663}/PKG-INFO +1 -1
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/pyproject.toml +1 -1
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/__main__.py +86 -1
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663/src/ha_mcp_dev.egg-info}/PKG-INFO +1 -1
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/LICENSE +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/MANIFEST.in +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/README.md +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/setup.cfg +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/__init__.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/_pypi_marker +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/_version.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/auth/__init__.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/auth/consent_form.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/auth/provider.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/backup_manager.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/client/__init__.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/client/rest_client.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/client/supervisor_client.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/client/websocket_client.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/client/websocket_listener.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/config.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/dashboard_screenshot/__init__.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/dashboard_screenshot/capture.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/dashboard_screenshot/provision.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/errors.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/policy/__init__.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/policy/approval_queue.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/policy/evaluator.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/policy/handlers.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/policy/middleware.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/policy/model.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/policy/persistence.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/policy/value_sources.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/py.typed +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/resources/skills-vendor/.claude/settings.json +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/resources/skills-vendor/.claude-plugin/marketplace.json +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/resources/skills-vendor/.claude-plugin/plugin.json +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/resources/skills-vendor/.github/ISSUE_TEMPLATE/skill-rca.md +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/resources/skills-vendor/.github/pull_request_template.md +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/resources/skills-vendor/AGENTS.md +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/resources/skills-vendor/CLAUDE.md +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/resources/skills-vendor/CONTRIBUTING.md +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/resources/skills-vendor/LICENSE +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/resources/skills-vendor/README.md +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/SKILL.md +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/evals/evals.json +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/automation-patterns.md +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-cards.md +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-guide.md +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/device-control.md +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/domain-docs.md +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/examples.yaml +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/helper-selection.md +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/safe-refactoring.md +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/template-guidelines.md +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/yaml-only-integrations.md +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/server.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/settings.css +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/settings.js +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/settings_ui.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/smoke_test.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/stdio_settings_sidecar.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/__init__.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/auto_backup.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/backup.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/best_practice_checker.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/device_control.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/enhanced.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/helpers.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/reference_validator.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/registry.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/smart_search/__init__.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/smart_search/_base.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/smart_search/_config.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/smart_search/_deep.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/smart_search/_entities.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/smart_search/_fetch.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/smart_search/_overview.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/smart_search/_scenes.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/smart_search/_scoring.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/tools_addons.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/tools_areas.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/tools_blueprints.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/tools_bug_report.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/tools_calendar.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/tools_camera.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/tools_categories.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/tools_code.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/tools_config_automations.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/tools_config_dashboards.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/tools_config_entry_flow.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/tools_config_helpers.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/tools_config_scenes.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/tools_config_scripts.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/tools_dashboard_screenshot.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/tools_energy.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/tools_entities.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/tools_filesystem.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/tools_groups.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/tools_hacs.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/tools_history.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/tools_integrations.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/tools_labels.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/tools_mcp_component.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/tools_registry.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/tools_resources.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/tools_search.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/tools_service.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/tools_services.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/tools_system.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/tools_todo.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/tools_traces.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/tools_updates.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/tools_utility.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/tools_voice_assistant.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/tools_yaml_config.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/tools_zones.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/util_helpers.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/validation_middleware.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/transforms/__init__.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/transforms/categorized_search.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/transforms/lite_docstrings.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/utils/__init__.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/utils/config_hash.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/utils/data_paths.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/utils/domain_handlers.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/utils/fuzzy_search.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/utils/kill_signal_diagnostics.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/utils/operation_manager.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/utils/python_sandbox.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/utils/skill_loader.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/utils/usage_logger.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp_dev.egg-info/SOURCES.txt +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp_dev.egg-info/dependency_links.txt +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp_dev.egg-info/entry_points.txt +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp_dev.egg-info/requires.txt +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp_dev.egg-info/top_level.txt +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/tests/__init__.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/tests/test_constants.py +0 -0
- {ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/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.dev663"
|
|
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"
|
|
@@ -22,6 +22,7 @@ truststore.inject_into_ssl()
|
|
|
22
22
|
import asyncio # noqa: E402
|
|
23
23
|
import copy # noqa: E402
|
|
24
24
|
import hashlib # noqa: E402
|
|
25
|
+
import ipaddress # noqa: E402
|
|
25
26
|
import logging # noqa: E402
|
|
26
27
|
import os # noqa: E402
|
|
27
28
|
import signal # noqa: E402
|
|
@@ -755,10 +756,93 @@ def _get_http_runtime(default_port: int = 8086) -> tuple[str, int, str]:
|
|
|
755
756
|
except ValueError:
|
|
756
757
|
logger.error(f"Invalid MCP_PORT value: {port_str!r}. Must be an integer.")
|
|
757
758
|
sys.exit(1)
|
|
758
|
-
path = os.getenv("MCP_SECRET_PATH",
|
|
759
|
+
path = os.getenv("MCP_SECRET_PATH", DEFAULT_MCP_PATH)
|
|
759
760
|
return host, port, path
|
|
760
761
|
|
|
761
762
|
|
|
763
|
+
# Default ``MCP_SECRET_PATH`` value, shared by ``_get_http_runtime`` (the
|
|
764
|
+
# read-from-env fallback) and ``_warn_if_default_path_exposed`` (the
|
|
765
|
+
# hardening-nudge predicate). Single source of truth so the two sites
|
|
766
|
+
# can't drift.
|
|
767
|
+
DEFAULT_MCP_PATH = "/mcp"
|
|
768
|
+
|
|
769
|
+
# Hostname literals (not IP addresses) treated as loopback by
|
|
770
|
+
# ``_is_loopback_host``. IP literals — the whole ``127.0.0.0/8`` block,
|
|
771
|
+
# ``::1``, bracketed forms, zone-suffixed forms, and IPv4-mapped IPv6 — are
|
|
772
|
+
# handled by the ``ipaddress`` parse before this set is consulted.
|
|
773
|
+
_LOOPBACK_HOSTNAMES = frozenset({"localhost", "ip6-localhost", "ip6-loopback"})
|
|
774
|
+
|
|
775
|
+
|
|
776
|
+
def _is_loopback_host(host: str) -> bool:
|
|
777
|
+
"""Return True when ``host`` names the local machine only.
|
|
778
|
+
|
|
779
|
+
Accepts IPv6 hosts in bracketed (``[::1]``) or zone-suffixed
|
|
780
|
+
(``::1%eth0``) form, the full ``127.0.0.0/8`` range, IPv4-mapped IPv6
|
|
781
|
+
loopback (``::ffff:127.0.0.1``, which ``is_loopback`` resolves on its
|
|
782
|
+
own), and the names in ``_LOOPBACK_HOSTNAMES``. A value that is neither
|
|
783
|
+
an IP literal nor a known loopback name (a real hostname, or a malformed
|
|
784
|
+
string) is treated as non-loopback.
|
|
785
|
+
"""
|
|
786
|
+
try:
|
|
787
|
+
candidate = host.strip("[]").split("%", 1)[0]
|
|
788
|
+
return ipaddress.ip_address(candidate).is_loopback
|
|
789
|
+
except ValueError:
|
|
790
|
+
# Not an IP literal — fall back to the known loopback hostnames.
|
|
791
|
+
return host.lower() in _LOOPBACK_HOSTNAMES
|
|
792
|
+
|
|
793
|
+
|
|
794
|
+
def _is_running_in_container() -> bool:
|
|
795
|
+
"""Best-effort detection of containerized execution.
|
|
796
|
+
|
|
797
|
+
Inside a container the server binds ``0.0.0.0`` regardless of how the
|
|
798
|
+
operator restricted host-side exposure (``docker run -p 127.0.0.1:...``),
|
|
799
|
+
so the bind host alone can't tell a loopback-only deployment from a
|
|
800
|
+
LAN-reachable one — the default-path warning would be a false positive
|
|
801
|
+
for every container. Container deployments are hardened through the
|
|
802
|
+
published guidance instead (AGENTS.md -> Docker; the add-on
|
|
803
|
+
auto-generates a secret path).
|
|
804
|
+
"""
|
|
805
|
+
# Docker writes /.dockerenv; Podman writes /run/.containerenv.
|
|
806
|
+
if os.path.exists("/.dockerenv") or os.path.exists("/run/.containerenv"):
|
|
807
|
+
return True
|
|
808
|
+
# The Home Assistant add-on runs under the Supervisor.
|
|
809
|
+
return bool(os.getenv("SUPERVISOR_TOKEN"))
|
|
810
|
+
|
|
811
|
+
|
|
812
|
+
def _warn_if_default_path_exposed(host: str, port: int, path: str) -> None:
|
|
813
|
+
"""Warn on a direct run that leaves the default path on a LAN bind.
|
|
814
|
+
|
|
815
|
+
Standard-mode HTTP/SSE authenticates by URL-path secrecy (see
|
|
816
|
+
SECURITY.md → Threat Model). The default ``/mcp`` is not the
|
|
817
|
+
high-entropy secret that model assumes once the bind leaves loopback.
|
|
818
|
+
|
|
819
|
+
Fires only for a direct ``ha-mcp-web`` / ``ha-mcp-sse`` start (uvx, pip,
|
|
820
|
+
source) that uses the default path on a non-loopback host. Operators
|
|
821
|
+
silence it the same way they harden — bind ``MCP_HOST=127.0.0.1`` or set
|
|
822
|
+
a high-entropy ``MCP_SECRET_PATH``. Containers are skipped: an
|
|
823
|
+
in-container ``0.0.0.0`` bind says nothing about real exposure, which is
|
|
824
|
+
set by the ``docker -p`` mapping the process can't observe (see
|
|
825
|
+
``_is_running_in_container``).
|
|
826
|
+
"""
|
|
827
|
+
if path != DEFAULT_MCP_PATH:
|
|
828
|
+
return
|
|
829
|
+
if _is_running_in_container():
|
|
830
|
+
return
|
|
831
|
+
if _is_loopback_host(host):
|
|
832
|
+
return
|
|
833
|
+
logger.warning(
|
|
834
|
+
"ha-mcp listening on %s:%s%s with default MCP_SECRET_PATH. "
|
|
835
|
+
"Standard-mode HTTP/SSE authenticates by URL-path secrecy and assumes "
|
|
836
|
+
"a high-entropy MCP_SECRET_PATH for non-loopback binds "
|
|
837
|
+
"(see SECURITY.md → Threat Model). "
|
|
838
|
+
"Either bind loopback (MCP_HOST=127.0.0.1) or set MCP_SECRET_PATH "
|
|
839
|
+
"to a high-entropy value (e.g. /private_<token_urlsafe(16)>).",
|
|
840
|
+
host,
|
|
841
|
+
port,
|
|
842
|
+
path,
|
|
843
|
+
)
|
|
844
|
+
|
|
845
|
+
|
|
762
846
|
async def _run_http_with_graceful_shutdown(
|
|
763
847
|
transport: str,
|
|
764
848
|
host: str,
|
|
@@ -861,6 +945,7 @@ def _run_http_server(transport: str, default_port: int = 8086) -> None:
|
|
|
861
945
|
from ha_mcp.settings_ui import register_settings_routes
|
|
862
946
|
|
|
863
947
|
host, port, path = _get_http_runtime(default_port)
|
|
948
|
+
_warn_if_default_path_exposed(host, port, path)
|
|
864
949
|
register_browser_landing(_get_mcp(), path)
|
|
865
950
|
register_settings_routes(_get_mcp(), _get_server(), secret_path=path)
|
|
866
951
|
_log_settings_url(host, port, path)
|
|
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.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/dashboard_screenshot/__init__.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/dashboard_screenshot/capture.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/dashboard_screenshot/provision.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
|
{ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/resources/skills-vendor/AGENTS.md
RENAMED
|
File without changes
|
{ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/resources/skills-vendor/CLAUDE.md
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/resources/skills-vendor/LICENSE
RENAMED
|
File without changes
|
{ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/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
|
|
File without changes
|
{ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/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.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/smart_search/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/smart_search/_config.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/smart_search/_entities.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/smart_search/_overview.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/smart_search/_scenes.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/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
|
|
File without changes
|
{ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/tools_config_automations.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/tools_config_dashboards.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/tools_config_entry_flow.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/tools_config_helpers.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/tools_config_scripts.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/tools_dashboard_screenshot.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.dev661 → ha_mcp_dev-7.6.0.dev663}/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.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/tools/validation_middleware.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp/transforms/categorized_search.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/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.dev661 → ha_mcp_dev-7.6.0.dev663}/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.dev661 → ha_mcp_dev-7.6.0.dev663}/src/ha_mcp_dev.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{ha_mcp_dev-7.6.0.dev661 → ha_mcp_dev-7.6.0.dev663}/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
|