ha-mcp-dev 7.14.2.dev2181__tar.gz → 7.14.2.dev2185__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.14.2.dev2181/src/ha_mcp_dev.egg-info → ha_mcp_dev-7.14.2.dev2185}/PKG-INFO +1 -1
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/pyproject.toml +1 -1
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_service.py +147 -16
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/util_helpers.py +11 -2
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185/src/ha_mcp_dev.egg-info}/PKG-INFO +1 -1
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/LICENSE +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/MANIFEST.in +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/README.md +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/setup.cfg +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/__init__.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/__main__.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/_pypi_marker +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/_version.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/auth/__init__.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/auth/consent_form.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/auth/provider.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/backup_manager.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/browser_landing.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/client/__init__.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/client/rest_client.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/client/supervisor_client.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/client/websocket_client.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/client/websocket_listener.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/config.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/dashboard_screenshot/__init__.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/dashboard_screenshot/capture.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/dashboard_screenshot/content.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/dashboard_screenshot/paths.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/dashboard_screenshot/provision.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/dashboard_screenshot/theme_guard.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/errors.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/llm_exposure.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/policy/__init__.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/policy/approval_queue.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/policy/evaluator.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/policy/handlers.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/policy/middleware.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/policy/model.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/policy/persistence.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/policy/value_sources.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/py.typed +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/read_only.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/resources/skills-vendor/.claude/settings.json +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/resources/skills-vendor/.claude-plugin/marketplace.json +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/resources/skills-vendor/.claude-plugin/plugin.json +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/resources/skills-vendor/.github/ISSUE_TEMPLATE/skill-rca.md +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/resources/skills-vendor/.github/pull_request_template.md +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/resources/skills-vendor/AGENTS.md +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/resources/skills-vendor/CLAUDE.md +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/resources/skills-vendor/CONTRIBUTING.md +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/resources/skills-vendor/LICENSE +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/resources/skills-vendor/README.md +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/SKILL.md +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/evals/evals.json +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/appdaemon.md +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/automation-patterns.md +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/blueprint-guide.md +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-cards.md +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-guide.md +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/device-control.md +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/domain-docs.md +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/examples.yaml +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/helper-selection.md +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/safe-refactoring.md +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/scenes.md +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/template-guidelines.md +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/yaml-only-integrations.md +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/server.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/settings_ui/__init__.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/settings_ui/_handlers_advanced.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/settings_ui/_handlers_backups.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/settings_ui/_handlers_fs.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/settings_ui/_handlers_server.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/settings_ui/_handlers_theme.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/settings_ui/_handlers_tools.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/settings_ui/_i18n.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/settings_ui/_persistence.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/settings_ui/_supervisor.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/settings_ui/_theme.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/settings_ui/_tools_meta.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/settings_ui/locales/README.md +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/settings_ui/locales/de.json +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/settings_ui/locales/en.json +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/settings_ui/locales/es.json +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/settings_ui/locales/fr.json +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/settings_ui/locales/it.json +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/settings_ui/locales/ru.json +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/settings_ui/locales/zh-Hans.json +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/settings_ui/settings.css +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/settings_ui/settings.html +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/settings_ui/settings.js +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/smoke_test.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/stdio_settings_sidecar.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/strict_bps.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/__init__.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/auto_backup.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/backup.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/best_practice_checker.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/component_api.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/component_config_reads.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/component_devices.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/component_registries.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/component_registry_lookup.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/config_entry_flow.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/device_control.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/helpers.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/radio/__init__.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/radio/base.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/radio/matter.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/radio/thread.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/radio/zigbee.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/radio/zwave.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/reference_validator.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/registry.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/smart_search/__init__.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/smart_search/_base.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/smart_search/_config.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/smart_search/_deep.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/smart_search/_entities.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/smart_search/_fetch.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/smart_search/_overview.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/smart_search/_scenes.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/smart_search/_scoring.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tool_search_hint_middleware.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_addons.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_areas.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_blueprints.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_bug_report.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_calendar.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_camera.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_categories.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_code.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_config_automations.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_config_dashboards.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_config_helpers.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_config_scenes.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_config_scripts.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_dashboard_screenshot.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_dev.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_energy.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_entities.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_filesystem.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_groups.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_hacs.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_history.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_integrations.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_labels.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_radio.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_registry.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_resources.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_search.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_services.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_system.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_themes.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_todo.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_traces.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_updates.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_utility.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_voice_assistant.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_yaml_config.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_yaml_read.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_zones.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/validation_middleware.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/transforms/__init__.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/transforms/categorized_search.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/transforms/lite_docstrings.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/transport_security.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/update_check.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/utils/__init__.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/utils/config_hash.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/utils/config_write_lock.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/utils/data_paths.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/utils/domain_handlers.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/utils/fuzzy_search.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/utils/kill_signal_diagnostics.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/utils/operation_manager.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/utils/python_sandbox.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/utils/skill_loader.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/utils/usage_logger.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/visibility/__init__.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/visibility/enforcement.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/visibility/model.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/visibility/persistence.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/visibility/resolver.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp_dev.egg-info/SOURCES.txt +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp_dev.egg-info/dependency_links.txt +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp_dev.egg-info/entry_points.txt +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp_dev.egg-info/requires.txt +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp_dev.egg-info/top_level.txt +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/tests/__init__.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/tests/test_constants.py +0 -0
- {ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/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.14.2.
|
|
7
|
+
version = "7.14.2.dev2185"
|
|
8
8
|
description = "Home Assistant MCP Server - Complete control of Home Assistant through MCP"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
# Upper bound widened to <3.15 so the package installs on Home Assistant's
|
|
@@ -151,6 +151,32 @@ _NON_STATE_CHANGING_DOMAINS = {
|
|
|
151
151
|
"system_log",
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
+
#: Emitted when a ``return_response=true`` reply is not HA's
|
|
155
|
+
#: ``{"changed_states": [...], "service_response": ...}`` envelope. Without it an
|
|
156
|
+
#: empty ``result`` reads as an affirmative "no entity states changed" rather than
|
|
157
|
+
#: "the records could not be separated out". Module-level so the tests that
|
|
158
|
+
#: pin the behaviour assert against this exact string instead of a prose fragment
|
|
159
|
+
#: that goes tautologically green when the wording is edited.
|
|
160
|
+
_NON_ENVELOPE_WARNING = (
|
|
161
|
+
"Home Assistant's return_response reply did not match the expected "
|
|
162
|
+
"{changed_states, service_response} envelope, so no changed-state records "
|
|
163
|
+
"could be separated from the response data. An empty 'result' here does NOT "
|
|
164
|
+
"mean nothing changed — the whole reply is reported under 'service_response'."
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
#: Emitted when the component served a ``return_response`` call but returned no
|
|
168
|
+
#: ``service_response`` key. The component only sets that key for a non-null
|
|
169
|
+
#: response, so an absent key is ambiguous server-side: the service may genuinely
|
|
170
|
+
#: have returned nothing, or the component may have discarded the response on its
|
|
171
|
+
#: dispatched-but-unconfirmed path. Only raised alongside ``partial`` — the case
|
|
172
|
+
#: where the discard is actually possible — so a plain null response stays quiet.
|
|
173
|
+
_COMPONENT_RESPONSE_UNCONFIRMED_WARNING = (
|
|
174
|
+
"The service was dispatched but its confirmation did not arrive, and no "
|
|
175
|
+
"response data came back with it. A null 'service_response' here does NOT "
|
|
176
|
+
"prove the service returned nothing — the response may have been produced "
|
|
177
|
+
"and lost with the confirmation. Re-read state to confirm the outcome."
|
|
178
|
+
)
|
|
179
|
+
|
|
154
180
|
# ``_SERVICE_TO_STATE`` (the service -> expected primary-state map) is the single
|
|
155
181
|
# source of truth in ``util_helpers`` — imported above and shared with the bulk
|
|
156
182
|
# consumer (``device_control``) so both write paths hand the component the same
|
|
@@ -343,9 +369,18 @@ class ServiceTools:
|
|
|
343
369
|
service: str,
|
|
344
370
|
entity_id: str | None,
|
|
345
371
|
data: str | dict[str, Any] | None,
|
|
372
|
+
*,
|
|
373
|
+
return_response: bool = False,
|
|
346
374
|
) -> dict[str, Any]:
|
|
347
|
-
"""Build a partial-success response for service call timeouts.
|
|
348
|
-
|
|
375
|
+
"""Build a partial-success response for service call timeouts.
|
|
376
|
+
|
|
377
|
+
When ``return_response`` was requested the key is emitted here too, so a
|
|
378
|
+
caller never has to branch on whether the key exists: every successful
|
|
379
|
+
reply carries it. It is necessarily null — the reply never arrived — and
|
|
380
|
+
that null proves nothing about what the service returned, so it comes
|
|
381
|
+
with the same ambiguity warning the component's unconfirmed path uses.
|
|
382
|
+
"""
|
|
383
|
+
response: dict[str, Any] = {
|
|
349
384
|
"success": True,
|
|
350
385
|
"partial": True,
|
|
351
386
|
"domain": domain,
|
|
@@ -366,6 +401,10 @@ class ServiceTools:
|
|
|
366
401
|
"The service was dispatched and may still be executing."
|
|
367
402
|
],
|
|
368
403
|
}
|
|
404
|
+
if return_response:
|
|
405
|
+
response["service_response"] = None
|
|
406
|
+
response["warnings"].append(_COMPONENT_RESPONSE_UNCONFIRMED_WARNING)
|
|
407
|
+
return response
|
|
369
408
|
|
|
370
409
|
async def _capture_initial_state(self, entity_id: str | None) -> str | None:
|
|
371
410
|
"""Capture the current state of an entity before a service call."""
|
|
@@ -406,6 +445,54 @@ class ServiceTools:
|
|
|
406
445
|
f"Service executed but state verification failed: {e}"
|
|
407
446
|
)
|
|
408
447
|
|
|
448
|
+
@staticmethod
|
|
449
|
+
def _split_return_response_envelope(
|
|
450
|
+
result: Any, *, return_response: bool
|
|
451
|
+
) -> tuple[Any, Any, bool, list[str]]:
|
|
452
|
+
"""Split HA's reply into (changed states, response, present, warnings).
|
|
453
|
+
|
|
454
|
+
HA answers ``return_response=true`` with an envelope
|
|
455
|
+
``{"changed_states": [...], "service_response": ...}``. The response data
|
|
456
|
+
belongs at the top level of ha_call_service's reply exactly ONCE — the
|
|
457
|
+
placement the component path (``_build_component_call_response``) already
|
|
458
|
+
uses — so it is peeled off here, BEFORE projection, leaving only the
|
|
459
|
+
changed states to project into ``result``. Returning it in both places
|
|
460
|
+
shipped it twice, byte-identical, doubling its token cost (issue #2085).
|
|
461
|
+
|
|
462
|
+
A legitimately null ``service_response`` is still reported as present
|
|
463
|
+
(``True``) so the caller emits the key.
|
|
464
|
+
|
|
465
|
+
With ``return_response`` false there is no envelope to split: HA returns a
|
|
466
|
+
plain changed-states list, so it passes through untouched and no
|
|
467
|
+
``service_response`` key is emitted (``present`` False). That is the
|
|
468
|
+
overwhelming majority of calls.
|
|
469
|
+
|
|
470
|
+
Anything else — a non-dict reply, a missing key, or a ``changed_states``
|
|
471
|
+
that is not a list — means a non-conforming responder (HA core always
|
|
472
|
+
sends both keys, with a list). Every such shape takes ONE path: the whole
|
|
473
|
+
reply becomes the response data, ``result`` stays empty, and a warning
|
|
474
|
+
says so. Uniformity is the point — peeling a recognised key out of an
|
|
475
|
+
unrecognised envelope would silently discard whatever else it carried,
|
|
476
|
+
and an empty ``result`` would otherwise read as an affirmative "no entity
|
|
477
|
+
states changed". A caller that asked for response data must never get back
|
|
478
|
+
neither the data nor an explanation.
|
|
479
|
+
"""
|
|
480
|
+
if not return_response:
|
|
481
|
+
return result, None, False, []
|
|
482
|
+
if (
|
|
483
|
+
isinstance(result, dict)
|
|
484
|
+
and "service_response" in result
|
|
485
|
+
and isinstance(result.get("changed_states"), list)
|
|
486
|
+
):
|
|
487
|
+
return result["changed_states"], result["service_response"], True, []
|
|
488
|
+
# Any other shape is non-conforming. Hand the WHOLE reply back as the
|
|
489
|
+
# response data rather than guessing which part is which: splitting one
|
|
490
|
+
# recognised key out of an unrecognised envelope discards the rest (a
|
|
491
|
+
# non-list ``changed_states`` would vanish entirely) and would make the
|
|
492
|
+
# warning's "the whole reply is reported under 'service_response'" a lie.
|
|
493
|
+
# Projecting nothing into ``result`` keeps the records from shipping twice.
|
|
494
|
+
return [], result, True, [_NON_ENVELOPE_WARNING]
|
|
495
|
+
|
|
409
496
|
@staticmethod
|
|
410
497
|
def _project_service_result(
|
|
411
498
|
result: Any,
|
|
@@ -420,6 +507,10 @@ class ServiceTools:
|
|
|
420
507
|
Issue #1446. Precedence:
|
|
421
508
|
|
|
422
509
|
- ``verbose=True``: bypass every transformation; return ``result`` as-is.
|
|
510
|
+
(``result`` here is always changed-state records, never an envelope:
|
|
511
|
+
the legacy path splits the envelope off before calling this — see
|
|
512
|
+
``_split_return_response_envelope`` — and the component path passes
|
|
513
|
+
transition ``new_state``s, which are never enveloped to begin with.)
|
|
423
514
|
- Explicit ``fields`` or ``attribute_keys``: apply per-record projection
|
|
424
515
|
via ``project_entity_record`` to every record. No compaction; this is
|
|
425
516
|
the power-user path.
|
|
@@ -470,6 +561,7 @@ class ServiceTools:
|
|
|
470
561
|
service: str,
|
|
471
562
|
entity_id: str | None,
|
|
472
563
|
data: str | dict[str, Any] | None,
|
|
564
|
+
return_response: bool = False,
|
|
473
565
|
) -> dict[str, Any]:
|
|
474
566
|
"""Handle a HomeAssistantConnectionError raised while calling a service.
|
|
475
567
|
|
|
@@ -481,7 +573,9 @@ class ServiceTools:
|
|
|
481
573
|
# mean the service was dispatched but HA didn't respond in time.
|
|
482
574
|
# The operation is likely still running (e.g., update.install, long automations).
|
|
483
575
|
if isinstance(error.__cause__, httpx.TimeoutException):
|
|
484
|
-
return self._build_timeout_response(
|
|
576
|
+
return self._build_timeout_response(
|
|
577
|
+
domain, service, entity_id, data, return_response=return_response
|
|
578
|
+
)
|
|
485
579
|
# Non-timeout connection errors are real failures
|
|
486
580
|
exception_to_structured_error(
|
|
487
581
|
error,
|
|
@@ -892,8 +986,23 @@ class ServiceTools:
|
|
|
892
986
|
}
|
|
893
987
|
if projection_warnings:
|
|
894
988
|
response.setdefault("warnings", []).extend(projection_warnings)
|
|
895
|
-
if return_response
|
|
896
|
-
response
|
|
989
|
+
if return_response:
|
|
990
|
+
# Emit the key whenever it was requested, even for a null response —
|
|
991
|
+
# the legacy path does the same (``_split_return_response_envelope``),
|
|
992
|
+
# and gating on ``is not None`` made the two paths answer the same
|
|
993
|
+
# call with different shapes. The component only sets the key for a
|
|
994
|
+
# non-null response, so a null one arrives as an absent key here.
|
|
995
|
+
response["service_response"] = component_result.get("service_response")
|
|
996
|
+
# ...which makes an absent key ambiguous: genuinely-null response, or
|
|
997
|
+
# one the component produced and dropped with the confirmation on its
|
|
998
|
+
# dispatched-unconfirmed path. Only the latter is possible when
|
|
999
|
+
# ``partial``, so warn there rather than on every null.
|
|
1000
|
+
if "service_response" not in component_result and component_result.get(
|
|
1001
|
+
"partial"
|
|
1002
|
+
):
|
|
1003
|
+
response.setdefault("warnings", []).append(
|
|
1004
|
+
_COMPONENT_RESPONSE_UNCONFIRMED_WARNING
|
|
1005
|
+
)
|
|
897
1006
|
if should_wait:
|
|
898
1007
|
if component_result.get("partial"):
|
|
899
1008
|
# Dispatched, but the confirming state_changed did not arrive within
|
|
@@ -965,7 +1074,9 @@ class ServiceTools:
|
|
|
965
1074
|
return_response=return_response,
|
|
966
1075
|
)
|
|
967
1076
|
if isinstance(component_result, _AmbiguousDispatch):
|
|
968
|
-
return self._build_timeout_response(
|
|
1077
|
+
return self._build_timeout_response(
|
|
1078
|
+
domain, service, entity_id, data, return_response=return_response
|
|
1079
|
+
)
|
|
969
1080
|
if component_result is None:
|
|
970
1081
|
return None
|
|
971
1082
|
return self._build_component_call_response(
|
|
@@ -1003,9 +1114,12 @@ class ServiceTools:
|
|
|
1003
1114
|
bool,
|
|
1004
1115
|
Field(
|
|
1005
1116
|
description=(
|
|
1006
|
-
"Return HA's raw
|
|
1007
|
-
"Use as an escape hatch when you need the full
|
|
1008
|
-
"chain or raw attribute payload (debug /
|
|
1117
|
+
"Return HA's raw changed-state records unchanged (default: "
|
|
1118
|
+
"False). Use as an escape hatch when you need the full "
|
|
1119
|
+
"propagation chain or raw attribute payload (debug / "
|
|
1120
|
+
"inspection). With return_response=True the response data "
|
|
1121
|
+
"still surfaces once as the top-level service_response key, "
|
|
1122
|
+
"never nested in result. "
|
|
1009
1123
|
"WARNING: brings back token-bloat for nested-group targets — "
|
|
1010
1124
|
"prefer result_fields / result_attribute_keys for targeted control."
|
|
1011
1125
|
),
|
|
@@ -1083,8 +1197,12 @@ class ServiceTools:
|
|
|
1083
1197
|
to the targeted entity's record (drops parent-group propagation) and
|
|
1084
1198
|
stripped of ``context`` / ``last_*`` metadata and heavy attribute
|
|
1085
1199
|
lists (``effect_list``, ``hue_scenes``). Escape hatches: ``verbose=True``
|
|
1086
|
-
for the raw
|
|
1087
|
-
for explicit per-record projection (mirrors
|
|
1200
|
+
for the raw changed-state records, or ``result_fields`` /
|
|
1201
|
+
``result_attribute_keys`` for explicit per-record projection (mirrors
|
|
1202
|
+
``ha_get_state``).
|
|
1203
|
+
- **return_response** (default False): the service's response data is
|
|
1204
|
+
returned once, as the top-level ``service_response`` key — never nested
|
|
1205
|
+
inside ``result``, which carries the changed entity states.
|
|
1088
1206
|
|
|
1089
1207
|
**For detailed service documentation, use ha_get_skill_guide.**
|
|
1090
1208
|
|
|
@@ -1177,6 +1295,15 @@ class ServiceTools:
|
|
|
1177
1295
|
domain, service, service_data, return_response=return_response_bool
|
|
1178
1296
|
)
|
|
1179
1297
|
|
|
1298
|
+
# Peel the return_response envelope apart BEFORE projection so the
|
|
1299
|
+
# response data is emitted once, top-level, and only the changed
|
|
1300
|
+
# states reach ``result`` (issue #2085).
|
|
1301
|
+
result, service_response, has_response_envelope, envelope_warnings = (
|
|
1302
|
+
self._split_return_response_envelope(
|
|
1303
|
+
result, return_response=return_response_bool
|
|
1304
|
+
)
|
|
1305
|
+
)
|
|
1306
|
+
|
|
1180
1307
|
projected_result, projection_warnings = self._project_service_result(
|
|
1181
1308
|
result,
|
|
1182
1309
|
entity_id=entity_id,
|
|
@@ -1194,12 +1321,12 @@ class ServiceTools:
|
|
|
1194
1321
|
"result": projected_result,
|
|
1195
1322
|
"message": f"Successfully executed {domain}.{service}",
|
|
1196
1323
|
}
|
|
1197
|
-
|
|
1198
|
-
|
|
1324
|
+
call_warnings = [*projection_warnings, *envelope_warnings]
|
|
1325
|
+
if call_warnings:
|
|
1326
|
+
response.setdefault("warnings", []).extend(call_warnings)
|
|
1199
1327
|
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
response["service_response"] = result.get("service_response", result)
|
|
1328
|
+
if has_response_envelope:
|
|
1329
|
+
response["service_response"] = service_response
|
|
1203
1330
|
|
|
1204
1331
|
# Wait for entity state to change
|
|
1205
1332
|
if should_wait and entity_id is not None:
|
|
@@ -1218,6 +1345,10 @@ class ServiceTools:
|
|
|
1218
1345
|
service=service,
|
|
1219
1346
|
entity_id=entity_id,
|
|
1220
1347
|
data=data,
|
|
1348
|
+
# The parameter, not ``return_response_bool`` — that local is
|
|
1349
|
+
# bound inside the try and would be unbound if the error fired
|
|
1350
|
+
# before it.
|
|
1351
|
+
return_response=return_response,
|
|
1221
1352
|
)
|
|
1222
1353
|
except ToolError:
|
|
1223
1354
|
raise
|
|
@@ -346,8 +346,9 @@ def compact_service_result(
|
|
|
346
346
|
3. Drop known-heavy attribute keys (``effect_list``, ``hue_scenes``) from
|
|
347
347
|
every record's ``attributes`` dict.
|
|
348
348
|
|
|
349
|
-
Returns ``result`` unchanged when not a list (
|
|
350
|
-
|
|
349
|
+
Returns ``result`` unchanged when it is not a list (defensive — every
|
|
350
|
+
ha_call_service path now projects a changed-state list), or when the list
|
|
351
|
+
is empty.
|
|
351
352
|
"""
|
|
352
353
|
if not isinstance(result, list) or not result:
|
|
353
354
|
return result
|
|
@@ -496,6 +497,14 @@ def unwrap_service_response(result: dict[str, Any]) -> dict[str, Any]:
|
|
|
496
497
|
HA's call_service with return_response wraps results in
|
|
497
498
|
{"changed_states": [...], "service_response": {...}}.
|
|
498
499
|
Returns service_response if present and is a dict, otherwise the original result.
|
|
500
|
+
|
|
501
|
+
Deliberately NOT the same rule as ``ServiceTools._split_return_response_envelope``,
|
|
502
|
+
which powers ha_call_service: that one returns the response whatever its type and
|
|
503
|
+
reports the whole reply only when the key is absent. The two disagree solely for a
|
|
504
|
+
NON-DICT ``service_response`` (this helper hands back the envelope, the split hands
|
|
505
|
+
back the value). Consumers here read component services that always answer with a
|
|
506
|
+
dict, so the divergence is unreachable — but do not "align" one to the other
|
|
507
|
+
without checking those ~20 call sites.
|
|
499
508
|
"""
|
|
500
509
|
sr = result.get("service_response")
|
|
501
510
|
return sr if isinstance(sr, dict) else result
|
|
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.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/client/supervisor_client.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/client/websocket_client.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/client/websocket_listener.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/dashboard_screenshot/__init__.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/dashboard_screenshot/capture.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/dashboard_screenshot/content.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/dashboard_screenshot/paths.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/resources/skills-vendor/AGENTS.md
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/resources/skills-vendor/CLAUDE.md
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/resources/skills-vendor/LICENSE
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/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
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/settings_ui/_handlers_advanced.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/settings_ui/_handlers_backups.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/settings_ui/_handlers_fs.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/settings_ui/_handlers_server.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/settings_ui/_handlers_theme.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/settings_ui/_handlers_tools.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/settings_ui/_persistence.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/settings_ui/_supervisor.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/settings_ui/_tools_meta.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/settings_ui/locales/README.md
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/settings_ui/locales/de.json
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/settings_ui/locales/en.json
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/settings_ui/locales/es.json
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/settings_ui/locales/fr.json
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/settings_ui/locales/it.json
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/settings_ui/locales/ru.json
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/settings_ui/locales/zh-Hans.json
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/settings_ui/settings.html
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/stdio_settings_sidecar.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/best_practice_checker.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/component_config_reads.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/component_devices.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/component_registries.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/config_entry_flow.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.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/reference_validator.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/smart_search/__init__.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/smart_search/_base.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/smart_search/_config.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/smart_search/_deep.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/smart_search/_entities.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/smart_search/_fetch.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/smart_search/_overview.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/smart_search/_scenes.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/smart_search/_scoring.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_blueprints.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_bug_report.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_categories.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_config_automations.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_config_dashboards.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_config_helpers.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_config_scenes.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_config_scripts.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_filesystem.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_integrations.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
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_voice_assistant.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/tools_yaml_config.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/tools/validation_middleware.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/transforms/categorized_search.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/transforms/lite_docstrings.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/utils/config_write_lock.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/utils/kill_signal_diagnostics.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/utils/operation_manager.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/visibility/enforcement.py
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp/visibility/persistence.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp_dev.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp_dev.egg-info/entry_points.txt
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp_dev.egg-info/requires.txt
RENAMED
|
File without changes
|
{ha_mcp_dev-7.14.2.dev2181 → ha_mcp_dev-7.14.2.dev2185}/src/ha_mcp_dev.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|