ha-mcp-dev 8.5.0.dev2770__tar.gz → 8.5.0.dev2773__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.5.0.dev2770/src/ha_mcp_dev.egg-info → ha_mcp_dev-8.5.0.dev2773}/PKG-INFO +2 -2
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/README.md +1 -1
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/pyproject.toml +1 -1
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/__main__.py +1 -1
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/auth/consent_form.py +2 -1
- ha_mcp_dev-8.5.0.dev2773/src/ha_mcp/client/admin_routes.py +43 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/client/rest_client.py +222 -8
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/hacs_auto_refresh.py +5 -5
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/policy/events.py +16 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/server.py +11 -3
- ha_mcp_dev-8.5.0.dev2773/src/ha_mcp/server_lifespan.py +52 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/helpers.py +13 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/smart_search/_deep.py +10 -1
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/tools_code.py +10 -2
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/util_helpers.py +10 -4
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773/src/ha_mcp_dev.egg-info}/PKG-INFO +2 -2
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp_dev.egg-info/SOURCES.txt +2 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/LICENSE +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/MANIFEST.in +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/setup.cfg +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_pypi_marker +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_rich_compat.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/LICENSE +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/MANIFEST.sha256 +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/REQUIRES.txt +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/VENDORED +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/_compat.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/_install_hints.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/_warnings.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/apps/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/apps/app.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/apps/approval.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/apps/choice.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/apps/config.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/apps/file_upload.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/apps/form.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/apps/generative.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/cli/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/cli/__main__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/cli/apps_dev.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/cli/auth.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/cli/cimd.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/cli/cli.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/cli/client.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/cli/deploy/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/cli/deploy/authentication.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/cli/deploy/command.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/cli/deploy/configuration.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/cli/deploy/credentials.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/cli/deploy/horizon_client.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/cli/deploy/output.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/cli/deploy/state.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/cli/discovery.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/cli/generate.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/cli/install/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/cli/install/claude_code.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/cli/install/claude_desktop.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/cli/install/cursor.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/cli/install/gemini_cli.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/cli/install/goose.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/cli/install/mcp_json.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/cli/install/shared.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/cli/install/stdio.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/cli/run.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/client/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/client/_sdk_context_shim.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/client/auth/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/client/auth/bearer.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/client/auth/client_credentials.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/client/auth/oauth.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/client/caching.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/client/client.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/client/dependencies.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/client/elicitation.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/client/extension_hooks.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/client/group.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/client/logging.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/client/messages.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/client/mixins/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/client/mixins/prompts.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/client/mixins/resources.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/client/mixins/tools.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/client/oauth_callback.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/client/progress.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/client/roots.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/client/sampling/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/client/sampling/handlers/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/client/sampling/handlers/anthropic.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/client/sampling/handlers/google_genai.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/client/sampling/handlers/openai.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/client/telemetry.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/client/transports/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/client/transports/base.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/client/transports/config.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/client/transports/http.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/client/transports/inference.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/client/transports/memory.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/client/transports/sse.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/client/transports/stdio.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/contrib/README.md +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/contrib/bulk_tool_caller/README.md +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/contrib/bulk_tool_caller/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/contrib/bulk_tool_caller/bulk_tool_caller.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/contrib/bulk_tool_caller/example.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/contrib/component_manager/README.md +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/contrib/component_manager/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/contrib/component_manager/component_manager.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/contrib/component_manager/example.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/contrib/mcp_mixin/README.md +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/contrib/mcp_mixin/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/contrib/mcp_mixin/example.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/contrib/mcp_mixin/mcp_mixin.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/decorators.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/dependencies.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/exceptions.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/experimental/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/experimental/transforms/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/experimental/transforms/code_mode.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/mcp_config.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/prompts/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/prompts/base.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/prompts/function_prompt.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/py.typed +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/resources/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/resources/base.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/resources/function_resource.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/resources/security.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/resources/template.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/resources/types.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/auth/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/auth/auth.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/auth/cimd.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/auth/handlers/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/auth/handlers/authorize.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/auth/identity_assertion.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/auth/jwt_issuer.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/auth/middleware.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/auth/oauth_proxy/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/auth/oauth_proxy/consent.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/auth/oauth_proxy/models.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/auth/oauth_proxy/proxy.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/auth/oauth_proxy/ui.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/auth/oauth_proxy/upstream.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/auth/oidc_proxy.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/auth/providers/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/auth/providers/auth0.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/auth/providers/aws.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/auth/providers/azure.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/auth/providers/clerk.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/auth/providers/debug.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/auth/providers/descope.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/auth/providers/discord.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/auth/providers/github.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/auth/providers/google.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/auth/providers/huggingface.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/auth/providers/in_memory.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/auth/providers/introspection.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/auth/providers/jwt.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/auth/providers/keycloak.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/auth/providers/oci.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/auth/providers/propelauth.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/auth/providers/scalekit.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/auth/providers/supabase.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/auth/providers/workos.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/auth/redirect_validation.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/auth/ssrf.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/caching.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/completions.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/context.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/dependencies.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/elicitation.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/event_store.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/extensions.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/http.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/lifespan.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/low_level.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/middleware/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/middleware/authorization.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/middleware/caching.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/middleware/dereference.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/middleware/error_handling.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/middleware/logging.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/middleware/middleware.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/middleware/ping.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/middleware/rate_limiting.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/middleware/response_limiting.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/middleware/timing.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/middleware/tool_injection.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/mixins/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/mixins/lifespan.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/mixins/mcp_operations.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/mixins/transport.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/providers/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/providers/addressing.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/providers/aggregate.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/providers/base.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/providers/fastmcp_provider.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/providers/filesystem.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/providers/filesystem_discovery.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/providers/local_provider/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/providers/local_provider/decorators/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/providers/local_provider/decorators/prompts.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/providers/local_provider/decorators/resources.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/providers/local_provider/decorators/tools.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/providers/local_provider/local_provider.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/providers/openapi/README.md +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/providers/openapi/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/providers/openapi/components.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/providers/openapi/provider.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/providers/openapi/routing.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/providers/prefab_payload.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/providers/prefab_synthesis.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/providers/proxy.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/providers/skills/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/providers/skills/_common.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/providers/skills/claude_provider.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/providers/skills/directory_provider.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/providers/skills/skill_provider.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/providers/skills/vendor_providers.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/providers/wrapped_provider.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/server.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/session_scoped_event_store.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/sessions.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/telemetry.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/transforms/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/transforms/catalog.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/transforms/namespace.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/transforms/prompts_as_tools.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/transforms/resources_as_tools.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/transforms/search/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/transforms/search/base.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/transforms/search/bm25.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/transforms/search/regex.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/transforms/tool_transform.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/transforms/version_filter.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/server/transforms/visibility.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/settings.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/telemetry.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/tools/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/tools/base.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/tools/function_parsing.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/tools/function_tool.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/tools/tool_transform.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/types.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/utilities/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/utilities/asgi_transport.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/utilities/async_utils.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/utilities/auth.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/utilities/authorization.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/utilities/cli.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/utilities/components.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/utilities/docstring_parsing.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/utilities/exceptions.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/utilities/http.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/utilities/inspect.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/utilities/json_schema.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/utilities/json_schema_type.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/utilities/lifespan.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/utilities/logging.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/utilities/mcp_server_config/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/utilities/mcp_server_config/v1/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/utilities/mcp_server_config/v1/environments/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/utilities/mcp_server_config/v1/environments/base.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/utilities/mcp_server_config/v1/environments/uv.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/utilities/mcp_server_config/v1/mcp_server_config.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/utilities/mcp_server_config/v1/schema.json +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/utilities/mcp_server_config/v1/sources/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/utilities/mcp_server_config/v1/sources/base.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/utilities/mcp_server_config/v1/sources/filesystem.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/utilities/mime.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/utilities/openapi/README.md +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/utilities/openapi/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/utilities/openapi/director.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/utilities/openapi/formatters.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/utilities/openapi/json_schema_converter.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/utilities/openapi/models.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/utilities/openapi/parser.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/utilities/openapi/schemas.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/utilities/pagination.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/utilities/prefab.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/utilities/skills.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/utilities/tasks.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/utilities/tests.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/utilities/timeout.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/utilities/token_cache.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/utilities/types.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/utilities/ui.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/utilities/version_check.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/fastmcp/utilities/versions.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/LICENSE +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/MANIFEST.sha256 +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/REQUIRES.txt +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/VENDORED +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/cli/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/cli/claude.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/cli/cli.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/client/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/client/__main__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/client/_input_required.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/client/_memory.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/client/_probe.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/client/_transport.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/client/auth/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/client/auth/exceptions.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/client/auth/extensions/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/client/auth/extensions/client_credentials.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/client/auth/extensions/identity_assertion.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/client/auth/oauth2.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/client/auth/utils.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/client/caching.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/client/client.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/client/context.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/client/extension.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/client/session.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/client/session_group.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/client/sse.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/client/stdio.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/client/streamable_http.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/client/subscriptions.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/os/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/os/posix/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/os/posix/utilities.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/os/win32/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/os/win32/utilities.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/py.typed +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/__main__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/_otel.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/_streamable_http_modern.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/apps.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/auth/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/auth/errors.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/auth/handlers/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/auth/handlers/authorize.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/auth/handlers/metadata.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/auth/handlers/register.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/auth/handlers/revoke.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/auth/handlers/token.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/auth/json_response.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/auth/middleware/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/auth/middleware/auth_context.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/auth/middleware/bearer_auth.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/auth/middleware/client_auth.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/auth/provider.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/auth/routes.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/auth/settings.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/caching.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/connection.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/context.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/elicitation.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/extension.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/fastmcp.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/lowlevel/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/lowlevel/helper_types.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/lowlevel/server.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/mcpserver/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/mcpserver/context.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/mcpserver/exceptions.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/mcpserver/prompts/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/mcpserver/prompts/base.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/mcpserver/prompts/manager.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/mcpserver/resolve.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/mcpserver/resources/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/mcpserver/resources/base.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/mcpserver/resources/resource_manager.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/mcpserver/resources/templates.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/mcpserver/resources/types.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/mcpserver/server.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/mcpserver/tools/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/mcpserver/tools/base.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/mcpserver/tools/tool_manager.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/mcpserver/utilities/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/mcpserver/utilities/context_injection.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/mcpserver/utilities/func_metadata.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/mcpserver/utilities/logging.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/mcpserver/utilities/types.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/models.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/request_state.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/runner.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/session.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/sse.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/stdio.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/streamable_http.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/streamable_http_manager.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/subscriptions.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/transport_security.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/server/validation.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/shared/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/shared/_callable_inspection.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/shared/_compat.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/shared/_context_streams.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/shared/_httpx_utils.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/shared/_otel.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/shared/_stream_protocols.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/shared/auth.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/shared/auth_utils.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/shared/context.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/shared/direct_dispatcher.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/shared/dispatcher.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/shared/exceptions.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/shared/extension.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/shared/inbound.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/shared/jsonrpc_dispatcher.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/shared/memory.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/shared/message.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/shared/metadata_utils.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/shared/path_security.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/shared/peer.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/shared/subscriptions.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/shared/tool_name_validation.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/shared/transport_context.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/shared/uri_template.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/types/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/types/jsonrpc.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/types/methods.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp/types/version.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp_types/LICENSE +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp_types/MANIFEST.sha256 +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp_types/REQUIRES.txt +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp_types/VENDORED +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp_types/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp_types/_types.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp_types/_v2025_11_25/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp_types/_v2026_07_28/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp_types/_wire_base.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp_types/jsonrpc.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp_types/methods.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp_types/py.typed +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/mcp_types/version.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/requirements.txt +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/LICENSE +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/MANIFEST.sha256 +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/VENDORED +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/__main__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/asyncio/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/asyncio/client.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/asyncio/connection.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/asyncio/messages.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/asyncio/router.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/asyncio/server.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/auth.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/cli.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/client.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/connection.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/datastructures.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/exceptions.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/extensions/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/extensions/base.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/extensions/permessage_deflate.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/frames.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/headers.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/http11.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/imports.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/legacy/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/legacy/auth.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/legacy/client.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/legacy/exceptions.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/legacy/framing.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/legacy/handshake.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/legacy/http.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/legacy/protocol.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/legacy/server.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/protocol.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/proxy.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/py.typed +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/server.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/streams.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/sync/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/sync/client.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/sync/connection.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/sync/messages.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/sync/router.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/sync/server.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/sync/utils.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/trio/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/trio/client.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/trio/connection.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/trio/messages.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/trio/router.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/trio/server.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/trio/utils.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/typing.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/uri.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/utils.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_vendor/websockets/version.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/_version.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/auth/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/auth/oidc_compat.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/auth/provider.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/backup_manager.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/browser_landing.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/client/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/client/supervisor_client.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/client/websocket_client.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/client/websocket_listener.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/config.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/dashboard_screenshot/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/dashboard_screenshot/capture.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/dashboard_screenshot/content.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/dashboard_screenshot/paths.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/dashboard_screenshot/provision.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/dashboard_screenshot/theme_guard.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/errors.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/ha_request_queue.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/http_transport.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/llm_exposure.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/log_filters.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/policy/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/policy/approval_queue.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/policy/decision_pin.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/policy/decisions.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/policy/editing.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/policy/evaluator.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/policy/handlers.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/policy/middleware.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/policy/model.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/policy/persistence.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/policy/value_sources.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/py.typed +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/read_only.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/redaction.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/renamed_tools.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/resources/skills-vendor/.claude/settings.json +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/resources/skills-vendor/.claude-plugin/marketplace.json +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/resources/skills-vendor/.claude-plugin/plugin.json +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/resources/skills-vendor/.github/ISSUE_TEMPLATE/skill-rca.md +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/resources/skills-vendor/.github/pull_request_template.md +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/resources/skills-vendor/AGENTS.md +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/resources/skills-vendor/CLAUDE.md +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/resources/skills-vendor/CONTRIBUTING.md +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/resources/skills-vendor/LICENSE +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/resources/skills-vendor/README.md +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/resources/skills-vendor/evals/area-target-over-entity-list/case.yaml +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/resources/skills-vendor/evals/arrive-home-automation/case.yaml +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/resources/skills-vendor/evals/assist-shortcut-card/case.yaml +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/resources/skills-vendor/evals/avg-temperature/case.yaml +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/resources/skills-vendor/evals/backup-deletion-confirmation/case.yaml +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/resources/skills-vendor/evals/blueprint-authoring/case.yaml +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/resources/skills-vendor/evals/button-event-entity/case.yaml +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/resources/skills-vendor/evals/device-id-trigger-migration/case.yaml +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/resources/skills-vendor/evals/helper-flow-fields-not-platform-yaml/case.yaml +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/resources/skills-vendor/evals/media-player-song/case.yaml +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/resources/skills-vendor/evals/motion-light-automation-mode/case.yaml +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/resources/skills-vendor/evals/rename-entity-impact-analysis/case.yaml +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/resources/skills-vendor/evals/template-attributes-yaml-exception/case.yaml +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/resources/skills-vendor/evals/timer-finished-automation/case.yaml +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/resources/skills-vendor/evals/vacuum-last-clean/case.yaml +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/resources/skills-vendor/scripts/check_eval_cases.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/SKILL.md +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/appdaemon.md +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/automation-patterns.md +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/backups.md +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/blueprint-guide.md +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-cards.md +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-guide.md +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/device-control.md +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/domain-docs.md +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/examples.yaml +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/helper-selection.md +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/safe-refactoring.md +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/scenes.md +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/template-guidelines.md +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/yaml-only-integrations.md +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/settings_ui/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/settings_ui/_handlers_advanced.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/settings_ui/_handlers_backups.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/settings_ui/_handlers_fs.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/settings_ui/_handlers_server.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/settings_ui/_handlers_theme.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/settings_ui/_handlers_tools.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/settings_ui/_i18n.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/settings_ui/_locale_policy.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/settings_ui/_persistence.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/settings_ui/_supervisor.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/settings_ui/_theme.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/settings_ui/_tools_meta.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/settings_ui/locales/README.md +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/settings_ui/locales/az.json +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/settings_ui/locales/cs.json +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/settings_ui/locales/de.json +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/settings_ui/locales/en.json +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/settings_ui/locales/eo.json +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/settings_ui/locales/es.json +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/settings_ui/locales/fr.json +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/settings_ui/locales/it.json +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/settings_ui/locales/ko.json +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/settings_ui/locales/nl.json +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/settings_ui/locales/pl.json +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/settings_ui/locales/ru.json +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/settings_ui/locales/sv.json +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/settings_ui/locales/tlh.json +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/settings_ui/locales/zh-Hans.json +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/settings_ui/locales/zh-Hant.json +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/settings_ui/settings.css +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/settings_ui/settings.html +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/settings_ui/settings.js +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/smoke_test.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/stdio_settings_sidecar.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/strict_bps.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tool_dispatch.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/auto_backup.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/backup.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/best_practice_checker.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/best_practice_result.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/best_practice_variables.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/blueprint_sources.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/blueprint_substitute.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/blueprint_write.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/bulk_selector.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/component_api.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/component_config_entries.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/component_config_reads.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/component_dashboard_edit.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/component_devices.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/component_registries.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/component_registry_lookup.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/config_entry_flow.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/config_entry_flow_form.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/config_entry_flow_menu.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/config_entry_flow_walker.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/config_entry_identity.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/config_entry_reconfigure.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/config_entry_reload_watch.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/dashboard_edit_errors.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/dashboard_list_checks.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/device_control.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/entity_registration.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/error_log_parsing.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/hacs_registration.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/integration_reconfigure.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/log_common.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/log_sources.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/log_sources_fault.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/log_sources_supervisor.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/radio/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/radio/base.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/radio/matter.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/radio/thread.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/radio/zigbee.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/radio/zwave.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/reference_validator.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/registry.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/renamed_tool_middleware.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/scene_discovery.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/smart_search/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/smart_search/_base.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/smart_search/_config.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/smart_search/_entities.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/smart_search/_fetch.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/smart_search/_graph.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/smart_search/_overview.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/smart_search/_scenes.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/smart_search/_scoring.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/tool_search_hint_middleware.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/tools_addons.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/tools_areas.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/tools_assist_pipeline.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/tools_blueprints.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/tools_bug_report.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/tools_calendar.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/tools_camera.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/tools_categories.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/tools_config_automations.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/tools_config_dashboards.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/tools_config_helpers.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/tools_config_scenes.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/tools_config_scripts.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/tools_dashboard_screenshot.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/tools_dev.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/tools_energy.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/tools_entities.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/tools_filesystem.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/tools_groups.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/tools_hacs.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/tools_history.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/tools_integrations.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/tools_labels.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/tools_logs.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/tools_radio.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/tools_registry.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/tools_resources.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/tools_search.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/tools_security_policy.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/tools_service.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/tools_services.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/tools_system.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/tools_themes.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/tools_todo.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/tools_traces.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/tools_updates.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/tools_utility.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/tools_voice_assistant.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/tools_yaml_config.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/tools_yaml_read.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/tools_zones.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/validation_middleware.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/transforms/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/transforms/categorized_search.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/transforms/component_search.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/transforms/lite_docstrings.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/transforms/write_tool_note.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/transport_security.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/update_check.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/utils/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/utils/config_hash.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/utils/config_write_lock.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/utils/dashboard_patch.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/utils/data_paths.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/utils/device_registry_semantics.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/utils/domain_handlers.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/utils/entity_membership.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/utils/fuzzy_search.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/utils/kill_signal_diagnostics.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/utils/mcp_client_host.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/utils/operation_manager.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/utils/python_sandbox.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/utils/registry_update_lock.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/utils/skill_loader.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/utils/usage_logger.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/visibility/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/visibility/enforcement.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/visibility/model.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/visibility/persistence.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/visibility/resolver.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp_dev.egg-info/dependency_links.txt +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp_dev.egg-info/entry_points.txt +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp_dev.egg-info/requires.txt +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp_dev.egg-info/top_level.txt +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/tests/__init__.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/tests/test_constants.py +0 -0
- {ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/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.5.0.
|
|
3
|
+
Version: 8.5.0.dev2773
|
|
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
|
|
@@ -143,7 +143,7 @@ Prefer to run ha-mcp as a Home Assistant **app (add-on)**? On **Home Assistant O
|
|
|
143
143
|
|
|
144
144
|
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.
|
|
145
145
|
|
|
146
|
-
- **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.
|
|
146
|
+
- **Docker (HTTP server):** run `ghcr.io/homeassistant-ai/ha-mcp` in HTTP mode, pointed at your Home Assistant URL and a long-lived token (an administrator's is recommended; non-admin tokens work with limitations), 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.
|
|
147
147
|
- **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/).
|
|
148
148
|
- **Local stdio (not recommended):** runs ha-mcp on your own machine over stdio. The one-command installers in the **Demo server** section below use this path; the [Setup Wizard](https://homeassistant-ai.github.io/ha-mcp/setup/) covers connecting it to your own Home Assistant.
|
|
149
149
|
- **OIDC authentication:** gate remote access behind an external identity provider (Authentik, Keycloak, Auth0, etc.) instead of a secret URL — all authenticated users share the server's Home Assistant credentials. See [OIDC Mode](docs/oidc.md).
|
|
@@ -82,7 +82,7 @@ Prefer to run ha-mcp as a Home Assistant **app (add-on)**? On **Home Assistant O
|
|
|
82
82
|
|
|
83
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
|
-
- **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.
|
|
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 (an administrator's is recommended; non-admin tokens work with limitations), 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/).
|
|
87
87
|
- **Local stdio (not recommended):** runs ha-mcp on your own machine over stdio. The one-command installers in the **Demo server** section below use this path; the [Setup Wizard](https://homeassistant-ai.github.io/ha-mcp/setup/) covers connecting it to your own Home Assistant.
|
|
88
88
|
- **OIDC authentication:** gate remote access behind an external identity provider (Authentik, Keycloak, Auth0, etc.) instead of a secret URL — all authenticated users share the server's Home Assistant credentials. See [OIDC Mode](docs/oidc.md).
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "ha-mcp-dev"
|
|
7
|
-
version = "8.5.0.
|
|
7
|
+
version = "8.5.0.dev2773"
|
|
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
|
|
@@ -182,7 +182,7 @@ To fix this, you need to provide your Home Assistant connection details:
|
|
|
182
182
|
1. HOMEASSISTANT_URL - Your Home Assistant instance URL
|
|
183
183
|
Example: http://homeassistant.local:8123
|
|
184
184
|
|
|
185
|
-
2. HOMEASSISTANT_TOKEN - A long-lived access token
|
|
185
|
+
2. HOMEASSISTANT_TOKEN - A long-lived access token (an administrator's is recommended)
|
|
186
186
|
Get one from: Home Assistant -> Profile -> Long-Lived Access Tokens
|
|
187
187
|
|
|
188
188
|
Configuration options:
|
|
@@ -316,7 +316,8 @@ def create_consent_html(
|
|
|
316
316
|
autocomplete="off"
|
|
317
317
|
>
|
|
318
318
|
<p class="help-text">
|
|
319
|
-
Create a token
|
|
319
|
+
Create a token (an administrator's is recommended; non-admin
|
|
320
|
+
tokens work with limitations) at: Home Assistant → Profile →
|
|
320
321
|
<a href="https://www.home-assistant.io/docs/authentication/#your-account-profile" target="_blank" rel="noopener">
|
|
321
322
|
Long-Lived Access Tokens
|
|
322
323
|
</a>
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""REST routes Home Assistant refuses to non-admin users with a counted 401.
|
|
2
|
+
|
|
3
|
+
Each answers a non-admin with a raised 401, which ``http.ban`` counts as a
|
|
4
|
+
failed login, so a burst of them IP-bans the ha-mcp host (#2546). Verified
|
|
5
|
+
against home-assistant/core ``api/__init__.py``,
|
|
6
|
+
``config/{view,core,config_entries}.py`` and ``diagnostics/__init__.py``.
|
|
7
|
+
Not listed: routes that check entity permissions instead (e.g.
|
|
8
|
+
``GET /api/states/<id>``), the hassio proxy (its 401 is returned, not raised,
|
|
9
|
+
so it is not counted), and admin-only services, which ``call_service`` sends
|
|
10
|
+
over WebSocket for a non-admin token.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import re
|
|
14
|
+
|
|
15
|
+
_ANY_METHOD = frozenset({"GET", "POST", "PUT", "PATCH", "DELETE"})
|
|
16
|
+
|
|
17
|
+
_ADMIN_ONLY_ROUTES: tuple[tuple[frozenset[str], re.Pattern[str]], ...] = tuple(
|
|
18
|
+
(frozenset(methods), re.compile(pattern))
|
|
19
|
+
for methods, pattern in (
|
|
20
|
+
({"POST", "DELETE"}, r"states/[^/]+"),
|
|
21
|
+
({"POST"}, r"events/[^/]+"),
|
|
22
|
+
({"GET"}, r"stream"),
|
|
23
|
+
({"POST"}, r"template"),
|
|
24
|
+
({"GET"}, r"error_log"),
|
|
25
|
+
(_ANY_METHOD, r"config/(automation|script|scene)/config/[^/]+"),
|
|
26
|
+
({"POST"}, r"config/core/check_config"),
|
|
27
|
+
({"GET"}, r"diagnostics/[^/]+/[^/]+(/[^/]+/[^/]+)?"),
|
|
28
|
+
({"DELETE"}, r"config/config_entries/entry/[^/]+"),
|
|
29
|
+
({"POST"}, r"config/config_entries/entry/[^/]+/reload"),
|
|
30
|
+
({"POST"}, r"config/config_entries/(options/|subentries/)?flow"),
|
|
31
|
+
({"GET", "POST"}, r"config/config_entries/(options/|subentries/)?flow/[^/]+"),
|
|
32
|
+
)
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def is_admin_only_route(method: str, endpoint: str) -> bool:
|
|
37
|
+
"""True when ``endpoint`` (relative to ``/api``) is admin-only for ``method``."""
|
|
38
|
+
path = endpoint.split("?", 1)[0].strip("/")
|
|
39
|
+
method = method.upper()
|
|
40
|
+
return any(
|
|
41
|
+
method in methods and pattern.fullmatch(path)
|
|
42
|
+
for methods, pattern in _ADMIN_ONLY_ROUTES
|
|
43
|
+
)
|
|
@@ -17,6 +17,7 @@ import httpx
|
|
|
17
17
|
from .._vendor.websockets.exceptions import WebSocketException
|
|
18
18
|
from .._version import get_supervisor_base_url, is_running_in_addon
|
|
19
19
|
from ..config import get_global_settings
|
|
20
|
+
from .admin_routes import is_admin_only_route
|
|
20
21
|
from .supervisor_client import make_supervisor_httpx_client
|
|
21
22
|
|
|
22
23
|
|
|
@@ -70,6 +71,15 @@ MIN_LOG_WINDOW_LINES = 2
|
|
|
70
71
|
# journald's cursor/timestamp metadata exists only in the journal export
|
|
71
72
|
# format, which the hassio-proxy route cannot request.
|
|
72
73
|
_PROBE_ENTRIES = 8
|
|
74
|
+
NON_ADMIN_TOKEN_WARNING = (
|
|
75
|
+
"ha-mcp does not officially support non-admin Home Assistant tokens. They "
|
|
76
|
+
"still work, but admin-only operations fail. Use a long-lived access token "
|
|
77
|
+
"from an administrator's profile for full access."
|
|
78
|
+
)
|
|
79
|
+
_ADMIN_ONLY_401_MESSAGE = (
|
|
80
|
+
"Home Assistant returned 401 for an admin-only endpoint: "
|
|
81
|
+
"the token is invalid or its user is not an administrator"
|
|
82
|
+
)
|
|
73
83
|
|
|
74
84
|
|
|
75
85
|
class HomeAssistantError(Exception):
|
|
@@ -114,6 +124,15 @@ class HomeAssistantAuthError(HomeAssistantError):
|
|
|
114
124
|
"""
|
|
115
125
|
|
|
116
126
|
|
|
127
|
+
class HomeAssistantAdminRequiredError(HomeAssistantAuthError):
|
|
128
|
+
"""An admin-only request refused because the token's user is not an admin.
|
|
129
|
+
|
|
130
|
+
A REST request is refused locally, never sent: Home Assistant would answer
|
|
131
|
+
401 and count it toward its IP ban (#2546). A service call is refused by
|
|
132
|
+
Home Assistant over WebSocket, where a refusal is not counted.
|
|
133
|
+
"""
|
|
134
|
+
|
|
135
|
+
|
|
117
136
|
class HomeAssistantAPIError(HomeAssistantError):
|
|
118
137
|
"""API error from Home Assistant."""
|
|
119
138
|
|
|
@@ -334,6 +353,8 @@ class HomeAssistantClient:
|
|
|
334
353
|
token: str | None = None,
|
|
335
354
|
timeout: int | None = None,
|
|
336
355
|
verify_ssl: bool | None = None,
|
|
356
|
+
is_admin: bool | None = None,
|
|
357
|
+
admin_route_refused: bool = False,
|
|
337
358
|
):
|
|
338
359
|
"""
|
|
339
360
|
Initialize Home Assistant client.
|
|
@@ -345,6 +366,10 @@ class HomeAssistantClient:
|
|
|
345
366
|
verify_ssl: Whether to verify the HA server's TLS certificate
|
|
346
367
|
(defaults to ``settings.verify_ssl``). Pass False to allow
|
|
347
368
|
self-signed certs or hostname mismatches.
|
|
369
|
+
is_admin: Whether the token's user is an administrator, when
|
|
370
|
+
another client for the same token already knows.
|
|
371
|
+
admin_route_refused: Whether another client for the same token
|
|
372
|
+
already got a 401 on an admin-only request.
|
|
348
373
|
"""
|
|
349
374
|
if base_url is None or token is None or verify_ssl is None:
|
|
350
375
|
settings = get_global_settings()
|
|
@@ -386,6 +411,14 @@ class HomeAssistantClient:
|
|
|
386
411
|
# disable the supervised branch — subsequent calls re-probe.
|
|
387
412
|
self._supervised_detected: bool | None = None
|
|
388
413
|
|
|
414
|
+
# Whether the token's user is an admin; ``None`` until Home Assistant
|
|
415
|
+
# has answered. See ``token_is_admin`` and ``guarded_request``.
|
|
416
|
+
self._is_admin: bool | None = is_admin
|
|
417
|
+
# Set by a 401 on an admin-only route or service call, so no further
|
|
418
|
+
# admin-only request is sent over REST. See ``guarded_request``.
|
|
419
|
+
self._admin_route_refused = admin_route_refused
|
|
420
|
+
self._admin_route_lock = asyncio.Lock()
|
|
421
|
+
|
|
389
422
|
logger.info(f"Initialized Home Assistant client for {self.base_url}")
|
|
390
423
|
|
|
391
424
|
async def __aenter__(self) -> "HomeAssistantClient":
|
|
@@ -432,6 +465,8 @@ class HomeAssistantClient:
|
|
|
432
465
|
is never replayed.
|
|
433
466
|
|
|
434
467
|
Raises:
|
|
468
|
+
HomeAssistantAdminRequiredError: Admin-only route refused without
|
|
469
|
+
being sent (see ``guarded_request``).
|
|
435
470
|
HomeAssistantAuthError: 401 response.
|
|
436
471
|
HomeAssistantAPIError: Non-2xx response (with status_code and
|
|
437
472
|
response_data set from JSON body when possible).
|
|
@@ -440,10 +475,14 @@ class HomeAssistantClient:
|
|
|
440
475
|
backoff = 0.5
|
|
441
476
|
for attempt in range(1, _MAX_REQUEST_ATTEMPTS + 1):
|
|
442
477
|
try:
|
|
443
|
-
response = await self.
|
|
478
|
+
response = await self.guarded_request(method, endpoint, **kwargs)
|
|
444
479
|
|
|
445
480
|
if response.status_code == 401:
|
|
446
|
-
raise HomeAssistantAuthError(
|
|
481
|
+
raise HomeAssistantAuthError(
|
|
482
|
+
_ADMIN_ONLY_401_MESSAGE
|
|
483
|
+
if is_admin_only_route(method, endpoint)
|
|
484
|
+
else "Invalid authentication token"
|
|
485
|
+
)
|
|
447
486
|
|
|
448
487
|
if response.status_code >= 400:
|
|
449
488
|
message, error_data = self._error_message_from_response(response)
|
|
@@ -488,6 +527,104 @@ class HomeAssistantClient:
|
|
|
488
527
|
# Unreachable: the final attempt takes the non-retry branch and raises.
|
|
489
528
|
raise AssertionError("_raw_request retry loop exhausted without returning")
|
|
490
529
|
|
|
530
|
+
async def guarded_request(
|
|
531
|
+
self, method: str, endpoint: str, **kwargs: Any
|
|
532
|
+
) -> httpx.Response:
|
|
533
|
+
"""Send a request, unless it is an admin-only route this token can't use.
|
|
534
|
+
|
|
535
|
+
Raises ``HomeAssistantAdminRequiredError`` without sending when the
|
|
536
|
+
token is known to be a non-admin's, or after an admin-only request got
|
|
537
|
+
401. While Home Assistant has not answered whether the token is an
|
|
538
|
+
admin's, admin-only requests go out one at a time and the first
|
|
539
|
+
response settles it: a 401 stops further ones, and a 2xx proves the
|
|
540
|
+
token is an admin's (a 404 or 405 can come before the admin gate).
|
|
541
|
+
"""
|
|
542
|
+
if not is_admin_only_route(method, endpoint):
|
|
543
|
+
return await self.httpx_client.request(method, endpoint, **kwargs)
|
|
544
|
+
if self._is_admin is True:
|
|
545
|
+
response = await self.httpx_client.request(method, endpoint, **kwargs)
|
|
546
|
+
self._note_admin_route_response(response)
|
|
547
|
+
return response
|
|
548
|
+
async with self._admin_route_lock:
|
|
549
|
+
route = f"{method.upper()} /api/{endpoint.lstrip('/')}"
|
|
550
|
+
if self._admin_route_refused:
|
|
551
|
+
raise HomeAssistantAdminRequiredError(
|
|
552
|
+
f"{route} not sent: an earlier admin-only request got 401 "
|
|
553
|
+
"(the token is invalid or its user is not an administrator)"
|
|
554
|
+
)
|
|
555
|
+
is_admin = await self.token_is_admin()
|
|
556
|
+
if is_admin is False:
|
|
557
|
+
raise HomeAssistantAdminRequiredError(
|
|
558
|
+
f"{route} is admin-only in Home Assistant and this token's "
|
|
559
|
+
"user is not an administrator"
|
|
560
|
+
)
|
|
561
|
+
response = await self.httpx_client.request(method, endpoint, **kwargs)
|
|
562
|
+
if is_admin is None and 200 <= response.status_code < 300:
|
|
563
|
+
self._is_admin = True
|
|
564
|
+
self._note_admin_route_response(response)
|
|
565
|
+
return response
|
|
566
|
+
|
|
567
|
+
def _note_admin_route_response(self, response: httpx.Response) -> None:
|
|
568
|
+
if response.status_code == 401:
|
|
569
|
+
self._is_admin = None
|
|
570
|
+
self._admin_route_refused = True
|
|
571
|
+
|
|
572
|
+
@property
|
|
573
|
+
def admin_route_refused(self) -> bool:
|
|
574
|
+
"""Whether admin-only requests are being refused for this token."""
|
|
575
|
+
return self._is_admin is False or self._admin_route_refused
|
|
576
|
+
|
|
577
|
+
@property
|
|
578
|
+
def known_is_admin(self) -> bool | None:
|
|
579
|
+
"""The cached answer to ``token_is_admin``, without asking."""
|
|
580
|
+
return self._is_admin
|
|
581
|
+
|
|
582
|
+
async def token_is_admin(self) -> bool | None:
|
|
583
|
+
"""Whether this token's user is a Home Assistant administrator.
|
|
584
|
+
|
|
585
|
+
``None`` when Home Assistant gave no answer; only a definite answer is
|
|
586
|
+
cached. The first non-admin answer logs ``NON_ADMIN_TOKEN_WARNING``.
|
|
587
|
+
"""
|
|
588
|
+
if self._is_admin is None:
|
|
589
|
+
user = await self._current_user()
|
|
590
|
+
is_admin = user.get("is_admin") if user else None
|
|
591
|
+
if not isinstance(is_admin, bool):
|
|
592
|
+
return None
|
|
593
|
+
self._is_admin = is_admin
|
|
594
|
+
if not is_admin:
|
|
595
|
+
logger.warning(
|
|
596
|
+
"The Home Assistant token for %s belongs to a non-admin user. %s",
|
|
597
|
+
self.base_url,
|
|
598
|
+
NON_ADMIN_TOKEN_WARNING,
|
|
599
|
+
)
|
|
600
|
+
return self._is_admin
|
|
601
|
+
|
|
602
|
+
async def _current_user(self) -> dict[str, Any] | None:
|
|
603
|
+
"""``auth/current_user`` for this token, or ``None`` when it can't be asked.
|
|
604
|
+
|
|
605
|
+
Asked over WebSocket because ``auth/current_user`` answers every user;
|
|
606
|
+
REST has no such route, only admin-only ones whose 401 would count
|
|
607
|
+
toward ``http.ban``. It uses a connection of its own: the pooled one
|
|
608
|
+
may be serving the caller's own event handler (a policy result event
|
|
609
|
+
fired from the bus), which would wait on itself.
|
|
610
|
+
"""
|
|
611
|
+
from .websocket_client import HomeAssistantWebSocketClient
|
|
612
|
+
|
|
613
|
+
ws = HomeAssistantWebSocketClient(
|
|
614
|
+
self.base_url, self.token, verify_ssl=self.verify_ssl
|
|
615
|
+
)
|
|
616
|
+
try:
|
|
617
|
+
if not await ws.connect():
|
|
618
|
+
return None
|
|
619
|
+
reply = await ws.send_command("auth/current_user")
|
|
620
|
+
except (HomeAssistantError, WebSocketException, OSError) as e:
|
|
621
|
+
logger.debug(f"auth/current_user probe failed: {e}")
|
|
622
|
+
return None
|
|
623
|
+
finally:
|
|
624
|
+
await ws.disconnect()
|
|
625
|
+
user = reply.get("result")
|
|
626
|
+
return user if isinstance(user, dict) else None
|
|
627
|
+
|
|
491
628
|
async def _request(
|
|
492
629
|
self, method: str, endpoint: str, **kwargs: Any
|
|
493
630
|
) -> dict[str, Any]:
|
|
@@ -582,17 +719,55 @@ class HomeAssistantClient:
|
|
|
582
719
|
|
|
583
720
|
payload = data or {}
|
|
584
721
|
|
|
722
|
+
if self._admin_route_refused or await self.token_is_admin() is False:
|
|
723
|
+
return await self._call_service_over_websocket(
|
|
724
|
+
domain, service, payload, return_response
|
|
725
|
+
)
|
|
726
|
+
if self._is_admin is True:
|
|
727
|
+
return await self._call_service_over_rest(
|
|
728
|
+
domain, service, payload, return_response
|
|
729
|
+
)
|
|
730
|
+
# Admin status unknown: one REST call at a time, so a 401 for an
|
|
731
|
+
# admin-only service latches before a second is sent.
|
|
732
|
+
async with self._admin_route_lock:
|
|
733
|
+
if self._admin_route_refused:
|
|
734
|
+
return await self._call_service_over_websocket(
|
|
735
|
+
domain, service, payload, return_response
|
|
736
|
+
)
|
|
737
|
+
return await self._call_service_over_rest(
|
|
738
|
+
domain, service, payload, return_response
|
|
739
|
+
)
|
|
740
|
+
|
|
741
|
+
async def _call_service_over_rest(
|
|
742
|
+
self,
|
|
743
|
+
domain: str,
|
|
744
|
+
service: str,
|
|
745
|
+
payload: dict[str, Any],
|
|
746
|
+
return_response: bool,
|
|
747
|
+
) -> list[dict[str, Any]] | dict[str, Any]:
|
|
748
|
+
"""POST the service call; on a 401 latch and retry it over WebSocket.
|
|
749
|
+
|
|
750
|
+
A 401 means Home Assistant refused before running the service, so the
|
|
751
|
+
WebSocket retry cannot apply it twice.
|
|
752
|
+
"""
|
|
585
753
|
# Build query params for return_response
|
|
586
754
|
params = {}
|
|
587
755
|
if return_response:
|
|
588
756
|
params["return_response"] = "true"
|
|
589
757
|
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
758
|
+
try:
|
|
759
|
+
result = await self._request(
|
|
760
|
+
"POST",
|
|
761
|
+
f"/services/{domain}/{service}",
|
|
762
|
+
json=payload,
|
|
763
|
+
params=params if params else None,
|
|
764
|
+
)
|
|
765
|
+
except HomeAssistantAuthError:
|
|
766
|
+
self._is_admin = None
|
|
767
|
+
self._admin_route_refused = True
|
|
768
|
+
return await self._call_service_over_websocket(
|
|
769
|
+
domain, service, payload, return_response
|
|
770
|
+
)
|
|
596
771
|
|
|
597
772
|
# When return_response is True, HA returns a dict with service_response key
|
|
598
773
|
if return_response:
|
|
@@ -606,6 +781,45 @@ class HomeAssistantClient:
|
|
|
606
781
|
else:
|
|
607
782
|
return []
|
|
608
783
|
|
|
784
|
+
async def _call_service_over_websocket(
|
|
785
|
+
self,
|
|
786
|
+
domain: str,
|
|
787
|
+
service: str,
|
|
788
|
+
payload: dict[str, Any],
|
|
789
|
+
return_response: bool,
|
|
790
|
+
) -> list[dict[str, Any]] | dict[str, Any]:
|
|
791
|
+
"""Call a service for a non-admin token, in ``call_service``'s return shape.
|
|
792
|
+
|
|
793
|
+
Over REST an admin-only service answers a non-admin with a 401 that
|
|
794
|
+
``http.ban`` counts; over WebSocket the refusal is only an error
|
|
795
|
+
(#2546). WebSocket reports no changed states, so that list is empty.
|
|
796
|
+
"""
|
|
797
|
+
reply = await self.send_websocket_message(
|
|
798
|
+
{
|
|
799
|
+
"type": "call_service",
|
|
800
|
+
"domain": domain,
|
|
801
|
+
"service": service,
|
|
802
|
+
"service_data": payload,
|
|
803
|
+
"return_response": return_response,
|
|
804
|
+
}
|
|
805
|
+
)
|
|
806
|
+
if not reply.get("success"):
|
|
807
|
+
error = str(reply.get("error", "Service call failed"))
|
|
808
|
+
if error.removeprefix("Command failed: ") == "Unauthorized":
|
|
809
|
+
raise HomeAssistantAdminRequiredError(
|
|
810
|
+
f"Service {domain}.{service} is admin-only in Home Assistant "
|
|
811
|
+
"and this token's user is not an administrator"
|
|
812
|
+
)
|
|
813
|
+
raise HomeAssistantAPIError(
|
|
814
|
+
f"API error: 400 - {error}",
|
|
815
|
+
status_code=400,
|
|
816
|
+
response_data={"message": error},
|
|
817
|
+
)
|
|
818
|
+
if return_response:
|
|
819
|
+
result = reply.get("result") or {}
|
|
820
|
+
return {"changed_states": [], "service_response": result.get("response")}
|
|
821
|
+
return []
|
|
822
|
+
|
|
609
823
|
async def get_services(self) -> dict[str, Any]:
|
|
610
824
|
"""Get all available services."""
|
|
611
825
|
logger.debug("Fetching available services")
|
|
@@ -278,11 +278,11 @@ async def maybe_refresh_hacs_after_update() -> None:
|
|
|
278
278
|
async def hacs_refresh_lifespan(_server: Any) -> AsyncIterator[dict[str, Any]]:
|
|
279
279
|
"""Schedule the startup nudge for the lifetime of any server run.
|
|
280
280
|
|
|
281
|
-
|
|
282
|
-
stdio, the HTTP CLI entry points, and the
|
|
283
|
-
calls ``mcp.run()`` directly and never passes through
|
|
284
|
-
``_run_with_shutdown`` (the wiring this replaces; the
|
|
285
|
-
found live, not by CI, because the e2e suites launch via the CLI
|
|
281
|
+
Entered by ``server_lifespan``, the FastMCP ``lifespan``, so it runs on
|
|
282
|
+
EVERY launcher — stdio, the HTTP CLI entry points, and the app's
|
|
283
|
+
``start.py``, which calls ``mcp.run()`` directly and never passes through
|
|
284
|
+
``__main__``'s ``_run_with_shutdown`` (the wiring this replaces; the app
|
|
285
|
+
gap was found live, not by CI, because the e2e suites launch via the CLI
|
|
286
286
|
entry points).
|
|
287
287
|
"""
|
|
288
288
|
task = asyncio.create_task(maybe_refresh_hacs_after_update())
|
|
@@ -14,6 +14,7 @@ from typing import TYPE_CHECKING, Any
|
|
|
14
14
|
|
|
15
15
|
import anyio
|
|
16
16
|
|
|
17
|
+
from ..client.rest_client import HomeAssistantAdminRequiredError
|
|
17
18
|
from .approval_queue import PendingApproval
|
|
18
19
|
from .model import Rule
|
|
19
20
|
|
|
@@ -184,6 +185,13 @@ async def emit_approval_result(
|
|
|
184
185
|
token,
|
|
185
186
|
EMIT_TIMEOUT_SECONDS,
|
|
186
187
|
)
|
|
188
|
+
except HomeAssistantAdminRequiredError:
|
|
189
|
+
logger.warning(
|
|
190
|
+
"policy events: %s for token=%s not fired: events need an "
|
|
191
|
+
"administrator's token; the decision itself is unaffected",
|
|
192
|
+
APPROVAL_RESULT_EVENT,
|
|
193
|
+
token,
|
|
194
|
+
)
|
|
187
195
|
except Exception:
|
|
188
196
|
logger.warning(
|
|
189
197
|
"policy events: failed to fire %s for token=%s; the decision "
|
|
@@ -227,6 +235,14 @@ async def emit_approval_requested(
|
|
|
227
235
|
entry.tool_name,
|
|
228
236
|
EMIT_TIMEOUT_SECONDS,
|
|
229
237
|
)
|
|
238
|
+
except HomeAssistantAdminRequiredError:
|
|
239
|
+
logger.warning(
|
|
240
|
+
"policy events: %s for tool=%s not fired: events need an "
|
|
241
|
+
"administrator's token; the pending request is still queued and "
|
|
242
|
+
"visible in the settings UI",
|
|
243
|
+
APPROVAL_REQUESTED_EVENT,
|
|
244
|
+
entry.tool_name,
|
|
245
|
+
)
|
|
230
246
|
except Exception:
|
|
231
247
|
# Broad by intent: every failure mode here has the same handling —
|
|
232
248
|
# log it and leave the gate working. Narrowing would turn an
|
|
@@ -20,8 +20,8 @@ from ha_mcp._vendor.mcp.types import Icon
|
|
|
20
20
|
|
|
21
21
|
from .config import _PACKAGE_VERSION, get_global_settings
|
|
22
22
|
from .errors import ErrorCode, create_error_response
|
|
23
|
-
from .hacs_auto_refresh import hacs_refresh_lifespan
|
|
24
23
|
from .http_transport import HttpTransportFastMCP as FastMCP
|
|
24
|
+
from .server_lifespan import server_lifespan
|
|
25
25
|
from .tools.helpers import raise_tool_error
|
|
26
26
|
from .transforms import DEFAULT_PINNED_TOOLS
|
|
27
27
|
|
|
@@ -144,7 +144,7 @@ class HomeAssistantSmartMCPServer:
|
|
|
144
144
|
version=server_version,
|
|
145
145
|
icons=SERVER_ICONS,
|
|
146
146
|
instructions=instructions,
|
|
147
|
-
lifespan=
|
|
147
|
+
lifespan=server_lifespan,
|
|
148
148
|
)
|
|
149
149
|
|
|
150
150
|
# Register all tools and expert prompts
|
|
@@ -1441,10 +1441,14 @@ class HomeAssistantSmartMCPServer:
|
|
|
1441
1441
|
url: str | None
|
|
1442
1442
|
token_value: str | None
|
|
1443
1443
|
verify_ssl: bool | None
|
|
1444
|
+
known_is_admin: bool | None
|
|
1445
|
+
admin_route_refused: bool
|
|
1444
1446
|
try:
|
|
1445
1447
|
url = client.base_url
|
|
1446
1448
|
token_value = client.token
|
|
1447
1449
|
verify_ssl = client.verify_ssl
|
|
1450
|
+
known_is_admin = client.known_is_admin
|
|
1451
|
+
admin_route_refused = client.admin_route_refused is True
|
|
1448
1452
|
except Exception:
|
|
1449
1453
|
logger.debug(
|
|
1450
1454
|
"policy decisions: no credentials for the result event; "
|
|
@@ -1457,7 +1461,11 @@ class HomeAssistantSmartMCPServer:
|
|
|
1457
1461
|
# ever reclaim. A wrong PIN retried by a chatty automation would
|
|
1458
1462
|
# otherwise open one per attempt.
|
|
1459
1463
|
async with HomeAssistantClient(
|
|
1460
|
-
url,
|
|
1464
|
+
url,
|
|
1465
|
+
token_value,
|
|
1466
|
+
verify_ssl=verify_ssl,
|
|
1467
|
+
is_admin=known_is_admin,
|
|
1468
|
+
admin_route_refused=admin_route_refused,
|
|
1461
1469
|
) as result_client:
|
|
1462
1470
|
await emit_approval_result(
|
|
1463
1471
|
result_client,
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"""FastMCP lifespan shared by every launcher: background startup passes."""
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
import logging
|
|
5
|
+
from collections.abc import AsyncIterator
|
|
6
|
+
from contextlib import asynccontextmanager, suppress
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
from ._version import is_embedded
|
|
10
|
+
from .client.rest_client import HomeAssistantClient
|
|
11
|
+
from .config import OAUTH_MODE_TOKEN, get_global_settings
|
|
12
|
+
from .hacs_auto_refresh import hacs_refresh_lifespan
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
async def warn_if_non_admin_token() -> None:
|
|
18
|
+
"""Ask Home Assistant about the configured token so a non-admin one is logged at startup (#2546)."""
|
|
19
|
+
try:
|
|
20
|
+
# The embedded server provisions its own admin token; OAuth mode has
|
|
21
|
+
# no server-level token to ask about.
|
|
22
|
+
settings = get_global_settings()
|
|
23
|
+
if is_embedded() or settings.homeassistant_token == OAUTH_MODE_TOKEN:
|
|
24
|
+
return
|
|
25
|
+
async with HomeAssistantClient() as client:
|
|
26
|
+
if await client.token_is_admin() is None:
|
|
27
|
+
logger.info(
|
|
28
|
+
"Could not ask Home Assistant whether the token is an "
|
|
29
|
+
"administrator's; admin-only requests go out one at a time "
|
|
30
|
+
"until the first one answers it"
|
|
31
|
+
)
|
|
32
|
+
except asyncio.CancelledError:
|
|
33
|
+
raise
|
|
34
|
+
except Exception:
|
|
35
|
+
logger.warning("Startup admin-token check failed", exc_info=True)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@asynccontextmanager
|
|
39
|
+
async def server_lifespan(server: Any) -> AsyncIterator[dict[str, Any]]:
|
|
40
|
+
"""Run the HACS startup nudge and the admin-token check for the server's lifetime.
|
|
41
|
+
|
|
42
|
+
Attached as the FastMCP ``lifespan`` so it runs on every launcher, including
|
|
43
|
+
the app's ``start.py``, which calls ``mcp.run()`` directly.
|
|
44
|
+
"""
|
|
45
|
+
async with hacs_refresh_lifespan(server) as state:
|
|
46
|
+
task = asyncio.create_task(warn_if_non_admin_token())
|
|
47
|
+
try:
|
|
48
|
+
yield state
|
|
49
|
+
finally:
|
|
50
|
+
task.cancel()
|
|
51
|
+
with suppress(asyncio.CancelledError):
|
|
52
|
+
await task
|
|
@@ -16,6 +16,8 @@ from ha_mcp._vendor.fastmcp import Context
|
|
|
16
16
|
from ha_mcp._vendor.fastmcp.exceptions import ToolError
|
|
17
17
|
|
|
18
18
|
from ..client.rest_client import (
|
|
19
|
+
NON_ADMIN_TOKEN_WARNING,
|
|
20
|
+
HomeAssistantAdminRequiredError,
|
|
19
21
|
HomeAssistantAPIError,
|
|
20
22
|
HomeAssistantAuthError,
|
|
21
23
|
HomeAssistantCommandError,
|
|
@@ -322,6 +324,17 @@ def _classify_exception(
|
|
|
322
324
|
result = create_connection_error(
|
|
323
325
|
error_msg, timeout="timeout" in error_str, context=context
|
|
324
326
|
)
|
|
327
|
+
case HomeAssistantAdminRequiredError():
|
|
328
|
+
result = create_error_response(
|
|
329
|
+
ErrorCode.AUTH_INSUFFICIENT_PERMISSIONS,
|
|
330
|
+
error_msg,
|
|
331
|
+
suggestions=[
|
|
332
|
+
"Use a long-lived access token from an administrator's profile",
|
|
333
|
+
"Or use the in-process server, which provisions its own admin token",
|
|
334
|
+
],
|
|
335
|
+
context=context,
|
|
336
|
+
)
|
|
337
|
+
result["warnings"] = [NON_ADMIN_TOKEN_WARNING]
|
|
325
338
|
case HomeAssistantAuthError():
|
|
326
339
|
result = create_auth_error(
|
|
327
340
|
error_msg, expired="expired" in error_str, context=context
|
{ha_mcp_dev-8.5.0.dev2770 → ha_mcp_dev-8.5.0.dev2773}/src/ha_mcp/tools/smart_search/_deep.py
RENAMED
|
@@ -8,7 +8,7 @@ from typing import Any
|
|
|
8
8
|
from ha_mcp._vendor.fastmcp import Context
|
|
9
9
|
from ha_mcp._vendor.fastmcp.exceptions import ToolError
|
|
10
10
|
|
|
11
|
-
from ...client.rest_client import HomeAssistantAPIError
|
|
11
|
+
from ...client.rest_client import NON_ADMIN_TOKEN_WARNING, HomeAssistantAPIError
|
|
12
12
|
from ...errors import get_error_code, get_error_message
|
|
13
13
|
from ..component_api import component_supports, get_component_caps
|
|
14
14
|
from ..config_entry_flow import FLOW_HELPER_TYPES
|
|
@@ -1347,6 +1347,15 @@ class DeepSearchMixin(SceneSearchMixin):
|
|
|
1347
1347
|
graph_surfaces_skipped=graph_surfaces_skipped,
|
|
1348
1348
|
graph_unavailable=graph_unavailable,
|
|
1349
1349
|
)
|
|
1350
|
+
# Keyed on the client, not the failure sample, which names only the
|
|
1351
|
+
# first error.
|
|
1352
|
+
if (
|
|
1353
|
+
automation_failed
|
|
1354
|
+
or script_failed
|
|
1355
|
+
or scene_stats.get("failed")
|
|
1356
|
+
or helper_failed
|
|
1357
|
+
) and self.client.admin_route_refused is True:
|
|
1358
|
+
response.setdefault("warnings", []).append(NON_ADMIN_TOKEN_WARNING)
|
|
1350
1359
|
return response
|
|
1351
1360
|
|
|
1352
1361
|
@staticmethod
|
|
@@ -35,6 +35,10 @@ from pydantic import Field
|
|
|
35
35
|
from ha_mcp._vendor.fastmcp.exceptions import ToolError
|
|
36
36
|
from ha_mcp._vendor.fastmcp.server.context import Context
|
|
37
37
|
|
|
38
|
+
from ..client.rest_client import (
|
|
39
|
+
NON_ADMIN_TOKEN_WARNING,
|
|
40
|
+
HomeAssistantAdminRequiredError,
|
|
41
|
+
)
|
|
38
42
|
from ..config import get_global_settings
|
|
39
43
|
from ..errors import ErrorCode, create_error_response
|
|
40
44
|
from .helpers import log_tool_usage, raise_tool_error
|
|
@@ -757,11 +761,13 @@ class _SandboxBridge:
|
|
|
757
761
|
logger.warning("api_get rejected endpoint %r: %s", endpoint, exc)
|
|
758
762
|
return {"error": str(exc)}
|
|
759
763
|
try:
|
|
760
|
-
response = await self.client.
|
|
764
|
+
response = await self.client.guarded_request("GET", normalized)
|
|
761
765
|
try:
|
|
762
766
|
return response.json()
|
|
763
767
|
except json.JSONDecodeError:
|
|
764
768
|
return response.text
|
|
769
|
+
except HomeAssistantAdminRequiredError as exc:
|
|
770
|
+
return {"error": str(exc), "warnings": [NON_ADMIN_TOKEN_WARNING]}
|
|
765
771
|
except Exception as exc:
|
|
766
772
|
logger.warning("api_get(%r) failed", endpoint, exc_info=True)
|
|
767
773
|
return {"error": str(exc)[:200]}
|
|
@@ -804,13 +810,15 @@ class _SandboxBridge:
|
|
|
804
810
|
post_kwargs: dict[str, Any] = {}
|
|
805
811
|
if data is not None:
|
|
806
812
|
post_kwargs["json"] = data
|
|
807
|
-
response = await self.client.
|
|
813
|
+
response = await self.client.guarded_request(
|
|
808
814
|
"POST", normalized, **post_kwargs
|
|
809
815
|
)
|
|
810
816
|
try:
|
|
811
817
|
return response.json()
|
|
812
818
|
except json.JSONDecodeError:
|
|
813
819
|
return response.text
|
|
820
|
+
except HomeAssistantAdminRequiredError as exc:
|
|
821
|
+
return {"error": str(exc), "warnings": [NON_ADMIN_TOKEN_WARNING]}
|
|
814
822
|
except Exception as exc:
|
|
815
823
|
logger.warning("api_post(%r) failed", endpoint, exc_info=True)
|
|
816
824
|
return {"error": str(exc)[:200]}
|