ha-mcp-dev 8.3.0.dev2422__tar.gz → 8.3.0.dev2427__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.
Files changed (280) hide show
  1. {ha_mcp_dev-8.3.0.dev2422/src/ha_mcp_dev.egg-info → ha_mcp_dev-8.3.0.dev2427}/PKG-INFO +1 -1
  2. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/pyproject.toml +1 -1
  3. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/__main__.py +2 -69
  4. ha_mcp_dev-8.3.0.dev2427/src/ha_mcp/log_filters.py +207 -0
  5. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/tools_addons.py +20 -7
  6. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427/src/ha_mcp_dev.egg-info}/PKG-INFO +1 -1
  7. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp_dev.egg-info/SOURCES.txt +1 -0
  8. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/LICENSE +0 -0
  9. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/MANIFEST.in +0 -0
  10. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/README.md +0 -0
  11. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/setup.cfg +0 -0
  12. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/__init__.py +0 -0
  13. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_pypi_marker +0 -0
  14. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_rich_compat.py +0 -0
  15. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/__init__.py +0 -0
  16. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/requirements.txt +0 -0
  17. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/LICENSE +0 -0
  18. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/MANIFEST.sha256 +0 -0
  19. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/VENDORED +0 -0
  20. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/__init__.py +0 -0
  21. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/__main__.py +0 -0
  22. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/asyncio/__init__.py +0 -0
  23. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/asyncio/client.py +0 -0
  24. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/asyncio/connection.py +0 -0
  25. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/asyncio/messages.py +0 -0
  26. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/asyncio/router.py +0 -0
  27. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/asyncio/server.py +0 -0
  28. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/auth.py +0 -0
  29. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/cli.py +0 -0
  30. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/client.py +0 -0
  31. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/connection.py +0 -0
  32. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/datastructures.py +0 -0
  33. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/exceptions.py +0 -0
  34. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/extensions/__init__.py +0 -0
  35. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/extensions/base.py +0 -0
  36. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/extensions/permessage_deflate.py +0 -0
  37. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/frames.py +0 -0
  38. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/headers.py +0 -0
  39. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/http11.py +0 -0
  40. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/imports.py +0 -0
  41. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/legacy/__init__.py +0 -0
  42. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/legacy/auth.py +0 -0
  43. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/legacy/client.py +0 -0
  44. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/legacy/exceptions.py +0 -0
  45. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/legacy/framing.py +0 -0
  46. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/legacy/handshake.py +0 -0
  47. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/legacy/http.py +0 -0
  48. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/legacy/protocol.py +0 -0
  49. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/legacy/server.py +0 -0
  50. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/protocol.py +0 -0
  51. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/proxy.py +0 -0
  52. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/py.typed +0 -0
  53. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/server.py +0 -0
  54. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/streams.py +0 -0
  55. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/sync/__init__.py +0 -0
  56. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/sync/client.py +0 -0
  57. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/sync/connection.py +0 -0
  58. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/sync/messages.py +0 -0
  59. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/sync/router.py +0 -0
  60. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/sync/server.py +0 -0
  61. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/sync/utils.py +0 -0
  62. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/trio/__init__.py +0 -0
  63. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/trio/client.py +0 -0
  64. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/trio/connection.py +0 -0
  65. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/trio/messages.py +0 -0
  66. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/trio/router.py +0 -0
  67. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/trio/server.py +0 -0
  68. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/trio/utils.py +0 -0
  69. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/typing.py +0 -0
  70. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/uri.py +0 -0
  71. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/utils.py +0 -0
  72. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_vendor/websockets/version.py +0 -0
  73. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/_version.py +0 -0
  74. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/auth/__init__.py +0 -0
  75. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/auth/consent_form.py +0 -0
  76. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/auth/oidc_compat.py +0 -0
  77. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/auth/provider.py +0 -0
  78. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/backup_manager.py +0 -0
  79. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/browser_landing.py +0 -0
  80. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/client/__init__.py +0 -0
  81. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/client/rest_client.py +0 -0
  82. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/client/supervisor_client.py +0 -0
  83. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/client/websocket_client.py +0 -0
  84. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/client/websocket_listener.py +0 -0
  85. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/config.py +0 -0
  86. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/dashboard_screenshot/__init__.py +0 -0
  87. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/dashboard_screenshot/capture.py +0 -0
  88. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/dashboard_screenshot/content.py +0 -0
  89. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/dashboard_screenshot/paths.py +0 -0
  90. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/dashboard_screenshot/provision.py +0 -0
  91. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/dashboard_screenshot/theme_guard.py +0 -0
  92. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/errors.py +0 -0
  93. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/hacs_auto_refresh.py +0 -0
  94. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/llm_exposure.py +0 -0
  95. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/policy/__init__.py +0 -0
  96. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/policy/approval_queue.py +0 -0
  97. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/policy/editing.py +0 -0
  98. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/policy/evaluator.py +0 -0
  99. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/policy/handlers.py +0 -0
  100. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/policy/middleware.py +0 -0
  101. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/policy/model.py +0 -0
  102. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/policy/persistence.py +0 -0
  103. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/policy/value_sources.py +0 -0
  104. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/py.typed +0 -0
  105. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/read_only.py +0 -0
  106. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/redaction.py +0 -0
  107. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/renamed_tools.py +0 -0
  108. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/resources/skills-vendor/.claude/settings.json +0 -0
  109. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/resources/skills-vendor/.claude-plugin/marketplace.json +0 -0
  110. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/resources/skills-vendor/.claude-plugin/plugin.json +0 -0
  111. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/resources/skills-vendor/.github/ISSUE_TEMPLATE/skill-rca.md +0 -0
  112. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/resources/skills-vendor/.github/pull_request_template.md +0 -0
  113. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/resources/skills-vendor/AGENTS.md +0 -0
  114. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/resources/skills-vendor/CLAUDE.md +0 -0
  115. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/resources/skills-vendor/CONTRIBUTING.md +0 -0
  116. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/resources/skills-vendor/LICENSE +0 -0
  117. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/resources/skills-vendor/README.md +0 -0
  118. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/SKILL.md +0 -0
  119. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/evals/evals.json +0 -0
  120. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/appdaemon.md +0 -0
  121. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/automation-patterns.md +0 -0
  122. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/blueprint-guide.md +0 -0
  123. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-cards.md +0 -0
  124. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-guide.md +0 -0
  125. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/device-control.md +0 -0
  126. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/domain-docs.md +0 -0
  127. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/examples.yaml +0 -0
  128. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/helper-selection.md +0 -0
  129. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/safe-refactoring.md +0 -0
  130. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/scenes.md +0 -0
  131. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/template-guidelines.md +0 -0
  132. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/yaml-only-integrations.md +0 -0
  133. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/server.py +0 -0
  134. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/settings_ui/__init__.py +0 -0
  135. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/settings_ui/_handlers_advanced.py +0 -0
  136. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/settings_ui/_handlers_backups.py +0 -0
  137. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/settings_ui/_handlers_fs.py +0 -0
  138. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/settings_ui/_handlers_server.py +0 -0
  139. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/settings_ui/_handlers_theme.py +0 -0
  140. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/settings_ui/_handlers_tools.py +0 -0
  141. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/settings_ui/_i18n.py +0 -0
  142. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/settings_ui/_persistence.py +0 -0
  143. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/settings_ui/_supervisor.py +0 -0
  144. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/settings_ui/_theme.py +0 -0
  145. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/settings_ui/_tools_meta.py +0 -0
  146. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/settings_ui/locales/README.md +0 -0
  147. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/settings_ui/locales/cs.json +0 -0
  148. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/settings_ui/locales/de.json +0 -0
  149. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/settings_ui/locales/en.json +0 -0
  150. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/settings_ui/locales/eo.json +0 -0
  151. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/settings_ui/locales/es.json +0 -0
  152. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/settings_ui/locales/fr.json +0 -0
  153. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/settings_ui/locales/it.json +0 -0
  154. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/settings_ui/locales/ko.json +0 -0
  155. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/settings_ui/locales/nl.json +0 -0
  156. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/settings_ui/locales/pl.json +0 -0
  157. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/settings_ui/locales/ru.json +0 -0
  158. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/settings_ui/locales/sv.json +0 -0
  159. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/settings_ui/locales/zh-Hans.json +0 -0
  160. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/settings_ui/settings.css +0 -0
  161. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/settings_ui/settings.html +0 -0
  162. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/settings_ui/settings.js +0 -0
  163. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/smoke_test.py +0 -0
  164. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/stdio_settings_sidecar.py +0 -0
  165. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/strict_bps.py +0 -0
  166. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/__init__.py +0 -0
  167. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/auto_backup.py +0 -0
  168. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/backup.py +0 -0
  169. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/best_practice_checker.py +0 -0
  170. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/best_practice_result.py +0 -0
  171. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/best_practice_variables.py +0 -0
  172. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/bulk_selector.py +0 -0
  173. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/component_api.py +0 -0
  174. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/component_config_entries.py +0 -0
  175. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/component_config_reads.py +0 -0
  176. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/component_devices.py +0 -0
  177. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/component_registries.py +0 -0
  178. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/component_registry_lookup.py +0 -0
  179. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/config_entry_flow.py +0 -0
  180. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/config_entry_flow_form.py +0 -0
  181. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/config_entry_flow_menu.py +0 -0
  182. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/config_entry_flow_walker.py +0 -0
  183. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/config_entry_identity.py +0 -0
  184. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/config_entry_reconfigure.py +0 -0
  185. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/config_entry_reload_watch.py +0 -0
  186. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/device_control.py +0 -0
  187. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/error_log_parsing.py +0 -0
  188. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/hacs_registration.py +0 -0
  189. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/helpers.py +0 -0
  190. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/integration_reconfigure.py +0 -0
  191. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/radio/__init__.py +0 -0
  192. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/radio/base.py +0 -0
  193. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/radio/matter.py +0 -0
  194. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/radio/thread.py +0 -0
  195. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/radio/zigbee.py +0 -0
  196. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/radio/zwave.py +0 -0
  197. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/reference_validator.py +0 -0
  198. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/registry.py +0 -0
  199. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/renamed_tool_middleware.py +0 -0
  200. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/smart_search/__init__.py +0 -0
  201. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/smart_search/_base.py +0 -0
  202. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/smart_search/_config.py +0 -0
  203. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/smart_search/_deep.py +0 -0
  204. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/smart_search/_entities.py +0 -0
  205. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/smart_search/_fetch.py +0 -0
  206. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/smart_search/_overview.py +0 -0
  207. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/smart_search/_scenes.py +0 -0
  208. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/smart_search/_scoring.py +0 -0
  209. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/tool_search_hint_middleware.py +0 -0
  210. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/tools_areas.py +0 -0
  211. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/tools_assist_pipeline.py +0 -0
  212. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/tools_blueprints.py +0 -0
  213. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/tools_bug_report.py +0 -0
  214. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/tools_calendar.py +0 -0
  215. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/tools_camera.py +0 -0
  216. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/tools_categories.py +0 -0
  217. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/tools_code.py +0 -0
  218. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/tools_config_automations.py +0 -0
  219. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/tools_config_dashboards.py +0 -0
  220. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/tools_config_helpers.py +0 -0
  221. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/tools_config_scenes.py +0 -0
  222. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/tools_config_scripts.py +0 -0
  223. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/tools_dashboard_screenshot.py +0 -0
  224. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/tools_dev.py +0 -0
  225. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/tools_energy.py +0 -0
  226. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/tools_entities.py +0 -0
  227. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/tools_filesystem.py +0 -0
  228. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/tools_groups.py +0 -0
  229. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/tools_hacs.py +0 -0
  230. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/tools_history.py +0 -0
  231. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/tools_integrations.py +0 -0
  232. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/tools_labels.py +0 -0
  233. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/tools_radio.py +0 -0
  234. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/tools_registry.py +0 -0
  235. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/tools_resources.py +0 -0
  236. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/tools_search.py +0 -0
  237. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/tools_security_policy.py +0 -0
  238. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/tools_service.py +0 -0
  239. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/tools_services.py +0 -0
  240. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/tools_system.py +0 -0
  241. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/tools_themes.py +0 -0
  242. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/tools_todo.py +0 -0
  243. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/tools_traces.py +0 -0
  244. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/tools_updates.py +0 -0
  245. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/tools_utility.py +0 -0
  246. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/tools_voice_assistant.py +0 -0
  247. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/tools_yaml_config.py +0 -0
  248. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/tools_yaml_read.py +0 -0
  249. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/tools_zones.py +0 -0
  250. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/util_helpers.py +0 -0
  251. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/tools/validation_middleware.py +0 -0
  252. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/transforms/__init__.py +0 -0
  253. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/transforms/categorized_search.py +0 -0
  254. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/transforms/lite_docstrings.py +0 -0
  255. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/transport_security.py +0 -0
  256. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/update_check.py +0 -0
  257. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/utils/__init__.py +0 -0
  258. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/utils/config_hash.py +0 -0
  259. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/utils/config_write_lock.py +0 -0
  260. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/utils/data_paths.py +0 -0
  261. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/utils/domain_handlers.py +0 -0
  262. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/utils/entity_membership.py +0 -0
  263. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/utils/fuzzy_search.py +0 -0
  264. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/utils/kill_signal_diagnostics.py +0 -0
  265. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/utils/operation_manager.py +0 -0
  266. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/utils/python_sandbox.py +0 -0
  267. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/utils/skill_loader.py +0 -0
  268. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/utils/usage_logger.py +0 -0
  269. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/visibility/__init__.py +0 -0
  270. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/visibility/enforcement.py +0 -0
  271. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/visibility/model.py +0 -0
  272. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/visibility/persistence.py +0 -0
  273. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp/visibility/resolver.py +0 -0
  274. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp_dev.egg-info/dependency_links.txt +0 -0
  275. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp_dev.egg-info/entry_points.txt +0 -0
  276. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp_dev.egg-info/requires.txt +0 -0
  277. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/src/ha_mcp_dev.egg-info/top_level.txt +0 -0
  278. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/tests/__init__.py +0 -0
  279. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/tests/test_constants.py +0 -0
  280. {ha_mcp_dev-8.3.0.dev2422 → ha_mcp_dev-8.3.0.dev2427}/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.3.0.dev2422
3
+ Version: 8.3.0.dev2427
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
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "ha-mcp-dev"
7
- version = "8.3.0.dev2422"
7
+ version = "8.3.0.dev2427"
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
@@ -33,15 +33,13 @@ import threading # noqa: E402
33
33
  from collections.abc import Coroutine # noqa: E402
34
34
  from typing import TYPE_CHECKING, Any, NoReturn # noqa: E402
35
35
 
36
- from fastmcp.exceptions import ToolError # noqa: E402
37
- from pydantic import ValidationError as PydanticValidationError # noqa: E402
38
-
39
36
  from ha_mcp.browser_landing import ( # noqa: E402
40
37
  register_browser_landing as _register_landing_route,
41
38
  )
42
39
  from ha_mcp.browser_landing import ( # noqa: E402
43
40
  register_healthz as _register_healthz_route,
44
41
  )
42
+ from ha_mcp.log_filters import install_sdk_log_filters # noqa: E402
45
43
 
46
44
  if TYPE_CHECKING:
47
45
  from fastmcp import FastMCP
@@ -384,68 +382,6 @@ mcp = _DeferredMCP()
384
382
  _LOG_DATE_FORMAT = "%Y-%m-%d %H:%M:%S"
385
383
 
386
384
 
387
- class StatelessSessionLogFilter(logging.Filter):
388
- """Suppress the routine 'Terminating session: None' log from the MCP SDK.
389
-
390
- In stateless HTTP mode every request creates and tears down a temporary
391
- session whose id is ``None``, so the SDK emits an INFO
392
- ``Terminating session: None`` (mcp/server/streamable_http.py) on *every*
393
- request. The line is routine but looks alarming and has repeatedly
394
- confused users into thinking the connection is broken.
395
-
396
- Returning ``False`` drops the record at this logger before it reaches any
397
- handler. (Merely downgrading the level to DEBUG did not work: the level
398
- gate is applied before the filter runs, so the record was already admitted
399
- and still emitted -- just relabelled.) Real session terminations carry an
400
- actual id and are not matched, so they still log.
401
-
402
- # TODO: remove when modelcontextprotocol/python-sdk#2329 is resolved
403
- """
404
-
405
- def filter(self, record: logging.LogRecord) -> bool:
406
- if record.name != "mcp.server.streamable_http":
407
- return True
408
- try:
409
- message = record.getMessage()
410
- except (ValueError, TypeError):
411
- # A malformed %-format record on this logger is not our target, and
412
- # a filter must not raise: filters run in Logger.handle() with no
413
- # exception handling, so a raise would crash the logging call.
414
- return True
415
- # Drop the stateless teardown noise; keep everything else.
416
- return "Terminating session: None" not in message
417
-
418
-
419
- class ToolValidationLogFilter(logging.Filter):
420
- """Demote fastmcp tool-failure tracebacks to single-line warnings.
421
-
422
- Pydantic ValidationError and tool-raised ToolError aren't server bugs,
423
- so the traceback through fastmcp/pydantic internals is just noise. The
424
- structured error detail is preserved in the WARNING message; stack is
425
- intentionally dropped because these are user-input errors, not bugs.
426
- """
427
-
428
- def filter(self, record: logging.LogRecord) -> bool:
429
- if record.name != "fastmcp.server.server" or not record.exc_info:
430
- return True
431
-
432
- msg = record.getMessage()
433
- err = record.exc_info[1]
434
- if "Error validating tool" in msg and isinstance(err, PydanticValidationError):
435
- record.msg = f"{msg}: {err.errors(include_url=False)}"
436
- elif "Error calling tool" in msg and isinstance(err, ToolError):
437
- record.msg = f"{msg}: {err}"
438
- else:
439
- return True
440
-
441
- record.args = ()
442
- record.levelno = logging.WARNING
443
- record.levelname = "WARNING"
444
- record.exc_info = None
445
- record.exc_text = None
446
- return True
447
-
448
-
449
385
  class ProbeAccessLogFilter(logging.Filter):
450
386
  """Drop benign, non-MCP HTTP probe noise from the uvicorn access log.
451
387
 
@@ -528,10 +464,7 @@ def _setup_logging(log_level_str: str, force: bool = True) -> None:
528
464
  # disabled. Prevent that NOTSET namespace from inheriting our root handler.
529
465
  fastmcp_logger.setLevel(logging.CRITICAL + 1)
530
466
 
531
- logging.getLogger("mcp.server.streamable_http").addFilter(
532
- StatelessSessionLogFilter()
533
- )
534
- logging.getLogger("fastmcp.server.server").addFilter(ToolValidationLogFilter())
467
+ install_sdk_log_filters()
535
468
 
536
469
 
537
470
  def _log_startup_version() -> None:
@@ -0,0 +1,207 @@
1
+ """MCP SDK / fastmcp log-noise filters shared across every HTTP launcher.
2
+
3
+ Extracted from :mod:`ha_mcp.__main__` for the same reason as
4
+ :mod:`ha_mcp.browser_landing`: the in-process server (the ``ha_mcp_tools``
5
+ custom-component worker thread) must never import ``ha_mcp.__main__``, since
6
+ that module runs process-global side effects at import time
7
+ (``truststore.inject_into_ssl()``, signal handlers, ``asyncio.run``). These
8
+ filters only call ``logging.Logger.addFilter`` on specific named loggers --
9
+ no ``basicConfig``, no handler or root-logger changes -- so
10
+ ``install_sdk_log_filters()`` is safe to call from any launcher, including
11
+ one that must leave Home Assistant's own logging configuration untouched
12
+ (see the ``log_config=None`` comment in ``embedded_server.py``).
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ import logging
18
+
19
+ import anyio
20
+ from fastmcp.exceptions import ToolError
21
+ from pydantic import ValidationError as PydanticValidationError
22
+
23
+
24
+ class StatelessSessionLogFilter(logging.Filter):
25
+ """Suppress the routine 'Terminating session: None' log from the MCP SDK.
26
+
27
+ In stateless HTTP mode every request creates and tears down a temporary
28
+ session whose id is ``None``, so the SDK emits an INFO
29
+ ``Terminating session: None`` (mcp/server/streamable_http.py) on *every*
30
+ request. The line is routine but looks alarming and has repeatedly
31
+ confused users into thinking the connection is broken.
32
+
33
+ Returning ``False`` drops the record at this logger before it reaches any
34
+ handler. (Merely downgrading the level to DEBUG did not work: the level
35
+ gate is applied before the filter runs, so the record was already admitted
36
+ and still emitted -- just relabelled.) Real session terminations carry an
37
+ actual id and are not matched, so they still log.
38
+
39
+ # TODO: remove when modelcontextprotocol/python-sdk#2329 is resolved
40
+ """
41
+
42
+ def filter(self, record: logging.LogRecord) -> bool:
43
+ """Drop the routine stateless-teardown record; pass everything else."""
44
+ if record.name != "mcp.server.streamable_http":
45
+ return True
46
+ try:
47
+ message = record.getMessage()
48
+ except (ValueError, TypeError):
49
+ # A malformed %-format record on this logger is not our target, and
50
+ # a filter must not raise: filters run in Logger.handle() with no
51
+ # exception handling, so a raise would crash the logging call.
52
+ return True
53
+ # Drop the stateless teardown noise; keep everything else.
54
+ return "Terminating session: None" not in message
55
+
56
+
57
+ class ToolValidationLogFilter(logging.Filter):
58
+ """Demote fastmcp tool-failure tracebacks to single-line warnings.
59
+
60
+ Pydantic ValidationError and tool-raised ToolError aren't server bugs,
61
+ so the traceback through fastmcp/pydantic internals is just noise. The
62
+ structured error detail is preserved in the WARNING message; stack is
63
+ intentionally dropped because these are user-input errors, not bugs.
64
+ """
65
+
66
+ def filter(self, record: logging.LogRecord) -> bool:
67
+ """Demote a known-benign validation/tool-error record to WARNING."""
68
+ if record.name != "fastmcp.server.server" or not record.exc_info:
69
+ return True
70
+
71
+ msg = record.getMessage()
72
+ err = record.exc_info[1]
73
+ if "Error validating tool" in msg and isinstance(err, PydanticValidationError):
74
+ record.msg = f"{msg}: {err.errors(include_url=False)}"
75
+ elif "Error calling tool" in msg and isinstance(err, ToolError):
76
+ record.msg = f"{msg}: {err}"
77
+ else:
78
+ return True
79
+
80
+ record.args = ()
81
+ record.levelno = logging.WARNING
82
+ record.levelname = "WARNING"
83
+ record.exc_info = None
84
+ record.exc_text = None
85
+ return True
86
+
87
+
88
+ _DISCONNECT_TEARDOWN_ERRORS = (anyio.ClosedResourceError, anyio.BrokenResourceError)
89
+
90
+
91
+ def _is_only_disconnect_teardown_errors(err: BaseException) -> bool:
92
+ """True if ``err`` is (or an ExceptionGroup wrapping only) a benign
93
+ streamable-HTTP memory-stream teardown error.
94
+
95
+ ``mcp.server.lowlevel.server.Server.run()`` dispatches each incoming
96
+ message via ``anyio.create_task_group().start_soon(...)``, so an error
97
+ raised while delivering one message's response is raised from a
98
+ task-group child -- anyio always wraps that in an ``ExceptionGroup``,
99
+ even for a single failure. The exception a "session crashed" log record
100
+ carries is therefore ``ExceptionGroup(...[<teardown error>])``, not a
101
+ bare one.
102
+
103
+ Both ``ClosedResourceError`` and ``BrokenResourceError`` -- sibling
104
+ ``Exception`` subclasses, neither a subclass of the other -- can surface
105
+ here for the same disconnect race: which one depends on which end
106
+ closed first (our end closing raises ``Closed``; the peer's
107
+ ``streamable_http`` ``terminate()`` closing first can wake a parked
108
+ sender into raising ``Broken`` instead, even though the situation is
109
+ identical from the caller's perspective). This repo already treats the
110
+ two as an equivalent pair for streamable-HTTP memory-stream teardown
111
+ elsewhere -- see ``tests/src/haos_runtime.py``'s transient-error tuple.
112
+
113
+ Recurse through (possibly nested) groups; any other leaf type means
114
+ this is not the known-benign disconnect race, so the caller should
115
+ leave the record alone.
116
+ """
117
+ if isinstance(err, _DISCONNECT_TEARDOWN_ERRORS):
118
+ return True
119
+ if isinstance(err, BaseExceptionGroup):
120
+ return bool(err.exceptions) and all(
121
+ _is_only_disconnect_teardown_errors(sub) for sub in err.exceptions
122
+ )
123
+ return False
124
+
125
+
126
+ class SessionDisconnectLogFilter(logging.Filter):
127
+ """Demote 'session crashed' tracebacks caused by an already-gone client.
128
+
129
+ Every HTTP entry point runs Streamable HTTP in stateless mode (see
130
+ ``ha_mcp.__main__._http_run_kwargs``). A tool call slow enough to outlast
131
+ the client's patience -- a busy Home Assistant instance, a
132
+ resource-contended local LLM host on the client side, or an ordinary HTTP
133
+ timeout -- lets the SDK finish serving the response and tear the
134
+ transport down while ``app.run()`` is still working; the eventual attempt
135
+ to deliver the response then writes into an already-closed memory stream
136
+ and raises ``anyio.ClosedResourceError`` or ``anyio.BrokenResourceError``
137
+ (wrapped in an ``ExceptionGroup`` -- see
138
+ ``_is_only_disconnect_teardown_errors``). The SDK already catches this
139
+ (``except Exception: logger.exception(...)`` in both the stateless and
140
+ stateful session runners of mcp/server/streamable_http_manager.py) -- it
141
+ just logs it as an alarming ERROR-level traceback. That's an expected
142
+ race in a stateless HTTP protocol (the client already gave up), not a
143
+ server bug, so demote it the same way ToolValidationLogFilter demotes
144
+ other known-benign failures. Any other exception on this logger -- an
145
+ actual crash -- is left untouched.
146
+ """
147
+
148
+ def filter(self, record: logging.LogRecord) -> bool:
149
+ """Demote a disconnect-caused 'session crashed' record to WARNING."""
150
+ if record.name != "mcp.server.streamable_http_manager" or not record.exc_info:
151
+ return True
152
+
153
+ err = record.exc_info[1]
154
+ if err is None or not _is_only_disconnect_teardown_errors(err):
155
+ return True
156
+
157
+ record.msg = (
158
+ f"{record.getMessage()}: client disconnected before response delivery"
159
+ )
160
+ record.args = ()
161
+ record.levelno = logging.WARNING
162
+ record.levelname = "WARNING"
163
+ record.exc_info = None
164
+ record.exc_text = None
165
+ return True
166
+
167
+
168
+ def _add_filter_once(logger_name: str, filter_cls: type[logging.Filter]) -> None:
169
+ """Attach one ``filter_cls`` instance to ``logger_name``, replacing any stale one.
170
+
171
+ ``install_sdk_log_filters()`` can run more than once per process: the
172
+ in-process embedded server calls it on every ``_serve()`` reload without
173
+ a process restart, and process-wide ``logging`` state (including each
174
+ named logger's filter list) persists across those reloads. Each reload
175
+ also re-imports this module from scratch (the embedded server purges
176
+ ``ha_mcp.*`` from ``sys.modules`` before reinstalling -- see
177
+ ``_purge_ha_mcp_modules``), so ``filter_cls`` is a BRAND NEW class object
178
+ each time, even though its name is unchanged. A same-``isinstance``-check
179
+ against a filter instance from a PREVIOUS generation would therefore
180
+ never match, letting filters accumulate one more stale instance per
181
+ reload forever. Match by ``(module, qualname)`` instead -- stable across
182
+ reloads of the same module path -- and drop every stale-generation match
183
+ before attaching the current one, so a logger never carries more than
184
+ one filter of a given conceptual type, and it's always this generation's.
185
+ """
186
+ logger = logging.getLogger(logger_name)
187
+ identity = (filter_cls.__module__, filter_cls.__qualname__)
188
+ logger.filters[:] = [
189
+ f
190
+ for f in logger.filters
191
+ if (type(f).__module__, type(f).__qualname__) != identity
192
+ ]
193
+ logger.addFilter(filter_cls())
194
+
195
+
196
+ def install_sdk_log_filters() -> None:
197
+ """Attach the demotion filters above to their target SDK/fastmcp loggers.
198
+
199
+ Every HTTP launcher must call this: the CLI (``ha_mcp.__main__``), the
200
+ Home Assistant app's ``start.py``, and the in-process embedded server
201
+ (``ha_mcp_tools/embedded_server.py``) each build and run their own
202
+ Streamable HTTP app, so none of them share another launcher's logging
203
+ setup. Safe to call repeatedly -- see ``_add_filter_once``.
204
+ """
205
+ _add_filter_once("mcp.server.streamable_http", StatelessSessionLogFilter)
206
+ _add_filter_once("mcp.server.streamable_http_manager", SessionDisconnectLogFilter)
207
+ _add_filter_once("fastmcp.server.server", ToolValidationLogFilter)
@@ -316,13 +316,17 @@ def _supervisor_invalid_response(
316
316
  return _supervisor_rest_failure(response, error)
317
317
 
318
318
 
319
+ def _bounded_supervisor_text(value: str) -> str:
320
+ """Return model-safe Supervisor text, marking any truncation visibly."""
321
+ if len(value) <= _MAX_RESPONSE_SIZE:
322
+ return value
323
+ prefix_size = _MAX_RESPONSE_SIZE - len(_SUPERVISOR_RESPONSE_TRUNCATION_SUFFIX)
324
+ return value[:prefix_size] + _SUPERVISOR_RESPONSE_TRUNCATION_SUFFIX
325
+
326
+
319
327
  def _bounded_supervisor_response_text(response: httpx.Response) -> str:
320
328
  """Return a model-safe Supervisor response body with visible truncation."""
321
- body = response.text.strip()
322
- if len(body) <= _MAX_RESPONSE_SIZE:
323
- return body
324
- prefix_size = _MAX_RESPONSE_SIZE - len(_SUPERVISOR_RESPONSE_TRUNCATION_SUFFIX)
325
- return body[:prefix_size] + _SUPERVISOR_RESPONSE_TRUNCATION_SUFFIX
329
+ return _bounded_supervisor_text(response.text.strip())
326
330
 
327
331
 
328
332
  def _normalize_supervisor_rest_response(
@@ -558,7 +562,12 @@ def _raise_supervisor_api_failure(
558
562
  endpoint: str,
559
563
  ) -> NoReturn:
560
564
  """Raise the structured exception represented by a non-retryable result."""
561
- error_text = str(result.get("error", f"Supervisor API call failed: {endpoint}"))
565
+ # Both transports land here, and both carry Supervisor's own text: the
566
+ # direct REST payload and the message Core relays over the WebSocket
567
+ # bridge. Bind the size once, where every failure passes.
568
+ error_text = _bounded_supervisor_text(
569
+ str(result.get("error", f"Supervisor API call failed: {endpoint}"))
570
+ )
562
571
  status_code = result.get("_status_code")
563
572
  response_data = result.get("_response_data")
564
573
  if status_code == 401:
@@ -613,7 +622,7 @@ def _supervisor_result_mapping(
613
622
  return payload
614
623
 
615
624
  verb = method.upper()
616
- message = (
625
+ message = _bounded_supervisor_text(
617
626
  f"Supervisor API {verb} {endpoint} returned an invalid result payload: "
618
627
  f"{payload!r}"
619
628
  )
@@ -717,6 +726,10 @@ async def _supervisor_api_call(
717
726
  if _JOB_COLLISION_MARKER not in error_text.lower():
718
727
  _raise_supervisor_api_failure(result, endpoint)
719
728
 
729
+ # The marker test runs on the raw text; everything below reports
730
+ # it, so bind the size once the classification is settled.
731
+ error_text = _bounded_supervisor_text(error_text)
732
+
720
733
  remaining = deadline - time.monotonic()
721
734
  if remaining <= 0:
722
735
  # The retry budget is exhausted; the group may be stuck or
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ha-mcp-dev
3
- Version: 8.3.0.dev2422
3
+ Version: 8.3.0.dev2427
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
@@ -13,6 +13,7 @@ src/ha_mcp/config.py
13
13
  src/ha_mcp/errors.py
14
14
  src/ha_mcp/hacs_auto_refresh.py
15
15
  src/ha_mcp/llm_exposure.py
16
+ src/ha_mcp/log_filters.py
16
17
  src/ha_mcp/py.typed
17
18
  src/ha_mcp/read_only.py
18
19
  src/ha_mcp/redaction.py