ha-mcp-dev 8.2.0.dev2358__tar.gz → 8.2.0.dev2360__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-8.2.0.dev2358/src/ha_mcp_dev.egg-info → ha_mcp_dev-8.2.0.dev2360}/PKG-INFO +26 -26
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/README.md +25 -25
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/pyproject.toml +1 -1
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/config.py +1 -1
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/dashboard_screenshot/provision.py +21 -19
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/policy/middleware.py +8 -1
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/policy/persistence.py +49 -1
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/read_only.py +16 -4
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/redaction.py +3 -3
- ha_mcp_dev-8.2.0.dev2360/src/ha_mcp/renamed_tools.py +43 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/server.py +9 -2
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/settings_ui/_persistence.py +29 -4
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/settings_ui/locales/en.json +28 -28
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/settings_ui/settings.js +4 -4
- ha_mcp_dev-8.2.0.dev2360/src/ha_mcp/tools/renamed_tool_middleware.py +78 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/tools_addons.py +76 -68
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/tools_dashboard_screenshot.py +5 -4
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/tools_dev.py +13 -5
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/tools_energy.py +1 -1
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/tools_hacs.py +1 -1
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/tools_integrations.py +1 -1
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/tools_search.py +1 -1
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/tools_utility.py +5 -5
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/transforms/categorized_search.py +23 -8
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/update_check.py +4 -1
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360/src/ha_mcp_dev.egg-info}/PKG-INFO +26 -26
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp_dev.egg-info/SOURCES.txt +2 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/LICENSE +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/MANIFEST.in +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/setup.cfg +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/__init__.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/__main__.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_pypi_marker +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_rich_compat.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/__init__.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/requirements.txt +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/LICENSE +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/MANIFEST.sha256 +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/VENDORED +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/__init__.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/__main__.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/asyncio/__init__.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/asyncio/client.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/asyncio/connection.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/asyncio/messages.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/asyncio/router.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/asyncio/server.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/auth.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/cli.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/client.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/connection.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/datastructures.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/exceptions.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/extensions/__init__.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/extensions/base.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/extensions/permessage_deflate.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/frames.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/headers.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/http11.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/imports.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/legacy/__init__.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/legacy/auth.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/legacy/client.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/legacy/exceptions.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/legacy/framing.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/legacy/handshake.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/legacy/http.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/legacy/protocol.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/legacy/server.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/protocol.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/proxy.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/py.typed +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/server.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/streams.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/sync/__init__.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/sync/client.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/sync/connection.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/sync/messages.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/sync/router.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/sync/server.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/sync/utils.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/trio/__init__.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/trio/client.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/trio/connection.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/trio/messages.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/trio/router.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/trio/server.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/trio/utils.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/typing.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/uri.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/utils.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_vendor/websockets/version.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/_version.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/auth/__init__.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/auth/consent_form.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/auth/oidc_compat.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/auth/provider.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/backup_manager.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/browser_landing.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/client/__init__.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/client/rest_client.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/client/supervisor_client.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/client/websocket_client.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/client/websocket_listener.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/dashboard_screenshot/__init__.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/dashboard_screenshot/capture.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/dashboard_screenshot/content.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/dashboard_screenshot/paths.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/dashboard_screenshot/theme_guard.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/errors.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/hacs_auto_refresh.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/llm_exposure.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/policy/__init__.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/policy/approval_queue.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/policy/editing.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/policy/evaluator.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/policy/handlers.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/policy/model.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/policy/value_sources.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/py.typed +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/resources/skills-vendor/.claude/settings.json +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/resources/skills-vendor/.claude-plugin/marketplace.json +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/resources/skills-vendor/.claude-plugin/plugin.json +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/resources/skills-vendor/.github/ISSUE_TEMPLATE/skill-rca.md +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/resources/skills-vendor/.github/pull_request_template.md +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/resources/skills-vendor/AGENTS.md +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/resources/skills-vendor/CLAUDE.md +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/resources/skills-vendor/CONTRIBUTING.md +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/resources/skills-vendor/LICENSE +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/resources/skills-vendor/README.md +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/SKILL.md +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/evals/evals.json +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/appdaemon.md +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/automation-patterns.md +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/blueprint-guide.md +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-cards.md +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-guide.md +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/device-control.md +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/domain-docs.md +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/examples.yaml +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/helper-selection.md +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/safe-refactoring.md +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/scenes.md +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/template-guidelines.md +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/yaml-only-integrations.md +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/settings_ui/__init__.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/settings_ui/_handlers_advanced.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/settings_ui/_handlers_backups.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/settings_ui/_handlers_fs.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/settings_ui/_handlers_server.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/settings_ui/_handlers_theme.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/settings_ui/_handlers_tools.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/settings_ui/_i18n.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/settings_ui/_supervisor.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/settings_ui/_theme.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/settings_ui/_tools_meta.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/settings_ui/locales/README.md +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/settings_ui/locales/cs.json +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/settings_ui/locales/de.json +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/settings_ui/locales/eo.json +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/settings_ui/locales/es.json +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/settings_ui/locales/fr.json +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/settings_ui/locales/it.json +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/settings_ui/locales/nl.json +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/settings_ui/locales/pl.json +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/settings_ui/locales/ru.json +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/settings_ui/locales/sv.json +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/settings_ui/locales/zh-Hans.json +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/settings_ui/settings.css +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/settings_ui/settings.html +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/smoke_test.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/stdio_settings_sidecar.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/strict_bps.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/__init__.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/auto_backup.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/backup.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/best_practice_checker.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/best_practice_result.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/best_practice_variables.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/component_api.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/component_config_entries.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/component_config_reads.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/component_devices.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/component_registries.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/component_registry_lookup.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/config_entry_flow.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/config_entry_flow_form.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/config_entry_flow_menu.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/config_entry_flow_walker.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/config_entry_identity.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/config_entry_reconfigure.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/config_entry_reload_watch.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/device_control.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/error_log_parsing.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/hacs_registration.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/helpers.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/integration_reconfigure.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/radio/__init__.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/radio/base.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/radio/matter.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/radio/thread.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/radio/zigbee.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/radio/zwave.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/reference_validator.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/registry.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/smart_search/__init__.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/smart_search/_base.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/smart_search/_config.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/smart_search/_deep.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/smart_search/_entities.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/smart_search/_fetch.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/smart_search/_overview.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/smart_search/_scenes.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/smart_search/_scoring.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/tool_search_hint_middleware.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/tools_areas.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/tools_assist_pipeline.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/tools_blueprints.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/tools_bug_report.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/tools_calendar.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/tools_camera.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/tools_categories.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/tools_code.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/tools_config_automations.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/tools_config_dashboards.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/tools_config_helpers.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/tools_config_scenes.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/tools_config_scripts.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/tools_entities.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/tools_filesystem.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/tools_groups.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/tools_history.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/tools_labels.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/tools_radio.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/tools_registry.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/tools_resources.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/tools_security_policy.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/tools_service.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/tools_services.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/tools_system.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/tools_themes.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/tools_todo.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/tools_traces.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/tools_updates.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/tools_voice_assistant.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/tools_yaml_config.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/tools_yaml_read.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/tools_zones.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/util_helpers.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/tools/validation_middleware.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/transforms/__init__.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/transforms/lite_docstrings.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/transport_security.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/utils/__init__.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/utils/config_hash.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/utils/config_write_lock.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/utils/data_paths.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/utils/domain_handlers.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/utils/fuzzy_search.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/utils/kill_signal_diagnostics.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/utils/operation_manager.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/utils/python_sandbox.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/utils/skill_loader.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/utils/usage_logger.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/visibility/__init__.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/visibility/enforcement.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/visibility/model.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/visibility/persistence.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/visibility/resolver.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp_dev.egg-info/dependency_links.txt +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp_dev.egg-info/entry_points.txt +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp_dev.egg-info/requires.txt +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp_dev.egg-info/top_level.txt +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/tests/__init__.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/tests/test_constants.py +0 -0
- {ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/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: 8.2.0.
|
|
3
|
+
Version: 8.2.0.dev2360
|
|
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
|
|
@@ -82,37 +82,37 @@ The recommended way to run ha-mcp is the **HA-MCP Custom Component**. It install
|
|
|
82
82
|
|
|
83
83
|
**Connect URL.** The Configure screen gives you a Home Assistant webhook URL for remote clients — `https://<your-ha-domain>/api/webhook/<webhook-id>` through Nabu Casa or any reverse proxy already pointed at Home Assistant (locally, `http://<ha-host>:8123/api/webhook/<webhook-id>`). For clients on the same network, the server is also reachable directly at `http://<ha-ip>:9584/private_<random>`.
|
|
84
84
|
|
|
85
|
-
- **Replaces other install methods:** the in-process server is a complete, standalone ha-mcp install — it takes the place of the add-on, Docker, and uvx/PyPI (stdio) methods. Run only one; do not run the in-process server alongside another install.
|
|
85
|
+
- **Replaces other install methods:** the in-process server is a complete, standalone ha-mcp install — it takes the place of the app (add-on), Docker, and uvx/PyPI (stdio) methods. Run only one; do not run the in-process server alongside another install.
|
|
86
86
|
- **Local only?** Turn off **Remote access via webhook** in the entry options — no webhook is registered at all, while the direct port and sidebar panel keep working.
|
|
87
87
|
- **Settings panel:** while the server runs, an admin-only **HA-MCP** panel appears in the Home Assistant sidebar for managing tools, feature flags, backups, and themes.
|
|
88
88
|
- **Optional authentication:** set **Webhook authentication** to `ha_auth` to require a Home Assistant account sign-in instead of using the secret URL as the credential.
|
|
89
89
|
- **Manual install (no HACS):** copy `custom_components/ha_mcp_tools/` from this repository into your Home Assistant `config/custom_components/` directory, then restart and add the integration as above.
|
|
90
90
|
|
|
91
|
-
The component's second entry type, the **File & YAML services entry** (**HA-MCP File & YAML Tools**), is only needed if you enable ha-mcp's opt-in file and YAML editing tools (feature flags, off by default) — skip it otherwise; you can add it later at any time. It works with any server type (in-process,
|
|
91
|
+
The component's second entry type, the **File & YAML services entry** (**HA-MCP File & YAML Tools**), is only needed if you enable ha-mcp's opt-in file and YAML editing tools (feature flags, off by default) — skip it otherwise; you can add it later at any time. It works with any server type (in-process, app, Docker, or stdio).
|
|
92
92
|
|
|
93
93
|
[Full in-process server documentation →](docs/in-process-server.md) · [Setup Wizard for client-specific config →](https://homeassistant-ai.github.io/ha-mcp/setup/)
|
|
94
94
|
|
|
95
|
-
### 🏠 Home Assistant
|
|
95
|
+
### 🏠 Home Assistant app (add-on)
|
|
96
96
|
|
|
97
|
-
Prefer to run ha-mcp as a Home Assistant **app
|
|
97
|
+
Prefer to run ha-mcp as a Home Assistant **app (add-on)**? On **Home Assistant OS** and **Supervised** installs it is a close second — no access token to manage, and it works with Claude Desktop, Claude.ai, ChatGPT, and any other MCP client on your local network or configured for remote access.
|
|
98
98
|
|
|
99
99
|
1. Add the repository to your Home Assistant instance:
|
|
100
100
|
|
|
101
101
|
[](https://my.home-assistant.io/redirect/supervisor_add_addon_repository/?repository_url=https%3A%2F%2Fgithub.com%2Fhomeassistant-ai%2Fha-mcp)
|
|
102
102
|
|
|
103
|
-
If that opens the App
|
|
103
|
+
If that opens the App store without an add-repository dialog (a [known Home Assistant issue](https://github.com/home-assistant/my.home-assistant.io/issues/698)), add it manually: **Settings → Apps → Install app → ⋮ → Repositories**, then paste `https://github.com/homeassistant-ai/ha-mcp`.
|
|
104
104
|
|
|
105
|
-
2. Install **"Home Assistant MCP Server"** from
|
|
105
|
+
2. Install **"Home Assistant MCP Server"** from **Settings → Apps → Install app** and click **Start**. *(Home Assistant 2026.2 renamed "Add-ons" to "Apps"; on older versions this is the Add-on store.)*
|
|
106
106
|
3. Open the **Logs** tab to find your unique MCP URL.
|
|
107
107
|
4. Connect your AI client to that URL — **no token or credential setup needed**.
|
|
108
108
|
|
|
109
|
-
[Full
|
|
109
|
+
[Full app documentation →](homeassistant-addon/DOCS.md)
|
|
110
110
|
|
|
111
|
-
> ⚠️ **Configure exactly one install method per client.** The custom component, the
|
|
111
|
+
> ⚠️ **Configure exactly one install method per client.** The custom component, the app, Docker/PyPI, and local stdio are independent ways to run the same server — pick one and point your AI client at that single URL. Keeping two entries for the same server in one client (for example a local `uvx ha-mcp@latest` entry with `HOMEASSISTANT_URL` / `HOMEASSISTANT_TOKEN` alongside an app or component URL) is a known cause of connection hangs.
|
|
112
112
|
|
|
113
113
|
### Other install methods
|
|
114
114
|
|
|
115
|
-
These run the server outside Home Assistant — useful for **Container** / **Core** installs (which can't run
|
|
115
|
+
These run the server outside Home Assistant — useful for **Container** / **Core** installs (which can't run apps) or a separate host. The [Setup Wizard](https://homeassistant-ai.github.io/ha-mcp/setup/) generates the exact client-specific config for each.
|
|
116
116
|
|
|
117
117
|
- **Docker (HTTP server):** run `ghcr.io/homeassistant-ai/ha-mcp` in HTTP mode, pointed at your Home Assistant URL and a long-lived token, and connect your client to its secret URL. See the [Setup Wizard](https://homeassistant-ai.github.io/ha-mcp/setup/) for the full command and per-client config.
|
|
118
118
|
- **PyPI / uvx (HTTP server):** run the published `ha-mcp` package with `uvx ha-mcp@latest` (or pip) as a streamable-HTTP server the same way. Details in the [Setup Wizard](https://homeassistant-ai.github.io/ha-mcp/setup/).
|
|
@@ -122,15 +122,15 @@ These run the server outside Home Assistant — useful for **Container** / **Cor
|
|
|
122
122
|
> ⚠️ **stdio has known transport issues.** The stdio transport has connection problems that streamable HTTP does not ([#1713](https://github.com/homeassistant-ai/ha-mcp/issues/1713)). It is recommended only for demo/testing tinkering — for a real setup, use the custom component or an HTTP method above.
|
|
123
123
|
|
|
124
124
|
<details>
|
|
125
|
-
<summary><b>🌐 Remote access (Nabu Casa / Webhook Proxy
|
|
125
|
+
<summary><b>🌐 Remote access (Nabu Casa / Webhook Proxy app / OpenAI Tunnel)</b></summary>
|
|
126
126
|
|
|
127
|
-
> **Using the HA-MCP custom component?** You do not need the **Webhook Proxy** — the component has its own built-in webhook for remote access (see the **Get Started** quick start at the top). The proxy is for the **
|
|
127
|
+
> **Using the HA-MCP custom component?** You do not need the **Webhook Proxy** — the component has its own built-in webhook for remote access (see the **Get Started** quick start at the top). The proxy is for the **app** (it can also front another external server via its `mcp_server_url` option). The **OpenAI Tunnel** below is different: it applies to **any** install method when Home Assistant isn't publicly reachable at all (no Nabu Casa or reverse proxy).
|
|
128
128
|
|
|
129
|
-
Already have **Nabu Casa** or another reverse proxy pointing at your Home Assistant? The Webhook Proxy
|
|
129
|
+
Already have **Nabu Casa** or another reverse proxy pointing at your Home Assistant? The Webhook Proxy app routes MCP traffic through your existing setup — no separate tunnel or port forwarding needed.
|
|
130
130
|
|
|
131
|
-
1. Install the **MCP Server
|
|
131
|
+
1. Install the **MCP Server app** (see above) and the **Webhook Proxy** app from the same store
|
|
132
132
|
2. Start the webhook proxy and **restart Home Assistant** when prompted
|
|
133
|
-
3. Copy the webhook URL from the
|
|
133
|
+
3. Copy the webhook URL from the app logs:
|
|
134
134
|
```
|
|
135
135
|
MCP Server URL (remote): https://xxxxx.ui.nabu.casa/api/webhook/mcp_xxxxxxxx
|
|
136
136
|
```
|
|
@@ -241,7 +241,7 @@ Spend less time configuring, more time enjoying your smart home.
|
|
|
241
241
|
| **🏠 Control** | Any service, bulk device control, real-time states |
|
|
242
242
|
| **🔧 Manage** | Automations, scripts, helpers, dashboards, areas, zones, groups, calendars, blueprints |
|
|
243
243
|
| **📊 Monitor** | History, statistics, camera snapshots, automation traces, ZHA devices |
|
|
244
|
-
| **💾 System** | Backup/restore, updates,
|
|
244
|
+
| **💾 System** | Backup/restore, updates, apps, device registry |
|
|
245
245
|
| **🔒 Safety** | Read Only Mode toggle, per-tool enable/disable, tool security policies (user approval), automatic edit backups |
|
|
246
246
|
|
|
247
247
|
<details>
|
|
@@ -251,7 +251,7 @@ Spend less time configuring, more time enjoying your smart home.
|
|
|
251
251
|
|
|
252
252
|
| Category | Tools |
|
|
253
253
|
|----------|-------|
|
|
254
|
-
| **
|
|
254
|
+
| **Apps (add-ons)** | `ha_get_app`, `ha_manage_app` |
|
|
255
255
|
| **Areas & Floors** | `ha_list_floors_areas`, `ha_remove_area_or_floor`, `ha_set_area_or_floor` |
|
|
256
256
|
| **Assist** | `ha_manage_pipeline` |
|
|
257
257
|
| **Automations** | `ha_config_get_automation`, `ha_config_remove_automation`, `ha_config_set_automation` |
|
|
@@ -300,7 +300,7 @@ ha-mcp is a standalone server built for **configuring, building, and debugging**
|
|
|
300
300
|
| Build & edit dashboards | No | Yes |
|
|
301
301
|
| Debug automations from traces, read history & logs | No | Yes |
|
|
302
302
|
| Manage helpers, areas, zones, labels, groups | No | Yes |
|
|
303
|
-
| Backups,
|
|
303
|
+
| Backups, apps, HACS, device & entity registry | No | Yes |
|
|
304
304
|
|
|
305
305
|
**Rule of thumb:** Use the built-in integration for voice-style control of devices you have already exposed; use ha-mcp when you want an AI assistant that can also build and maintain your Home Assistant setup.
|
|
306
306
|
|
|
@@ -364,12 +364,12 @@ For setups *without* deferred tool support — models like Claude Haiku, Gemini,
|
|
|
364
364
|
|
|
365
365
|
If your model can't see the tools or your Home Assistant, it may be getting handed the whole tool catalog at once and struggling with it. It's recommended to try the following to see if it helps:
|
|
366
366
|
|
|
367
|
-
- **Enable tool search** (`ENABLE_TOOL_SEARCH=true`, or the
|
|
367
|
+
- **Enable tool search** (`ENABLE_TOOL_SEARCH=true`, or the app option below). Instead of listing every tool up front, the server defers the catalog behind a search interface so the model pulls in only the tools it needs, when it needs them.
|
|
368
368
|
- **Raise the model's context window above the default.** Local runtimes ship with small defaults (Ollama's `num_ctx` is one example) that can't hold a large tool set plus the conversation — increase it well beyond the default.
|
|
369
369
|
|
|
370
370
|
### Enable search-based discovery
|
|
371
371
|
|
|
372
|
-
Set ENABLE_TOOL_SEARCH=true (or toggle the option in the HA
|
|
372
|
+
Set ENABLE_TOOL_SEARCH=true (or toggle the option in the HA app). The full catalog is replaced in the tool list with four entry points plus a small set of always-visible "pinned" tools (ha_search, ha_get_overview, ha_report_issue, etc.). All tools remain callable directly by name once discovered:
|
|
373
373
|
|
|
374
374
|
| Tool | Purpose |
|
|
375
375
|
|------|---------|
|
|
@@ -394,9 +394,9 @@ The proxy split lets MCP clients apply different permission policies per categor
|
|
|
394
394
|
|
|
395
395
|
Leave it off in clients with deferred tool loading (claude.ai, Claude Desktop, Claude Code); the full catalog has no idle cost there, direct calls skip the search step, and the client's built-in tool search is the better choice — there is no benefit to running ha-mcp's on top of it. Whether tools are deferred depends on the client and model combination: the same model can behave differently per client — GitHub Copilot CLI running Claude Sonnet/Opus inlines the full catalog and still benefits from tool search here. Some Codex models and ChatGPT include deferred tools too — check your client/model directly to confirm its features so you don't leave this enabled unnecessarily.
|
|
396
396
|
|
|
397
|
-
> 🔄 **Refresh your client's tool list after changing this (or any) setting.** Toggling `ENABLE_TOOL_SEARCH` (or changing pinned/disabled tools, Read Only Mode, etc.) changes the tools the server exposes, but your AI client keeps serving its **cached** tool list until it re-fetches. Restarting the
|
|
397
|
+
> 🔄 **Refresh your client's tool list after changing this (or any) setting.** Toggling `ENABLE_TOOL_SEARCH` (or changing pinned/disabled tools, Read Only Mode, etc.) changes the tools the server exposes, but your AI client keeps serving its **cached** tool list until it re-fetches. Restarting the app or Home Assistant does **not** refresh the client — reconnect or refresh the MCP server in your client (e.g. re-add/refresh the connector in ChatGPT, or close and reopen Claude Desktop). If you skip this, newly enabled tools won't appear in the client at all, and tools the server no longer exposes still show as available but return `Unknown tool` when called. ChatGPT sometimes keeps serving the stale list even after the connector is removed and re-added under the same name — if tools are still missing after re-adding, delete the connector and create a new one with a **different name**.
|
|
398
398
|
|
|
399
|
-
For the HA
|
|
399
|
+
For the HA app, the same option is documented in [`homeassistant-addon/DOCS.md`](homeassistant-addon/DOCS.md#enable_tool_search) along with the in-add-on settings UI for fine-grained tool enable/disable/pin.
|
|
400
400
|
|
|
401
401
|
---
|
|
402
402
|
|
|
@@ -404,7 +404,7 @@ For the HA add-on, the same option is documented in [`homeassistant-addon/DOCS.m
|
|
|
404
404
|
|
|
405
405
|
Want early access to new features and fixes? Dev releases (`.devN`) are published on every push to master.
|
|
406
406
|
|
|
407
|
-
**[Dev Channel Documentation](docs/dev-channel.md)** — Instructions for pip/uvx, Docker, and Home Assistant
|
|
407
|
+
**[Dev Channel Documentation](docs/dev-channel.md)** — Instructions for pip/uvx, Docker, and Home Assistant app.
|
|
408
408
|
|
|
409
409
|
---
|
|
410
410
|
|
|
@@ -478,17 +478,17 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file
|
|
|
478
478
|
- **[@TomasDJo](https://github.com/TomasDJo)** — Category support for automations, scripts, and scenes.
|
|
479
479
|
- **[@bzelch](https://github.com/bzelch)** — `python_transform` support for automations and scripts.
|
|
480
480
|
- **[@gcormier](https://github.com/gcormier)** — Windows installer improvements: removed unused variable and fixed terminal closing after install.
|
|
481
|
-
- **[@ekobres](https://github.com/ekobres)** — Feature flags for `HAMCP_ENABLE_FILESYSTEM_TOOLS` and the (since removed) `HAMCP_ENABLE_CUSTOM_COMPONENT_INTEGRATION` in the
|
|
481
|
+
- **[@ekobres](https://github.com/ekobres)** — Feature flags for `HAMCP_ENABLE_FILESYSTEM_TOOLS` and the (since removed) `HAMCP_ENABLE_CUSTOM_COMPONENT_INTEGRATION` in the app config, with beta tagging in source and docs.
|
|
482
482
|
- **[@w3z315](https://github.com/w3z315)** — Financial support via [GitHub Sponsors](https://github.com/sponsors/julienld). Thank you! ☕
|
|
483
483
|
- **[@griffinmartin](https://github.com/griffinmartin)** — Added OpenCode (by Anomaly) as a selectable AI client in the setup wizard, with both stdio and streamable HTTP support.
|
|
484
|
-
- **[@hhopke](https://github.com/hhopke)** — Fixed
|
|
484
|
+
- **[@hhopke](https://github.com/hhopke)** — Fixed app (add-on) API calls to route through HA Core ingress proxy instead of direct container connections, fixing `ha_manage_addon` (now `ha_manage_app`) proxy mode on app installs.
|
|
485
485
|
- **[@tomwilkie](https://github.com/tomwilkie)** — JMESPath middleware exploration (#1147) whose review-time token-measurement data informed the design of #1199 and #1225.
|
|
486
486
|
- **[@SealKan](https://github.com/SealKan)** — `fields=`/`attribute_keys=` projection on six read-heavy tools (#1225), `ha_call_event` tool (#1239), dashboards-list helper refactor (#1207), `for:`-field duration-math detector in the best-practice checker (#1264), persistent DCR OAuth client registrations across restarts (#1265), and issue-triage prompt token-budgeting (#1522).
|
|
487
487
|
- **[@KarelTestSpecial](https://github.com/KarelTestSpecial)** — Cached YAML instance to prevent CPU spikes during bulk edits (#1371).
|
|
488
488
|
- **[@corgan2222](https://github.com/corgan2222)** — HA brand assets for custom integration (#1317).
|
|
489
489
|
- **[@drseanwing](https://github.com/drseanwing)** — Progress emission via FastMCP `Context` in long-running tools (#1124); tool-discovery / categorized-search docs (#1123).
|
|
490
490
|
- **[@fnordpig](https://github.com/fnordpig)** — Config subentry support (#1393) and Assist pipeline management tool (#1392).
|
|
491
|
-
- **[@paul43210](https://github.com/paul43210)** — `array_patch` mode in `
|
|
491
|
+
- **[@paul43210](https://github.com/paul43210)** — `array_patch` mode in `ha_manage_app` for atomic GET-modify-POST (#1063).
|
|
492
492
|
- **[@L1AD](https://github.com/L1AD)** — Filed #966 proposing tool security policies; pointed to PolicyLayer's MCP-security work as prior art that inspired the predicate DSL shape.
|
|
493
493
|
- **[@nightcityblade](https://github.com/nightcityblade)** — Updated stale Home Assistant Advanced Mode references after HA 2026.6 made formerly advanced options available by default (#1533).
|
|
494
494
|
- **[@emmelutzer](https://github.com/emmelutzer)** — Financial support via [GitHub Sponsors](https://github.com/sponsors/julienld). Thank you! ☕
|
|
@@ -50,37 +50,37 @@ The recommended way to run ha-mcp is the **HA-MCP Custom Component**. It install
|
|
|
50
50
|
|
|
51
51
|
**Connect URL.** The Configure screen gives you a Home Assistant webhook URL for remote clients — `https://<your-ha-domain>/api/webhook/<webhook-id>` through Nabu Casa or any reverse proxy already pointed at Home Assistant (locally, `http://<ha-host>:8123/api/webhook/<webhook-id>`). For clients on the same network, the server is also reachable directly at `http://<ha-ip>:9584/private_<random>`.
|
|
52
52
|
|
|
53
|
-
- **Replaces other install methods:** the in-process server is a complete, standalone ha-mcp install — it takes the place of the add-on, Docker, and uvx/PyPI (stdio) methods. Run only one; do not run the in-process server alongside another install.
|
|
53
|
+
- **Replaces other install methods:** the in-process server is a complete, standalone ha-mcp install — it takes the place of the app (add-on), Docker, and uvx/PyPI (stdio) methods. Run only one; do not run the in-process server alongside another install.
|
|
54
54
|
- **Local only?** Turn off **Remote access via webhook** in the entry options — no webhook is registered at all, while the direct port and sidebar panel keep working.
|
|
55
55
|
- **Settings panel:** while the server runs, an admin-only **HA-MCP** panel appears in the Home Assistant sidebar for managing tools, feature flags, backups, and themes.
|
|
56
56
|
- **Optional authentication:** set **Webhook authentication** to `ha_auth` to require a Home Assistant account sign-in instead of using the secret URL as the credential.
|
|
57
57
|
- **Manual install (no HACS):** copy `custom_components/ha_mcp_tools/` from this repository into your Home Assistant `config/custom_components/` directory, then restart and add the integration as above.
|
|
58
58
|
|
|
59
|
-
The component's second entry type, the **File & YAML services entry** (**HA-MCP File & YAML Tools**), is only needed if you enable ha-mcp's opt-in file and YAML editing tools (feature flags, off by default) — skip it otherwise; you can add it later at any time. It works with any server type (in-process,
|
|
59
|
+
The component's second entry type, the **File & YAML services entry** (**HA-MCP File & YAML Tools**), is only needed if you enable ha-mcp's opt-in file and YAML editing tools (feature flags, off by default) — skip it otherwise; you can add it later at any time. It works with any server type (in-process, app, Docker, or stdio).
|
|
60
60
|
|
|
61
61
|
[Full in-process server documentation →](docs/in-process-server.md) · [Setup Wizard for client-specific config →](https://homeassistant-ai.github.io/ha-mcp/setup/)
|
|
62
62
|
|
|
63
|
-
### 🏠 Home Assistant
|
|
63
|
+
### 🏠 Home Assistant app (add-on)
|
|
64
64
|
|
|
65
|
-
Prefer to run ha-mcp as a Home Assistant **app
|
|
65
|
+
Prefer to run ha-mcp as a Home Assistant **app (add-on)**? On **Home Assistant OS** and **Supervised** installs it is a close second — no access token to manage, and it works with Claude Desktop, Claude.ai, ChatGPT, and any other MCP client on your local network or configured for remote access.
|
|
66
66
|
|
|
67
67
|
1. Add the repository to your Home Assistant instance:
|
|
68
68
|
|
|
69
69
|
[](https://my.home-assistant.io/redirect/supervisor_add_addon_repository/?repository_url=https%3A%2F%2Fgithub.com%2Fhomeassistant-ai%2Fha-mcp)
|
|
70
70
|
|
|
71
|
-
If that opens the App
|
|
71
|
+
If that opens the App store without an add-repository dialog (a [known Home Assistant issue](https://github.com/home-assistant/my.home-assistant.io/issues/698)), add it manually: **Settings → Apps → Install app → ⋮ → Repositories**, then paste `https://github.com/homeassistant-ai/ha-mcp`.
|
|
72
72
|
|
|
73
|
-
2. Install **"Home Assistant MCP Server"** from
|
|
73
|
+
2. Install **"Home Assistant MCP Server"** from **Settings → Apps → Install app** and click **Start**. *(Home Assistant 2026.2 renamed "Add-ons" to "Apps"; on older versions this is the Add-on store.)*
|
|
74
74
|
3. Open the **Logs** tab to find your unique MCP URL.
|
|
75
75
|
4. Connect your AI client to that URL — **no token or credential setup needed**.
|
|
76
76
|
|
|
77
|
-
[Full
|
|
77
|
+
[Full app documentation →](homeassistant-addon/DOCS.md)
|
|
78
78
|
|
|
79
|
-
> ⚠️ **Configure exactly one install method per client.** The custom component, the
|
|
79
|
+
> ⚠️ **Configure exactly one install method per client.** The custom component, the app, Docker/PyPI, and local stdio are independent ways to run the same server — pick one and point your AI client at that single URL. Keeping two entries for the same server in one client (for example a local `uvx ha-mcp@latest` entry with `HOMEASSISTANT_URL` / `HOMEASSISTANT_TOKEN` alongside an app or component URL) is a known cause of connection hangs.
|
|
80
80
|
|
|
81
81
|
### Other install methods
|
|
82
82
|
|
|
83
|
-
These run the server outside Home Assistant — useful for **Container** / **Core** installs (which can't run
|
|
83
|
+
These run the server outside Home Assistant — useful for **Container** / **Core** installs (which can't run apps) or a separate host. The [Setup Wizard](https://homeassistant-ai.github.io/ha-mcp/setup/) generates the exact client-specific config for each.
|
|
84
84
|
|
|
85
85
|
- **Docker (HTTP server):** run `ghcr.io/homeassistant-ai/ha-mcp` in HTTP mode, pointed at your Home Assistant URL and a long-lived token, and connect your client to its secret URL. See the [Setup Wizard](https://homeassistant-ai.github.io/ha-mcp/setup/) for the full command and per-client config.
|
|
86
86
|
- **PyPI / uvx (HTTP server):** run the published `ha-mcp` package with `uvx ha-mcp@latest` (or pip) as a streamable-HTTP server the same way. Details in the [Setup Wizard](https://homeassistant-ai.github.io/ha-mcp/setup/).
|
|
@@ -90,15 +90,15 @@ These run the server outside Home Assistant — useful for **Container** / **Cor
|
|
|
90
90
|
> ⚠️ **stdio has known transport issues.** The stdio transport has connection problems that streamable HTTP does not ([#1713](https://github.com/homeassistant-ai/ha-mcp/issues/1713)). It is recommended only for demo/testing tinkering — for a real setup, use the custom component or an HTTP method above.
|
|
91
91
|
|
|
92
92
|
<details>
|
|
93
|
-
<summary><b>🌐 Remote access (Nabu Casa / Webhook Proxy
|
|
93
|
+
<summary><b>🌐 Remote access (Nabu Casa / Webhook Proxy app / OpenAI Tunnel)</b></summary>
|
|
94
94
|
|
|
95
|
-
> **Using the HA-MCP custom component?** You do not need the **Webhook Proxy** — the component has its own built-in webhook for remote access (see the **Get Started** quick start at the top). The proxy is for the **
|
|
95
|
+
> **Using the HA-MCP custom component?** You do not need the **Webhook Proxy** — the component has its own built-in webhook for remote access (see the **Get Started** quick start at the top). The proxy is for the **app** (it can also front another external server via its `mcp_server_url` option). The **OpenAI Tunnel** below is different: it applies to **any** install method when Home Assistant isn't publicly reachable at all (no Nabu Casa or reverse proxy).
|
|
96
96
|
|
|
97
|
-
Already have **Nabu Casa** or another reverse proxy pointing at your Home Assistant? The Webhook Proxy
|
|
97
|
+
Already have **Nabu Casa** or another reverse proxy pointing at your Home Assistant? The Webhook Proxy app routes MCP traffic through your existing setup — no separate tunnel or port forwarding needed.
|
|
98
98
|
|
|
99
|
-
1. Install the **MCP Server
|
|
99
|
+
1. Install the **MCP Server app** (see above) and the **Webhook Proxy** app from the same store
|
|
100
100
|
2. Start the webhook proxy and **restart Home Assistant** when prompted
|
|
101
|
-
3. Copy the webhook URL from the
|
|
101
|
+
3. Copy the webhook URL from the app logs:
|
|
102
102
|
```
|
|
103
103
|
MCP Server URL (remote): https://xxxxx.ui.nabu.casa/api/webhook/mcp_xxxxxxxx
|
|
104
104
|
```
|
|
@@ -209,7 +209,7 @@ Spend less time configuring, more time enjoying your smart home.
|
|
|
209
209
|
| **🏠 Control** | Any service, bulk device control, real-time states |
|
|
210
210
|
| **🔧 Manage** | Automations, scripts, helpers, dashboards, areas, zones, groups, calendars, blueprints |
|
|
211
211
|
| **📊 Monitor** | History, statistics, camera snapshots, automation traces, ZHA devices |
|
|
212
|
-
| **💾 System** | Backup/restore, updates,
|
|
212
|
+
| **💾 System** | Backup/restore, updates, apps, device registry |
|
|
213
213
|
| **🔒 Safety** | Read Only Mode toggle, per-tool enable/disable, tool security policies (user approval), automatic edit backups |
|
|
214
214
|
|
|
215
215
|
<details>
|
|
@@ -219,7 +219,7 @@ Spend less time configuring, more time enjoying your smart home.
|
|
|
219
219
|
|
|
220
220
|
| Category | Tools |
|
|
221
221
|
|----------|-------|
|
|
222
|
-
| **
|
|
222
|
+
| **Apps (add-ons)** | `ha_get_app`, `ha_manage_app` |
|
|
223
223
|
| **Areas & Floors** | `ha_list_floors_areas`, `ha_remove_area_or_floor`, `ha_set_area_or_floor` |
|
|
224
224
|
| **Assist** | `ha_manage_pipeline` |
|
|
225
225
|
| **Automations** | `ha_config_get_automation`, `ha_config_remove_automation`, `ha_config_set_automation` |
|
|
@@ -268,7 +268,7 @@ ha-mcp is a standalone server built for **configuring, building, and debugging**
|
|
|
268
268
|
| Build & edit dashboards | No | Yes |
|
|
269
269
|
| Debug automations from traces, read history & logs | No | Yes |
|
|
270
270
|
| Manage helpers, areas, zones, labels, groups | No | Yes |
|
|
271
|
-
| Backups,
|
|
271
|
+
| Backups, apps, HACS, device & entity registry | No | Yes |
|
|
272
272
|
|
|
273
273
|
**Rule of thumb:** Use the built-in integration for voice-style control of devices you have already exposed; use ha-mcp when you want an AI assistant that can also build and maintain your Home Assistant setup.
|
|
274
274
|
|
|
@@ -332,12 +332,12 @@ For setups *without* deferred tool support — models like Claude Haiku, Gemini,
|
|
|
332
332
|
|
|
333
333
|
If your model can't see the tools or your Home Assistant, it may be getting handed the whole tool catalog at once and struggling with it. It's recommended to try the following to see if it helps:
|
|
334
334
|
|
|
335
|
-
- **Enable tool search** (`ENABLE_TOOL_SEARCH=true`, or the
|
|
335
|
+
- **Enable tool search** (`ENABLE_TOOL_SEARCH=true`, or the app option below). Instead of listing every tool up front, the server defers the catalog behind a search interface so the model pulls in only the tools it needs, when it needs them.
|
|
336
336
|
- **Raise the model's context window above the default.** Local runtimes ship with small defaults (Ollama's `num_ctx` is one example) that can't hold a large tool set plus the conversation — increase it well beyond the default.
|
|
337
337
|
|
|
338
338
|
### Enable search-based discovery
|
|
339
339
|
|
|
340
|
-
Set ENABLE_TOOL_SEARCH=true (or toggle the option in the HA
|
|
340
|
+
Set ENABLE_TOOL_SEARCH=true (or toggle the option in the HA app). The full catalog is replaced in the tool list with four entry points plus a small set of always-visible "pinned" tools (ha_search, ha_get_overview, ha_report_issue, etc.). All tools remain callable directly by name once discovered:
|
|
341
341
|
|
|
342
342
|
| Tool | Purpose |
|
|
343
343
|
|------|---------|
|
|
@@ -362,9 +362,9 @@ The proxy split lets MCP clients apply different permission policies per categor
|
|
|
362
362
|
|
|
363
363
|
Leave it off in clients with deferred tool loading (claude.ai, Claude Desktop, Claude Code); the full catalog has no idle cost there, direct calls skip the search step, and the client's built-in tool search is the better choice — there is no benefit to running ha-mcp's on top of it. Whether tools are deferred depends on the client and model combination: the same model can behave differently per client — GitHub Copilot CLI running Claude Sonnet/Opus inlines the full catalog and still benefits from tool search here. Some Codex models and ChatGPT include deferred tools too — check your client/model directly to confirm its features so you don't leave this enabled unnecessarily.
|
|
364
364
|
|
|
365
|
-
> 🔄 **Refresh your client's tool list after changing this (or any) setting.** Toggling `ENABLE_TOOL_SEARCH` (or changing pinned/disabled tools, Read Only Mode, etc.) changes the tools the server exposes, but your AI client keeps serving its **cached** tool list until it re-fetches. Restarting the
|
|
365
|
+
> 🔄 **Refresh your client's tool list after changing this (or any) setting.** Toggling `ENABLE_TOOL_SEARCH` (or changing pinned/disabled tools, Read Only Mode, etc.) changes the tools the server exposes, but your AI client keeps serving its **cached** tool list until it re-fetches. Restarting the app or Home Assistant does **not** refresh the client — reconnect or refresh the MCP server in your client (e.g. re-add/refresh the connector in ChatGPT, or close and reopen Claude Desktop). If you skip this, newly enabled tools won't appear in the client at all, and tools the server no longer exposes still show as available but return `Unknown tool` when called. ChatGPT sometimes keeps serving the stale list even after the connector is removed and re-added under the same name — if tools are still missing after re-adding, delete the connector and create a new one with a **different name**.
|
|
366
366
|
|
|
367
|
-
For the HA
|
|
367
|
+
For the HA app, the same option is documented in [`homeassistant-addon/DOCS.md`](homeassistant-addon/DOCS.md#enable_tool_search) along with the in-add-on settings UI for fine-grained tool enable/disable/pin.
|
|
368
368
|
|
|
369
369
|
---
|
|
370
370
|
|
|
@@ -372,7 +372,7 @@ For the HA add-on, the same option is documented in [`homeassistant-addon/DOCS.m
|
|
|
372
372
|
|
|
373
373
|
Want early access to new features and fixes? Dev releases (`.devN`) are published on every push to master.
|
|
374
374
|
|
|
375
|
-
**[Dev Channel Documentation](docs/dev-channel.md)** — Instructions for pip/uvx, Docker, and Home Assistant
|
|
375
|
+
**[Dev Channel Documentation](docs/dev-channel.md)** — Instructions for pip/uvx, Docker, and Home Assistant app.
|
|
376
376
|
|
|
377
377
|
---
|
|
378
378
|
|
|
@@ -446,17 +446,17 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file
|
|
|
446
446
|
- **[@TomasDJo](https://github.com/TomasDJo)** — Category support for automations, scripts, and scenes.
|
|
447
447
|
- **[@bzelch](https://github.com/bzelch)** — `python_transform` support for automations and scripts.
|
|
448
448
|
- **[@gcormier](https://github.com/gcormier)** — Windows installer improvements: removed unused variable and fixed terminal closing after install.
|
|
449
|
-
- **[@ekobres](https://github.com/ekobres)** — Feature flags for `HAMCP_ENABLE_FILESYSTEM_TOOLS` and the (since removed) `HAMCP_ENABLE_CUSTOM_COMPONENT_INTEGRATION` in the
|
|
449
|
+
- **[@ekobres](https://github.com/ekobres)** — Feature flags for `HAMCP_ENABLE_FILESYSTEM_TOOLS` and the (since removed) `HAMCP_ENABLE_CUSTOM_COMPONENT_INTEGRATION` in the app config, with beta tagging in source and docs.
|
|
450
450
|
- **[@w3z315](https://github.com/w3z315)** — Financial support via [GitHub Sponsors](https://github.com/sponsors/julienld). Thank you! ☕
|
|
451
451
|
- **[@griffinmartin](https://github.com/griffinmartin)** — Added OpenCode (by Anomaly) as a selectable AI client in the setup wizard, with both stdio and streamable HTTP support.
|
|
452
|
-
- **[@hhopke](https://github.com/hhopke)** — Fixed
|
|
452
|
+
- **[@hhopke](https://github.com/hhopke)** — Fixed app (add-on) API calls to route through HA Core ingress proxy instead of direct container connections, fixing `ha_manage_addon` (now `ha_manage_app`) proxy mode on app installs.
|
|
453
453
|
- **[@tomwilkie](https://github.com/tomwilkie)** — JMESPath middleware exploration (#1147) whose review-time token-measurement data informed the design of #1199 and #1225.
|
|
454
454
|
- **[@SealKan](https://github.com/SealKan)** — `fields=`/`attribute_keys=` projection on six read-heavy tools (#1225), `ha_call_event` tool (#1239), dashboards-list helper refactor (#1207), `for:`-field duration-math detector in the best-practice checker (#1264), persistent DCR OAuth client registrations across restarts (#1265), and issue-triage prompt token-budgeting (#1522).
|
|
455
455
|
- **[@KarelTestSpecial](https://github.com/KarelTestSpecial)** — Cached YAML instance to prevent CPU spikes during bulk edits (#1371).
|
|
456
456
|
- **[@corgan2222](https://github.com/corgan2222)** — HA brand assets for custom integration (#1317).
|
|
457
457
|
- **[@drseanwing](https://github.com/drseanwing)** — Progress emission via FastMCP `Context` in long-running tools (#1124); tool-discovery / categorized-search docs (#1123).
|
|
458
458
|
- **[@fnordpig](https://github.com/fnordpig)** — Config subentry support (#1393) and Assist pipeline management tool (#1392).
|
|
459
|
-
- **[@paul43210](https://github.com/paul43210)** — `array_patch` mode in `
|
|
459
|
+
- **[@paul43210](https://github.com/paul43210)** — `array_patch` mode in `ha_manage_app` for atomic GET-modify-POST (#1063).
|
|
460
460
|
- **[@L1AD](https://github.com/L1AD)** — Filed #966 proposing tool security policies; pointed to PolicyLayer's MCP-security work as prior art that inspired the predicate DSL shape.
|
|
461
461
|
- **[@nightcityblade](https://github.com/nightcityblade)** — Updated stale Home Assistant Advanced Mode references after HA 2026.6 made formerly advanced options available by default (#1533).
|
|
462
462
|
- **[@emmelutzer](https://github.com/emmelutzer)** — Financial support via [GitHub Sponsors](https://github.com/sponsors/julienld). Thank you! ☕
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "ha-mcp-dev"
|
|
7
|
-
version = "8.2.0.
|
|
7
|
+
version = "8.2.0.dev2360"
|
|
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
|
|
@@ -341,7 +341,7 @@ class Settings(BaseSettings):
|
|
|
341
341
|
# either direction, and it is absent from the add-on config schemas
|
|
342
342
|
# like enable_dev_mode. A leash on those surfaces, NOT a sandbox: dev
|
|
343
343
|
# mode's update_source/restart can still replace the running server
|
|
344
|
-
# build, and in add-on mode
|
|
344
|
+
# build, and in add-on mode ha_manage_app can reach the add-on's
|
|
345
345
|
# own options and ingress — gate those tools with policy rules (or
|
|
346
346
|
# keep dev mode off) where that boundary matters.
|
|
347
347
|
dev_tools_security_policy_access: bool = Field(
|
{ha_mcp_dev-8.2.0.dev2358 → ha_mcp_dev-8.2.0.dev2360}/src/ha_mcp/dashboard_screenshot/provision.py
RENAMED
|
@@ -13,8 +13,8 @@ startup, never silently installed):
|
|
|
13
13
|
2. **HA OS / Supervised** — ``SUPERVISOR_TOKEN`` is present. The Puppet
|
|
14
14
|
add-on (slug ``*_puppet``) is discovered via the Supervisor REST API and
|
|
15
15
|
reached on the internal network by its hostname. The user must have
|
|
16
|
-
installed + started it themselves (add balloob's
|
|
17
|
-
install "Puppet") — we never auto-install.
|
|
16
|
+
installed + started it themselves (add balloob's repository to the App
|
|
17
|
+
store, then install "Puppet") — we never auto-install.
|
|
18
18
|
3. **Neither** (stdio / standalone) — a clear :class:`ToolError` explaining
|
|
19
19
|
how to enable it.
|
|
20
20
|
"""
|
|
@@ -68,16 +68,17 @@ _REPO_URL = "https://github.com/balloob/home-assistant-addons"
|
|
|
68
68
|
# reused across every engine-troubleshooting message here and in capture.py so
|
|
69
69
|
# a copy edit only has to happen once.
|
|
70
70
|
TOKEN_HINT = (
|
|
71
|
-
"set the
|
|
71
|
+
"set the app's 'access_token' option to a Home Assistant long-lived "
|
|
72
72
|
"access token (create one in Profile > Security, ideally for a dedicated "
|
|
73
73
|
"low-privilege user) and (re)start it"
|
|
74
74
|
)
|
|
75
75
|
|
|
76
76
|
_INSTALL_HELP = (
|
|
77
77
|
"Dashboard screenshot mode is enabled, but the Puppet screenshot engine "
|
|
78
|
-
"add-on is not installed. On HA OS / Supervised: (1) add balloob's
|
|
79
|
-
f"repository ({_REPO_URL}) under Settings >
|
|
80
|
-
"Repositories
|
|
78
|
+
"app (add-on) is not installed. On HA OS / Supervised: (1) add balloob's "
|
|
79
|
+
f"repository ({_REPO_URL}) under Settings > Apps > Install app > ⋮ > "
|
|
80
|
+
"Repositories (Settings > Add-ons > Add-on store before Home Assistant "
|
|
81
|
+
"2026.2), then install the 'Puppet' app; and (2) it REQUIRES a "
|
|
81
82
|
f"token — {TOKEN_HINT}. Without a token the engine only serves a "
|
|
82
83
|
"configuration-instructions page. On Docker / Container, run the Puppet "
|
|
83
84
|
"image as a sidecar (with its access_token set) and point ha-mcp at it via "
|
|
@@ -85,14 +86,15 @@ _INSTALL_HELP = (
|
|
|
85
86
|
)
|
|
86
87
|
|
|
87
88
|
_NOT_STARTED_HELP = (
|
|
88
|
-
"The Puppet screenshot engine add-on is installed but not started.
|
|
89
|
-
|
|
89
|
+
"The Puppet screenshot engine app (add-on) is installed but not started. "
|
|
90
|
+
"Open Settings > Apps > Puppet (Settings > Add-ons > Puppet before Home "
|
|
91
|
+
f"Assistant 2026.2), {TOKEN_HINT} (enable 'Start on boot' to keep "
|
|
90
92
|
"it available)."
|
|
91
93
|
)
|
|
92
94
|
|
|
93
95
|
_STDIO_HELP = (
|
|
94
96
|
"Dashboard screenshot mode needs either HA OS / Supervised (add balloob's "
|
|
95
|
-
"
|
|
97
|
+
"repository to the App store and install the 'Puppet' app) or a Puppet sidecar "
|
|
96
98
|
"reachable via HAMCP_DASHBOARD_SCREENSHOT_ENGINE_URL. This deployment "
|
|
97
99
|
"(stdio / standalone) can host neither — see docs/beta.md."
|
|
98
100
|
)
|
|
@@ -116,10 +118,10 @@ def _select_started_verified_puppet(
|
|
|
116
118
|
raise_tool_error(
|
|
117
119
|
create_error_response(
|
|
118
120
|
ErrorCode.CONFIG_VALIDATION_FAILED,
|
|
119
|
-
"Installed *_puppet
|
|
121
|
+
"Installed *_puppet apps did not match Puppet's expected schema.",
|
|
120
122
|
context={"matched_slugs": [slug for slug, _ in addon_infos]},
|
|
121
123
|
suggestions=[
|
|
122
|
-
"Verify the installed screenshot engine is balloob's Puppet
|
|
124
|
+
"Verify the installed screenshot engine is balloob's Puppet app"
|
|
123
125
|
],
|
|
124
126
|
)
|
|
125
127
|
)
|
|
@@ -128,7 +130,7 @@ def _select_started_verified_puppet(
|
|
|
128
130
|
raise_tool_error(
|
|
129
131
|
create_error_response(
|
|
130
132
|
ErrorCode.SERVICE_CALL_FAILED,
|
|
131
|
-
"The schema-verified Puppet
|
|
133
|
+
"The schema-verified Puppet app is not started.",
|
|
132
134
|
details=_NOT_STARTED_HELP,
|
|
133
135
|
context={"matched_slugs": [slug for slug, _ in verified]},
|
|
134
136
|
)
|
|
@@ -137,7 +139,7 @@ def _select_started_verified_puppet(
|
|
|
137
139
|
raise_tool_error(
|
|
138
140
|
create_error_response(
|
|
139
141
|
ErrorCode.CONFIG_VALIDATION_FAILED,
|
|
140
|
-
"Multiple started Puppet
|
|
142
|
+
"Multiple started Puppet apps matched the expected schema; "
|
|
141
143
|
"refusing an ambiguous target.",
|
|
142
144
|
context={"matched_slugs": [slug for slug, _ in started]},
|
|
143
145
|
)
|
|
@@ -188,7 +190,7 @@ async def resolve_engine() -> EngineTarget:
|
|
|
188
190
|
"Dashboard screenshot mode is not available in this deployment.",
|
|
189
191
|
details=_STDIO_HELP,
|
|
190
192
|
suggestions=[
|
|
191
|
-
"Use HA OS / Supervised and install the screenshot engine
|
|
193
|
+
"Use HA OS / Supervised and install the screenshot engine app",
|
|
192
194
|
"Or run the engine as a sidecar and set "
|
|
193
195
|
+ "HAMCP_DASHBOARD_SCREENSHOT_ENGINE_URL",
|
|
194
196
|
],
|
|
@@ -251,7 +253,7 @@ async def _discover_engine_via_supervisor() -> EngineTarget:
|
|
|
251
253
|
raise_tool_error(
|
|
252
254
|
create_error_response(
|
|
253
255
|
ErrorCode.RESOURCE_NOT_FOUND,
|
|
254
|
-
"The Puppet screenshot engine
|
|
256
|
+
"The Puppet screenshot engine app is not installed.",
|
|
255
257
|
details=_INSTALL_HELP,
|
|
256
258
|
)
|
|
257
259
|
)
|
|
@@ -259,7 +261,7 @@ async def _discover_engine_via_supervisor() -> EngineTarget:
|
|
|
259
261
|
# The /addons list is only reliable for slug discovery (the
|
|
260
262
|
# repo-hash prefix is not known ahead of time). Per-addon details
|
|
261
263
|
# are authoritative on /addons/<slug>/info — the same source
|
|
262
|
-
#
|
|
264
|
+
# ha_manage_app trusts.
|
|
263
265
|
addon_infos: list[tuple[str, dict[str, Any]]] = []
|
|
264
266
|
for match in matches:
|
|
265
267
|
slug = str(match["slug"])
|
|
@@ -273,7 +275,7 @@ async def _discover_engine_via_supervisor() -> EngineTarget:
|
|
|
273
275
|
raise_tool_error(
|
|
274
276
|
create_error_response(
|
|
275
277
|
ErrorCode.SERVICE_CALL_FAILED,
|
|
276
|
-
f"Screenshot engine
|
|
278
|
+
f"Screenshot engine app '{slug}' is started but "
|
|
277
279
|
"the Supervisor returned no hostname/ip_address.",
|
|
278
280
|
context={"slug": slug},
|
|
279
281
|
)
|
|
@@ -293,10 +295,10 @@ async def _discover_engine_via_supervisor() -> EngineTarget:
|
|
|
293
295
|
create_error_response(
|
|
294
296
|
ErrorCode.CONNECTION_FAILED,
|
|
295
297
|
"Could not query the Supervisor to locate the Puppet "
|
|
296
|
-
"screenshot engine
|
|
298
|
+
"screenshot engine app.",
|
|
297
299
|
details=str(e),
|
|
298
300
|
suggestions=[
|
|
299
|
-
"Verify the Puppet
|
|
301
|
+
"Verify the Puppet app is installed and started",
|
|
300
302
|
"Or set HAMCP_DASHBOARD_SCREENSHOT_ENGINE_URL explicitly",
|
|
301
303
|
],
|
|
302
304
|
)
|
|
@@ -12,6 +12,7 @@ from anyio.to_thread import run_sync as run_in_thread
|
|
|
12
12
|
from fastmcp.server.middleware.middleware import CallNext, Middleware, MiddlewareContext
|
|
13
13
|
|
|
14
14
|
from ..errors import ErrorCode, create_error_response
|
|
15
|
+
from ..renamed_tools import current_tool_name
|
|
15
16
|
from ..tools.helpers import raise_tool_error, safe_progress
|
|
16
17
|
from .approval_queue import ApprovalQueue, PendingApproval, compute_args_hash
|
|
17
18
|
from .evaluator import Verdict, evaluate, find_matching_rule
|
|
@@ -100,7 +101,13 @@ class PolicyMiddleware(Middleware):
|
|
|
100
101
|
],
|
|
101
102
|
)
|
|
102
103
|
)
|
|
103
|
-
|
|
104
|
+
# RenamedToolAliasMiddleware runs ahead of this one and normally
|
|
105
|
+
# rewrites a retired name before it arrives. Resolving it again costs a
|
|
106
|
+
# dict lookup and removes the ordering dependency, which here is the
|
|
107
|
+
# difference between gated and ungated: rules are keyed on the current
|
|
108
|
+
# name, and ``evaluate`` returns ALLOW when nothing matches, so a gate
|
|
109
|
+
# reading a stale name lets the call through.
|
|
110
|
+
name = current_tool_name(context.message.name)
|
|
104
111
|
args = context.message.arguments or {}
|
|
105
112
|
|
|
106
113
|
if _passes_ungated(name, args):
|
|
@@ -8,6 +8,7 @@ from pathlib import Path
|
|
|
8
8
|
|
|
9
9
|
from pydantic import ValidationError
|
|
10
10
|
|
|
11
|
+
from ..renamed_tools import RENAMED_TOOLS, current_tool_name
|
|
11
12
|
from .model import Policy, Rule
|
|
12
13
|
|
|
13
14
|
logger = logging.getLogger(__name__)
|
|
@@ -24,9 +25,56 @@ def load_policy(data_dir: Path) -> Policy:
|
|
|
24
25
|
except json.JSONDecodeError as e:
|
|
25
26
|
raise ValueError(f"tool_policy.json is not valid JSON: {e}") from e
|
|
26
27
|
try:
|
|
27
|
-
|
|
28
|
+
policy = Policy.model_validate(raw)
|
|
28
29
|
except ValidationError as e:
|
|
29
30
|
raise ValueError(f"tool_policy.json failed schema validation: {e}") from e
|
|
31
|
+
return _follow_renamed_tools(policy)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _follow_renamed_tools(policy: Policy) -> Policy:
|
|
35
|
+
"""Point rules naming a retired tool at the name it answers to today.
|
|
36
|
+
|
|
37
|
+
A rule is a gate: left on the old name it matches nothing, so a tool the
|
|
38
|
+
user had put behind approval or denial would run ungated after the rename,
|
|
39
|
+
with the rule still visible in the editor as if it applied.
|
|
40
|
+
|
|
41
|
+
Re-keying can leave two rules on one tool, and both are kept on purpose:
|
|
42
|
+
gating is additive — ANY matching rule requires approval — so dropping
|
|
43
|
+
either would weaken the gate the user configured. What the duplication does
|
|
44
|
+
decide is ``remember_minutes``, which the middleware reads off the FIRST
|
|
45
|
+
matching rule, so an inherited rule moves behind the rules that already
|
|
46
|
+
name the current tool: the one authored against the tool as it is called
|
|
47
|
+
today is the deliberate one.
|
|
48
|
+
|
|
49
|
+
Nothing else moves. An inherited rule with no same-tool counterpart keeps
|
|
50
|
+
its position, so a ``*`` rule that used to sit behind it still does — this
|
|
51
|
+
re-keying is not the place to change which rule answers for a tool that
|
|
52
|
+
only ever had one.
|
|
53
|
+
"""
|
|
54
|
+
if not any(rule.tool_name in RENAMED_TOOLS for rule in policy.rules):
|
|
55
|
+
return policy
|
|
56
|
+
|
|
57
|
+
resolved: list[tuple[Rule, bool]] = [
|
|
58
|
+
(rule.model_copy(update={"tool_name": current_tool_name(rule.tool_name)}), True)
|
|
59
|
+
if rule.tool_name in RENAMED_TOOLS
|
|
60
|
+
else (rule, False)
|
|
61
|
+
for rule in policy.rules
|
|
62
|
+
]
|
|
63
|
+
authored: dict[str, int] = {
|
|
64
|
+
rule.tool_name: index
|
|
65
|
+
for index, (rule, inherited) in enumerate(resolved)
|
|
66
|
+
if not inherited
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
def anchor(index: int) -> tuple[int, int]:
|
|
70
|
+
rule, inherited = resolved[index]
|
|
71
|
+
if not inherited:
|
|
72
|
+
return (index, 0)
|
|
73
|
+
# Sort right behind the last rule authored on this tool, or stay put.
|
|
74
|
+
return (authored.get(rule.tool_name, index), 1)
|
|
75
|
+
|
|
76
|
+
order = sorted(range(len(resolved)), key=anchor)
|
|
77
|
+
return policy.model_copy(update={"rules": [resolved[index][0] for index in order]})
|
|
30
78
|
|
|
31
79
|
|
|
32
80
|
def migrate_policy_any_semantics(data_dir: Path) -> bool:
|