ha-mcp-dev 7.8.0.dev702__tar.gz → 7.8.0.dev703__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.8.0.dev702/src/ha_mcp_dev.egg-info → ha_mcp_dev-7.8.0.dev703}/PKG-INFO +3 -3
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/README.md +2 -2
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/pyproject.toml +3 -1
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/read_only.py +6 -1
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/settings.js +2 -2
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/backup.py +121 -1
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/tools_filesystem.py +36 -15
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703/src/ha_mcp_dev.egg-info}/PKG-INFO +3 -3
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/LICENSE +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/MANIFEST.in +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/setup.cfg +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/__init__.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/__main__.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/_pypi_marker +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/_version.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/auth/__init__.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/auth/consent_form.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/auth/provider.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/backup_manager.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/client/__init__.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/client/rest_client.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/client/supervisor_client.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/client/websocket_client.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/client/websocket_listener.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/config.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/dashboard_screenshot/__init__.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/dashboard_screenshot/capture.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/dashboard_screenshot/provision.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/errors.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/policy/__init__.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/policy/approval_queue.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/policy/evaluator.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/policy/handlers.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/policy/middleware.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/policy/model.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/policy/persistence.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/policy/value_sources.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/py.typed +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/resources/skills-vendor/.claude/settings.json +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/resources/skills-vendor/.claude-plugin/marketplace.json +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/resources/skills-vendor/.claude-plugin/plugin.json +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/resources/skills-vendor/.github/ISSUE_TEMPLATE/skill-rca.md +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/resources/skills-vendor/.github/pull_request_template.md +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/resources/skills-vendor/AGENTS.md +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/resources/skills-vendor/CLAUDE.md +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/resources/skills-vendor/CONTRIBUTING.md +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/resources/skills-vendor/LICENSE +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/resources/skills-vendor/README.md +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/SKILL.md +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/evals/evals.json +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/automation-patterns.md +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-cards.md +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-guide.md +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/device-control.md +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/domain-docs.md +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/examples.yaml +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/helper-selection.md +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/safe-refactoring.md +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/template-guidelines.md +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/yaml-only-integrations.md +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/server.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/settings.css +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/settings_ui.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/smoke_test.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/stdio_settings_sidecar.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/__init__.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/auto_backup.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/best_practice_checker.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/config_entry_flow.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/device_control.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/enhanced.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/helpers.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/reference_validator.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/registry.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/smart_search/__init__.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/smart_search/_base.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/smart_search/_config.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/smart_search/_deep.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/smart_search/_entities.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/smart_search/_fetch.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/smart_search/_overview.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/smart_search/_scenes.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/smart_search/_scoring.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/tool_search_hint_middleware.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/tools_addons.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/tools_areas.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/tools_blueprints.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/tools_bug_report.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/tools_calendar.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/tools_camera.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/tools_categories.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/tools_code.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/tools_config_automations.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/tools_config_dashboards.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/tools_config_helpers.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/tools_config_scenes.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/tools_config_scripts.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/tools_dashboard_screenshot.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/tools_energy.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/tools_entities.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/tools_groups.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/tools_hacs.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/tools_history.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/tools_integrations.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/tools_labels.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/tools_mcp_component.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/tools_registry.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/tools_resources.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/tools_search.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/tools_service.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/tools_services.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/tools_system.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/tools_themes.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/tools_todo.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/tools_traces.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/tools_updates.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/tools_utility.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/tools_voice_assistant.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/tools_yaml_config.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/tools_zones.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/util_helpers.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/validation_middleware.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/transforms/__init__.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/transforms/categorized_search.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/transforms/lite_docstrings.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/utils/__init__.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/utils/config_hash.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/utils/data_paths.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/utils/domain_handlers.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/utils/fuzzy_search.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/utils/kill_signal_diagnostics.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/utils/operation_manager.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/utils/python_sandbox.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/utils/skill_loader.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/utils/usage_logger.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp_dev.egg-info/SOURCES.txt +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp_dev.egg-info/dependency_links.txt +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp_dev.egg-info/entry_points.txt +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp_dev.egg-info/requires.txt +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp_dev.egg-info/top_level.txt +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/tests/__init__.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/tests/test_constants.py +0 -0
- {ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/tests/test_env_manager.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ha-mcp-dev
|
|
3
|
-
Version: 7.8.0.
|
|
3
|
+
Version: 7.8.0.dev703
|
|
4
4
|
Summary: Home Assistant MCP Server - Complete control of Home Assistant through MCP
|
|
5
5
|
Author-email: Julien <github@qc-h.net>
|
|
6
6
|
License: MIT
|
|
@@ -275,8 +275,8 @@ Some tools require a companion custom component installed in Home Assistant. Sta
|
|
|
275
275
|
| Tool | Description |
|
|
276
276
|
|------|-------------|
|
|
277
277
|
| `ha_config_set_yaml` *(beta)* | Safely add, replace, or remove top-level YAML keys in `configuration.yaml` and package files (automatic backup, validation, and config check) |
|
|
278
|
-
| `ha_list_files` *(beta)* | List files in allowed directories
|
|
279
|
-
| `ha_read_file` *(beta)* | Read files from allowed paths (config YAML, logs,
|
|
278
|
+
| `ha_list_files` *(beta)* | List files in allowed directories |
|
|
279
|
+
| `ha_read_file` *(beta)* | Read files from allowed paths (config YAML, logs, and allowed directories) |
|
|
280
280
|
| `ha_write_file` *(beta)* | Write files to allowed directories |
|
|
281
281
|
| `ha_delete_file` *(beta)* | Delete files from allowed directories |
|
|
282
282
|
|
|
@@ -245,8 +245,8 @@ Some tools require a companion custom component installed in Home Assistant. Sta
|
|
|
245
245
|
| Tool | Description |
|
|
246
246
|
|------|-------------|
|
|
247
247
|
| `ha_config_set_yaml` *(beta)* | Safely add, replace, or remove top-level YAML keys in `configuration.yaml` and package files (automatic backup, validation, and config check) |
|
|
248
|
-
| `ha_list_files` *(beta)* | List files in allowed directories
|
|
249
|
-
| `ha_read_file` *(beta)* | Read files from allowed paths (config YAML, logs,
|
|
248
|
+
| `ha_list_files` *(beta)* | List files in allowed directories |
|
|
249
|
+
| `ha_read_file` *(beta)* | Read files from allowed paths (config YAML, logs, and allowed directories) |
|
|
250
250
|
| `ha_write_file` *(beta)* | Write files to allowed directories |
|
|
251
251
|
| `ha_delete_file` *(beta)* | Delete files from allowed directories |
|
|
252
252
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "ha-mcp-dev"
|
|
7
|
-
version = "7.8.0.
|
|
7
|
+
version = "7.8.0.dev703"
|
|
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"
|
|
@@ -85,6 +85,8 @@ ignore_missing_imports = true
|
|
|
85
85
|
[[tool.mypy.overrides]]
|
|
86
86
|
module = [
|
|
87
87
|
"homeassistant.*",
|
|
88
|
+
"aiohasupervisor",
|
|
89
|
+
"aiohasupervisor.*",
|
|
88
90
|
"aiohttp",
|
|
89
91
|
"voluptuous",
|
|
90
92
|
"jsonschema",
|
|
@@ -66,8 +66,12 @@ class ReadOnlyExemption(NamedTuple):
|
|
|
66
66
|
def _backup_write(args: dict[str, Any]) -> str | None:
|
|
67
67
|
scope = args.get("scope")
|
|
68
68
|
action = args.get("action")
|
|
69
|
+
# Read-only-safe: per-edit backup listing/viewing, and snapshot listing
|
|
70
|
+
# (issue #1586 — pure ``backup/info`` read, no tarball mutation).
|
|
69
71
|
if scope == "edits" and action in ("list", "view"):
|
|
70
72
|
return None
|
|
73
|
+
if scope == "snapshot" and action == "list":
|
|
74
|
+
return None
|
|
71
75
|
return f"scope={scope!r}, action={action!r}"
|
|
72
76
|
|
|
73
77
|
|
|
@@ -144,7 +148,8 @@ def _custom_tool_write(args: dict[str, Any]) -> str | None:
|
|
|
144
148
|
READ_ONLY_EXEMPT_TOOLS: dict[str, ReadOnlyExemption] = {
|
|
145
149
|
"ha_manage_backup": ReadOnlyExemption(
|
|
146
150
|
_backup_write,
|
|
147
|
-
"listing and viewing per-edit backups (scope='edits', action='list' or
|
|
151
|
+
"listing and viewing per-edit backups (scope='edits', action='list' or "
|
|
152
|
+
"'view') and listing snapshots (scope='snapshot', action='list')",
|
|
148
153
|
),
|
|
149
154
|
"ha_manage_addon": ReadOnlyExemption(
|
|
150
155
|
_addon_write,
|
|
@@ -1030,8 +1030,8 @@ function renderFsCustomPathsSubForm(parentEl, masterOn, fsOn) {
|
|
|
1030
1030
|
: '.storage, secrets.yaml';
|
|
1031
1031
|
info.innerHTML =
|
|
1032
1032
|
`<div class="feature-name">Custom filesystem directories (advanced)</div>` +
|
|
1033
|
-
`<div class="feature-help">Extra directories (one per line
|
|
1034
|
-
`<div class="feature-help">Always blocked (cannot be added): <code>${escapeHtml(denyList)}</code>, path traversal (<code>..</code>), and absolute
|
|
1033
|
+
`<div class="feature-help">Extra directories (one per line) that the file tools may READ and WRITE — either relative to your config dir (e.g. <code>pyscript</code>, <code>python_scripts</code>) or an absolute HAOS sibling volume <code>/share</code>, <code>/media</code>, <code>/ssl</code>, <code>/backup</code> (or a subdirectory of one). Each entry grants both read and write. Applies immediately; no restart needed.</div>` +
|
|
1034
|
+
`<div class="feature-help">Always blocked (cannot be added): <code>${escapeHtml(denyList)}</code>, path traversal (<code>..</code>), and any absolute path outside the HAOS sibling volumes.</div>`;
|
|
1035
1035
|
|
|
1036
1036
|
const control = document.createElement('div');
|
|
1037
1037
|
control.className = 'feature-control';
|
|
@@ -731,10 +731,126 @@ async def restore_backup(
|
|
|
731
731
|
return None # py/mixed-returns: explicit terminal; error handlers above always raise (NoReturn), unreachable
|
|
732
732
|
|
|
733
733
|
|
|
734
|
+
def _summarize_backup(entry: dict[str, Any]) -> dict[str, Any]:
|
|
735
|
+
"""Project one HA ``backup/info`` entry to the fields a caller needs to
|
|
736
|
+
identify and choose a snapshot (issue #1586).
|
|
737
|
+
|
|
738
|
+
Size is reported per backup agent; we surface the largest reported size
|
|
739
|
+
across agents. Every field is ``.get`` so a schema the running HA version
|
|
740
|
+
doesn't populate yields ``None`` rather than raising.
|
|
741
|
+
"""
|
|
742
|
+
agents = entry.get("agents") or {}
|
|
743
|
+
size_bytes: int | None = None
|
|
744
|
+
if isinstance(agents, dict):
|
|
745
|
+
sizes: list[int] = []
|
|
746
|
+
for a in agents.values():
|
|
747
|
+
if isinstance(a, dict):
|
|
748
|
+
size = a.get("size")
|
|
749
|
+
# Accept int or float (some agents report byte counts as float);
|
|
750
|
+
# bool is an int subclass but never a real size, so exclude it.
|
|
751
|
+
if isinstance(size, (int, float)) and not isinstance(size, bool):
|
|
752
|
+
sizes.append(int(size))
|
|
753
|
+
if sizes:
|
|
754
|
+
size_bytes = max(sizes)
|
|
755
|
+
return {
|
|
756
|
+
"backup_id": entry.get("backup_id"),
|
|
757
|
+
"name": entry.get("name"),
|
|
758
|
+
"date": entry.get("date"),
|
|
759
|
+
"size_bytes": size_bytes,
|
|
760
|
+
"protected": entry.get("protected"),
|
|
761
|
+
"database_included": entry.get("database_included"),
|
|
762
|
+
"homeassistant_included": entry.get("homeassistant_included"),
|
|
763
|
+
"homeassistant_version": entry.get("homeassistant_version"),
|
|
764
|
+
"with_automatic_settings": entry.get("with_automatic_settings"),
|
|
765
|
+
"agent_ids": list(agents.keys()) if isinstance(agents, dict) else [],
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
|
|
769
|
+
async def list_backups(client: HomeAssistantClient, limit: int = 200) -> dict[str, Any]:
|
|
770
|
+
"""List the full HA snapshot tarballs known to Home Assistant (issue #1586).
|
|
771
|
+
|
|
772
|
+
Surfaces the inventory HA already returns from its WebSocket ``backup/info``
|
|
773
|
+
command — the same data ``restore_backup`` uses internally to verify a
|
|
774
|
+
``backup_id`` exists. Before this, the snapshot scope exposed only
|
|
775
|
+
``create`` and ``restore``, so a caller had no way to discover backup IDs or
|
|
776
|
+
confirm a specific backup landed; they had to already know the ID. Newest
|
|
777
|
+
first. Read-only: no safety backup, no restart.
|
|
778
|
+
"""
|
|
779
|
+
ws_client = None
|
|
780
|
+
try:
|
|
781
|
+
ws_client, error = await get_connected_ws_client(
|
|
782
|
+
client.base_url, client.token, verify_ssl=client.verify_ssl
|
|
783
|
+
)
|
|
784
|
+
if error:
|
|
785
|
+
raise_tool_error(
|
|
786
|
+
error
|
|
787
|
+
or create_error_response(
|
|
788
|
+
ErrorCode.CONNECTION_FAILED,
|
|
789
|
+
"Failed to connect to Home Assistant WebSocket to list backups",
|
|
790
|
+
)
|
|
791
|
+
)
|
|
792
|
+
ws_client = cast(HomeAssistantWebSocketClient, ws_client)
|
|
793
|
+
|
|
794
|
+
info = await ws_client.send_command("backup/info")
|
|
795
|
+
if not info.get("success"):
|
|
796
|
+
raise_tool_error(
|
|
797
|
+
create_error_response(
|
|
798
|
+
ErrorCode.SERVICE_CALL_FAILED,
|
|
799
|
+
info.get("error", "Failed to retrieve backup information"),
|
|
800
|
+
)
|
|
801
|
+
)
|
|
802
|
+
|
|
803
|
+
result_block = info.get("result") or {}
|
|
804
|
+
raw_backups = result_block.get("backups") or []
|
|
805
|
+
summarized = [_summarize_backup(b) for b in raw_backups]
|
|
806
|
+
# Newest first so "did my backup land?" is answered by the top entry.
|
|
807
|
+
# Parse via _parse_backup_date (handles `Z`/naive) rather than sorting
|
|
808
|
+
# the raw strings lexicographically — `'Z'` > `'+'` would misorder a mix
|
|
809
|
+
# of `...Z` and `...+00:00`. Undated entries sink to the bottom.
|
|
810
|
+
_date_floor = datetime.min.replace(tzinfo=UTC)
|
|
811
|
+
summarized.sort(
|
|
812
|
+
key=lambda b: _parse_backup_date(b.get("date")) or _date_floor,
|
|
813
|
+
reverse=True,
|
|
814
|
+
)
|
|
815
|
+
total = len(summarized)
|
|
816
|
+
if limit and total > limit:
|
|
817
|
+
summarized = summarized[:limit]
|
|
818
|
+
return {
|
|
819
|
+
"success": True,
|
|
820
|
+
"count": len(summarized),
|
|
821
|
+
"total": total,
|
|
822
|
+
"backups": summarized,
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
except ToolError:
|
|
826
|
+
raise
|
|
827
|
+
except Exception as e:
|
|
828
|
+
logger.error(f"Error listing backups: {e}")
|
|
829
|
+
exception_to_structured_error(
|
|
830
|
+
e,
|
|
831
|
+
context={"tool": "list_backups"},
|
|
832
|
+
suggestions=["Check Home Assistant connection and the backup integration"],
|
|
833
|
+
)
|
|
834
|
+
return None # unreachable: exception_to_structured_error always raises
|
|
835
|
+
finally:
|
|
836
|
+
# Always disconnect WebSocket — narrow to transport errors; a
|
|
837
|
+
# programming error during cleanup should still surface.
|
|
838
|
+
if ws_client:
|
|
839
|
+
try:
|
|
840
|
+
await ws_client.disconnect()
|
|
841
|
+
except (TimeoutError, OSError, ConnectionError) as err:
|
|
842
|
+
logger.debug(
|
|
843
|
+
"ws disconnect (cleanup) transport error: %s: %s",
|
|
844
|
+
type(err).__name__,
|
|
845
|
+
err,
|
|
846
|
+
)
|
|
847
|
+
|
|
848
|
+
|
|
734
849
|
# Valid (scope, action) combinations. Anything outside this set is
|
|
735
850
|
# rejected with a structured VALIDATION_INVALID_PARAMETER error.
|
|
736
851
|
_VALID_COMBOS: set[tuple[str, str]] = {
|
|
737
852
|
("snapshot", "create"),
|
|
853
|
+
("snapshot", "list"),
|
|
738
854
|
("snapshot", "restore"),
|
|
739
855
|
("edits", "create"),
|
|
740
856
|
("edits", "list"),
|
|
@@ -799,6 +915,7 @@ def register_backup_tools(
|
|
|
799
915
|
| scope | action | What it does |
|
|
800
916
|
|---|---|---|
|
|
801
917
|
| `snapshot` | `create` | Create a full HA tarball (config + addons, no DB by default). Heavy, seconds-long. |
|
|
918
|
+
| `snapshot` | `list` | List full HA tarball snapshots (id, name, date, size). Read-only — use to discover a `backup_id` or confirm a backup landed. |
|
|
802
919
|
| `snapshot` | `restore` | Restore a full HA tarball. **Restarts HA.** Last-resort recovery. |
|
|
803
920
|
| `edits` | `create` | On-demand snapshot of one entity (`domain` + `entity_id` required). Use before the user manually edits in the HA UI. Same handler path the decorator takes on writes; bypasses the `enable_auto_backup` toggle. |
|
|
804
921
|
| `edits` | `list` | List per-entity auto-backups (lightweight). Filter by `domain` and/or `entity_id`. |
|
|
@@ -817,6 +934,7 @@ def register_backup_tools(
|
|
|
817
934
|
|
|
818
935
|
**Examples:**
|
|
819
936
|
- Snapshot before risky op: `ha_manage_backup(scope="snapshot", action="create", name="Before_Big_Change")`
|
|
937
|
+
- List snapshots (to discover a backup_id or confirm one landed): `ha_manage_backup(scope="snapshot", action="list")`
|
|
820
938
|
- Restore full snapshot: `ha_manage_backup(scope="snapshot", action="restore", backup_id="dd7550ed")`
|
|
821
939
|
- On-demand entity snapshot before a manual UI edit: `ha_manage_backup(scope="edits", action="create", domain="helper_input_boolean", entity_id="kitchen_lights_active")`
|
|
822
940
|
- List recent auto-backups for one automation: `ha_manage_backup(scope="edits", action="list", domain="automation", entity_id="kitchen_lights")`
|
|
@@ -906,7 +1024,7 @@ def register_backup_tools(
|
|
|
906
1024
|
default=200,
|
|
907
1025
|
ge=1,
|
|
908
1026
|
le=10_000,
|
|
909
|
-
description="(edits.list) Maximum number of entries to return.",
|
|
1027
|
+
description="(edits.list / snapshot.list) Maximum number of entries to return.",
|
|
910
1028
|
),
|
|
911
1029
|
] = 200,
|
|
912
1030
|
) -> dict[str, Any]:
|
|
@@ -916,6 +1034,8 @@ def register_backup_tools(
|
|
|
916
1034
|
if scope == "snapshot":
|
|
917
1035
|
if action == "create":
|
|
918
1036
|
return await create_backup(client, name)
|
|
1037
|
+
if action == "list":
|
|
1038
|
+
return await list_backups(client, limit)
|
|
919
1039
|
# action == "restore"
|
|
920
1040
|
bid = _require("backup_id", backup_id, scope, action)
|
|
921
1041
|
return await restore_backup(client, bid, restore_database)
|
|
@@ -57,7 +57,11 @@ CALLER_TOKEN_BOOTSTRAP_SERVICE = "get_caller_token"
|
|
|
57
57
|
# ``themes/*.yaml`` yaml_path scope; a <0.8.0 component reaches the old
|
|
58
58
|
# handler and rejects ``themes/<name>.yaml`` with a misleading "not
|
|
59
59
|
# allowed" message instead of this actionable update prompt.
|
|
60
|
-
|
|
60
|
+
# 0.9.0: the file tools accept absolute HAOS sibling-volume paths (/share,
|
|
61
|
+
# /media, /ssl, /backup — issue #1586). A <0.9.0 component's allowlist
|
|
62
|
+
# normalizer rejects every absolute path, so adding a volume would silently
|
|
63
|
+
# do nothing; the version gate surfaces an actionable "update" prompt instead.
|
|
64
|
+
MIN_COMPONENT_VERSION = "0.9.0"
|
|
61
65
|
|
|
62
66
|
|
|
63
67
|
def _version_tuple(version: str) -> tuple[int, ...]:
|
|
@@ -333,9 +337,12 @@ class FilesystemTools:
|
|
|
333
337
|
str,
|
|
334
338
|
Field(
|
|
335
339
|
description=(
|
|
336
|
-
"Relative
|
|
337
|
-
"
|
|
338
|
-
"
|
|
340
|
+
"Directory path. Relative to the config dir for the built-in "
|
|
341
|
+
"allowlist (www/, themes/, custom_templates/, dashboards/). "
|
|
342
|
+
"Custom directories and HAOS sibling volumes "
|
|
343
|
+
"(/share, /media, /ssl, /backup) configured in the ha-mcp "
|
|
344
|
+
"settings UI are also allowed (pass the absolute path). "
|
|
345
|
+
"Example: 'www/' or '/share/llm'"
|
|
339
346
|
),
|
|
340
347
|
),
|
|
341
348
|
],
|
|
@@ -360,7 +367,9 @@ class FilesystemTools:
|
|
|
360
367
|
- `themes/` - Theme files
|
|
361
368
|
- `custom_templates/` - Jinja2 template files
|
|
362
369
|
- `dashboards/` - YAML-mode dashboard files
|
|
363
|
-
- Plus any custom directories
|
|
370
|
+
- Plus any custom directories OR HAOS sibling volumes (`/share`,
|
|
371
|
+
`/media`, `/ssl`, `/backup`) configured in the ha-mcp settings UI
|
|
372
|
+
(pass the absolute path for volumes)
|
|
364
373
|
|
|
365
374
|
**Security:** Only directories in the allowed list can be accessed.
|
|
366
375
|
Path traversal attempts (../) are blocked.
|
|
@@ -435,8 +444,10 @@ class FilesystemTools:
|
|
|
435
444
|
str,
|
|
436
445
|
Field(
|
|
437
446
|
description=(
|
|
438
|
-
"
|
|
439
|
-
"
|
|
447
|
+
"File path. Relative to the config dir for the built-in "
|
|
448
|
+
"allowlist; absolute for a configured HAOS sibling volume "
|
|
449
|
+
"(/share, /media, /ssl, /backup). Examples: "
|
|
450
|
+
"'configuration.yaml', 'www/custom.css', '/share/llm/notes.md'"
|
|
440
451
|
),
|
|
441
452
|
),
|
|
442
453
|
],
|
|
@@ -468,7 +479,9 @@ class FilesystemTools:
|
|
|
468
479
|
- `home-assistant.log` (tail only)
|
|
469
480
|
- `www/**`, `themes/**`, `custom_templates/**`, `dashboards/**`
|
|
470
481
|
- `custom_components/**/*.py` (read-only)
|
|
471
|
-
- Plus any custom directories
|
|
482
|
+
- Plus any custom directories OR HAOS sibling volumes (`/share`,
|
|
483
|
+
`/media`, `/ssl`, `/backup`) configured in the ha-mcp settings UI
|
|
484
|
+
(pass the absolute path for volumes)
|
|
472
485
|
|
|
473
486
|
**Security:**
|
|
474
487
|
- Path traversal (../) is blocked
|
|
@@ -546,9 +559,11 @@ class FilesystemTools:
|
|
|
546
559
|
str,
|
|
547
560
|
Field(
|
|
548
561
|
description=(
|
|
549
|
-
"
|
|
550
|
-
"
|
|
551
|
-
"
|
|
562
|
+
"File path. Must be in a writable built-in dir (www/, "
|
|
563
|
+
"themes/, custom_templates/, dashboards/), a configured "
|
|
564
|
+
"custom directory, or a configured HAOS sibling volume "
|
|
565
|
+
"(/share, /media, /ssl, /backup — pass the absolute path). "
|
|
566
|
+
"Example: 'www/custom.css', '/share/llm/out.txt'"
|
|
552
567
|
),
|
|
553
568
|
),
|
|
554
569
|
],
|
|
@@ -590,7 +605,9 @@ class FilesystemTools:
|
|
|
590
605
|
- `themes/` - Theme YAML files
|
|
591
606
|
- `custom_templates/` - Jinja2 template files
|
|
592
607
|
- `dashboards/` - YAML-mode dashboard files
|
|
593
|
-
- Plus any custom directories
|
|
608
|
+
- Plus any custom directories OR HAOS sibling volumes (`/share`,
|
|
609
|
+
`/media`, `/ssl`, `/backup`) configured in the ha-mcp settings UI
|
|
610
|
+
(pass the absolute path for volumes)
|
|
594
611
|
|
|
595
612
|
**Security:**
|
|
596
613
|
- Only the directories above allow writes
|
|
@@ -678,8 +695,10 @@ class FilesystemTools:
|
|
|
678
695
|
str,
|
|
679
696
|
Field(
|
|
680
697
|
description=(
|
|
681
|
-
"
|
|
682
|
-
"
|
|
698
|
+
"File path. Must be in a writable built-in dir (www/, "
|
|
699
|
+
"themes/, custom_templates/, dashboards/), a configured "
|
|
700
|
+
"custom directory, or a configured HAOS sibling volume "
|
|
701
|
+
"(/share, /media, /ssl, /backup — pass the absolute path). "
|
|
683
702
|
"Example: 'www/old-file.css'"
|
|
684
703
|
),
|
|
685
704
|
),
|
|
@@ -705,7 +724,9 @@ class FilesystemTools:
|
|
|
705
724
|
- `themes/` - Theme files
|
|
706
725
|
- `custom_templates/` - Template files
|
|
707
726
|
- `dashboards/` - YAML-mode dashboard files
|
|
708
|
-
- Plus any custom directories
|
|
727
|
+
- Plus any custom directories OR HAOS sibling volumes (`/share`,
|
|
728
|
+
`/media`, `/ssl`, `/backup`) configured in the ha-mcp settings UI
|
|
729
|
+
(pass the absolute path for volumes)
|
|
709
730
|
|
|
710
731
|
**Security:**
|
|
711
732
|
- Only the directories above allow deletions
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ha-mcp-dev
|
|
3
|
-
Version: 7.8.0.
|
|
3
|
+
Version: 7.8.0.dev703
|
|
4
4
|
Summary: Home Assistant MCP Server - Complete control of Home Assistant through MCP
|
|
5
5
|
Author-email: Julien <github@qc-h.net>
|
|
6
6
|
License: MIT
|
|
@@ -275,8 +275,8 @@ Some tools require a companion custom component installed in Home Assistant. Sta
|
|
|
275
275
|
| Tool | Description |
|
|
276
276
|
|------|-------------|
|
|
277
277
|
| `ha_config_set_yaml` *(beta)* | Safely add, replace, or remove top-level YAML keys in `configuration.yaml` and package files (automatic backup, validation, and config check) |
|
|
278
|
-
| `ha_list_files` *(beta)* | List files in allowed directories
|
|
279
|
-
| `ha_read_file` *(beta)* | Read files from allowed paths (config YAML, logs,
|
|
278
|
+
| `ha_list_files` *(beta)* | List files in allowed directories |
|
|
279
|
+
| `ha_read_file` *(beta)* | Read files from allowed paths (config YAML, logs, and allowed directories) |
|
|
280
280
|
| `ha_write_file` *(beta)* | Write files to allowed directories |
|
|
281
281
|
| `ha_delete_file` *(beta)* | Delete files from allowed directories |
|
|
282
282
|
|
|
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.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/dashboard_screenshot/__init__.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/dashboard_screenshot/capture.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/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.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/resources/skills-vendor/AGENTS.md
RENAMED
|
File without changes
|
{ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/resources/skills-vendor/CLAUDE.md
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/resources/skills-vendor/LICENSE
RENAMED
|
File without changes
|
{ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/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
|
{ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/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
|
{ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/smart_search/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/smart_search/_config.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/smart_search/_entities.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/smart_search/_overview.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/smart_search/_scenes.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/smart_search/_scoring.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/tool_search_hint_middleware.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.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/tools_config_automations.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/tools_config_dashboards.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/tools_config_helpers.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/tools_config_scripts.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/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.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/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.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/tools/validation_middleware.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp/transforms/categorized_search.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/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.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/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.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/src/ha_mcp_dev.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{ha_mcp_dev-7.8.0.dev702 → ha_mcp_dev-7.8.0.dev703}/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
|