ha-mcp-dev 7.7.0.dev697__tar.gz → 7.7.0.dev698__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 (143) hide show
  1. {ha_mcp_dev-7.7.0.dev697/src/ha_mcp_dev.egg-info → ha_mcp_dev-7.7.0.dev698}/PKG-INFO +1 -1
  2. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/pyproject.toml +1 -1
  3. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/__main__.py +69 -2
  4. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698/src/ha_mcp_dev.egg-info}/PKG-INFO +1 -1
  5. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/LICENSE +0 -0
  6. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/MANIFEST.in +0 -0
  7. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/README.md +0 -0
  8. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/setup.cfg +0 -0
  9. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/__init__.py +0 -0
  10. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/_pypi_marker +0 -0
  11. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/_version.py +0 -0
  12. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/auth/__init__.py +0 -0
  13. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/auth/consent_form.py +0 -0
  14. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/auth/provider.py +0 -0
  15. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/backup_manager.py +0 -0
  16. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/client/__init__.py +0 -0
  17. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/client/rest_client.py +0 -0
  18. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/client/supervisor_client.py +0 -0
  19. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/client/websocket_client.py +0 -0
  20. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/client/websocket_listener.py +0 -0
  21. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/config.py +0 -0
  22. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/dashboard_screenshot/__init__.py +0 -0
  23. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/dashboard_screenshot/capture.py +0 -0
  24. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/dashboard_screenshot/provision.py +0 -0
  25. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/errors.py +0 -0
  26. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/policy/__init__.py +0 -0
  27. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/policy/approval_queue.py +0 -0
  28. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/policy/evaluator.py +0 -0
  29. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/policy/handlers.py +0 -0
  30. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/policy/middleware.py +0 -0
  31. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/policy/model.py +0 -0
  32. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/policy/persistence.py +0 -0
  33. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/policy/value_sources.py +0 -0
  34. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/py.typed +0 -0
  35. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/read_only.py +0 -0
  36. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/resources/skills-vendor/.claude/settings.json +0 -0
  37. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/resources/skills-vendor/.claude-plugin/marketplace.json +0 -0
  38. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/resources/skills-vendor/.claude-plugin/plugin.json +0 -0
  39. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/resources/skills-vendor/.github/ISSUE_TEMPLATE/skill-rca.md +0 -0
  40. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/resources/skills-vendor/.github/pull_request_template.md +0 -0
  41. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/resources/skills-vendor/AGENTS.md +0 -0
  42. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/resources/skills-vendor/CLAUDE.md +0 -0
  43. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/resources/skills-vendor/CONTRIBUTING.md +0 -0
  44. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/resources/skills-vendor/LICENSE +0 -0
  45. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/resources/skills-vendor/README.md +0 -0
  46. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/SKILL.md +0 -0
  47. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/evals/evals.json +0 -0
  48. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/automation-patterns.md +0 -0
  49. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-cards.md +0 -0
  50. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-guide.md +0 -0
  51. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/device-control.md +0 -0
  52. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/domain-docs.md +0 -0
  53. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/examples.yaml +0 -0
  54. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/helper-selection.md +0 -0
  55. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/safe-refactoring.md +0 -0
  56. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/template-guidelines.md +0 -0
  57. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/yaml-only-integrations.md +0 -0
  58. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/server.py +0 -0
  59. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/settings.css +0 -0
  60. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/settings.js +0 -0
  61. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/settings_ui.py +0 -0
  62. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/smoke_test.py +0 -0
  63. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/stdio_settings_sidecar.py +0 -0
  64. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/__init__.py +0 -0
  65. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/auto_backup.py +0 -0
  66. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/backup.py +0 -0
  67. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/best_practice_checker.py +0 -0
  68. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/config_entry_flow.py +0 -0
  69. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/device_control.py +0 -0
  70. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/enhanced.py +0 -0
  71. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/helpers.py +0 -0
  72. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/reference_validator.py +0 -0
  73. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/registry.py +0 -0
  74. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/smart_search/__init__.py +0 -0
  75. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/smart_search/_base.py +0 -0
  76. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/smart_search/_config.py +0 -0
  77. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/smart_search/_deep.py +0 -0
  78. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/smart_search/_entities.py +0 -0
  79. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/smart_search/_fetch.py +0 -0
  80. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/smart_search/_overview.py +0 -0
  81. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/smart_search/_scenes.py +0 -0
  82. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/smart_search/_scoring.py +0 -0
  83. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/tool_search_hint_middleware.py +0 -0
  84. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/tools_addons.py +0 -0
  85. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/tools_areas.py +0 -0
  86. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/tools_blueprints.py +0 -0
  87. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/tools_bug_report.py +0 -0
  88. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/tools_calendar.py +0 -0
  89. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/tools_camera.py +0 -0
  90. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/tools_categories.py +0 -0
  91. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/tools_code.py +0 -0
  92. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/tools_config_automations.py +0 -0
  93. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/tools_config_dashboards.py +0 -0
  94. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/tools_config_helpers.py +0 -0
  95. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/tools_config_scenes.py +0 -0
  96. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/tools_config_scripts.py +0 -0
  97. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/tools_dashboard_screenshot.py +0 -0
  98. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/tools_energy.py +0 -0
  99. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/tools_entities.py +0 -0
  100. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/tools_filesystem.py +0 -0
  101. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/tools_groups.py +0 -0
  102. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/tools_hacs.py +0 -0
  103. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/tools_history.py +0 -0
  104. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/tools_integrations.py +0 -0
  105. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/tools_labels.py +0 -0
  106. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/tools_mcp_component.py +0 -0
  107. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/tools_registry.py +0 -0
  108. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/tools_resources.py +0 -0
  109. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/tools_search.py +0 -0
  110. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/tools_service.py +0 -0
  111. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/tools_services.py +0 -0
  112. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/tools_system.py +0 -0
  113. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/tools_themes.py +0 -0
  114. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/tools_todo.py +0 -0
  115. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/tools_traces.py +0 -0
  116. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/tools_updates.py +0 -0
  117. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/tools_utility.py +0 -0
  118. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/tools_voice_assistant.py +0 -0
  119. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/tools_yaml_config.py +0 -0
  120. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/tools_zones.py +0 -0
  121. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/util_helpers.py +0 -0
  122. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/tools/validation_middleware.py +0 -0
  123. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/transforms/__init__.py +0 -0
  124. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/transforms/categorized_search.py +0 -0
  125. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/transforms/lite_docstrings.py +0 -0
  126. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/utils/__init__.py +0 -0
  127. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/utils/config_hash.py +0 -0
  128. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/utils/data_paths.py +0 -0
  129. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/utils/domain_handlers.py +0 -0
  130. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/utils/fuzzy_search.py +0 -0
  131. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/utils/kill_signal_diagnostics.py +0 -0
  132. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/utils/operation_manager.py +0 -0
  133. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/utils/python_sandbox.py +0 -0
  134. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/utils/skill_loader.py +0 -0
  135. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp/utils/usage_logger.py +0 -0
  136. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp_dev.egg-info/SOURCES.txt +0 -0
  137. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp_dev.egg-info/dependency_links.txt +0 -0
  138. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp_dev.egg-info/entry_points.txt +0 -0
  139. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp_dev.egg-info/requires.txt +0 -0
  140. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/src/ha_mcp_dev.egg-info/top_level.txt +0 -0
  141. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/tests/__init__.py +0 -0
  142. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/tests/test_constants.py +0 -0
  143. {ha_mcp_dev-7.7.0.dev697 → ha_mcp_dev-7.7.0.dev698}/tests/test_env_manager.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ha-mcp-dev
3
- Version: 7.7.0.dev697
3
+ Version: 7.7.0.dev698
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 = "7.7.0.dev697"
7
+ version = "7.7.0.dev698"
8
8
  description = "Home Assistant MCP Server - Complete control of Home Assistant through MCP"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.13,<3.14"
@@ -402,6 +402,46 @@ class ToolValidationLogFilter(logging.Filter):
402
402
  return True
403
403
 
404
404
 
405
+ class ProbeAccessLogFilter(logging.Filter):
406
+ """Drop benign, non-MCP HTTP probe noise from the uvicorn access log.
407
+
408
+ * ``GET``/``HEAD`` ``/favicon.ico`` -> ``404``: browsers auto-request a
409
+ favicon that doesn't exist. Pure noise, always dropped.
410
+ * ``GET``/``HEAD`` on the MCP path -> ``405``: a non-MCP caller (browser,
411
+ health check, reverse proxy, or a connector's SSE-style pre-flight) hit a
412
+ POST-only Streamable HTTP endpoint. The raw access line is dropped and the
413
+ landing handler logs one annotated "(NORMAL for most non-SSE connections)"
414
+ line in its place. Dropped only when ``drop_mcp_405`` is set — SSE callers
415
+ pass False, since there a GET answers 200 and a GET-405 is a genuine fault.
416
+ """
417
+
418
+ def __init__(self, mcp_path: str, *, drop_mcp_405: bool = True) -> None:
419
+ super().__init__()
420
+ self._mcp_path = mcp_path.rstrip("/") or "/"
421
+ self._drop_mcp_405 = drop_mcp_405
422
+
423
+ def filter(self, record: logging.LogRecord) -> bool:
424
+ # uvicorn.access records carry structured args: (client, method, path,
425
+ # http_version, status_int). Match on those, not the formatted string.
426
+ args = record.args
427
+ if not isinstance(args, tuple) or len(args) != 5:
428
+ return True
429
+ method, raw_path, status = args[1], args[2], args[4]
430
+ if method not in ("GET", "HEAD"):
431
+ return True
432
+ path = str(raw_path).split("?", 1)[0].rstrip("/") or "/"
433
+ if status == 404 and path == "/favicon.ico":
434
+ return False # browser favicon auto-request — pure noise
435
+ # By-design probe 405 on the MCP path; the handler logs an annotated line
436
+ # instead. This trusts that the landing route is the only GET/HEAD responder
437
+ # on the MCP path (true today). Kept in SSE mode (drop_mcp_405=False), where
438
+ # a GET answers 200 and a 405 is a real fault.
439
+ is_dropped_probe = (
440
+ status == 405 and path == self._mcp_path and self._drop_mcp_405
441
+ )
442
+ return not is_dropped_probe
443
+
444
+
405
445
  def _setup_logging(log_level_str: str, force: bool = False) -> None:
406
446
  """Configure root logger with consistent timestamp format."""
407
447
  logging.basicConfig(
@@ -858,7 +898,12 @@ async def _run_http_with_graceful_shutdown(
858
898
  _registered_landing_paths: set[str] = set()
859
899
 
860
900
 
861
- def register_browser_landing(mcp_instance: "FastMCP | _DeferredMCP", path: str) -> None:
901
+ def register_browser_landing(
902
+ mcp_instance: "FastMCP | _DeferredMCP",
903
+ path: str,
904
+ *,
905
+ quiet_probe_log: bool = True,
906
+ ) -> None:
862
907
  """Register a GET handler that returns 405 with a helpful message.
863
908
 
864
909
  Browsers and misconfigured clients that send GET instead of POST will see
@@ -869,6 +914,10 @@ def register_browser_landing(mcp_instance: "FastMCP | _DeferredMCP", path: str)
869
914
  Args:
870
915
  mcp_instance: The FastMCP server to register the route on.
871
916
  path: The MCP endpoint path (e.g. "/mcp" or a secret path).
917
+ quiet_probe_log: When True (default, for Streamable HTTP), drop the
918
+ by-design GET/HEAD-405 probe line on the MCP path from the uvicorn
919
+ access log (the handler logs an annotated replacement). Pass False
920
+ for SSE, where a GET answers 200 and a 405 is a genuine fault.
872
921
  """
873
922
  if path in _registered_landing_paths:
874
923
  logger.warning(
@@ -905,6 +954,12 @@ def register_browser_landing(mcp_instance: "FastMCP | _DeferredMCP", path: str)
905
954
  # Custom routes are registered at lowest precedence (after the MCP route).
906
955
  @mcp_instance.custom_route(path, methods=["GET"])
907
956
  async def _browser_landing(_: Request) -> PlainTextResponse:
957
+ # Any GET here is a non-MCP caller (browser, health check, proxy, or a
958
+ # connector's SSE-style pre-flight) hitting this POST-only Streamable HTTP
959
+ # endpoint, which answers 405 by design. Log one annotated line so the 405
960
+ # reads as expected; ProbeAccessLogFilter drops the raw uvicorn access line
961
+ # so there's no cryptic duplicate.
962
+ logger.info("GET %s -> 405 (NORMAL for most non-SSE connections)", path)
908
963
  return PlainTextResponse(
909
964
  _landing_message,
910
965
  status_code=405,
@@ -913,6 +968,16 @@ def register_browser_landing(mcp_instance: "FastMCP | _DeferredMCP", path: str)
913
968
  headers={"Allow": "POST, DELETE"},
914
969
  )
915
970
 
971
+ # Tidy uvicorn's access log: always drop browser favicon 404s, and drop the
972
+ # raw by-design GET/HEAD-405 probe line on the MCP path (the handler above logs
973
+ # an annotated replacement). The 405 drop is skipped for SSE
974
+ # (quiet_probe_log=False), where a GET answers 200 and a 405 is a real fault.
975
+ # Attach to uvicorn.access directly — it has propagate=False, so a root-logger
976
+ # filter would miss it.
977
+ logging.getLogger("uvicorn.access").addFilter(
978
+ ProbeAccessLogFilter(path, drop_mcp_405=quiet_probe_log)
979
+ )
980
+
916
981
 
917
982
  def _log_settings_url(host: str, port: int, path: str) -> None:
918
983
  """Log the web settings-UI URL at HTTP startup.
@@ -946,7 +1011,9 @@ def _run_http_server(transport: str, default_port: int = 8086) -> None:
946
1011
 
947
1012
  host, port, path = _get_http_runtime(default_port)
948
1013
  _warn_if_default_path_exposed(host, port, path)
949
- register_browser_landing(_get_mcp(), path)
1014
+ # SSE transport answers GET with 200 (the event stream), so a GET->405 there
1015
+ # would be a real fault, not a benign probe — keep its access log intact.
1016
+ register_browser_landing(_get_mcp(), path, quiet_probe_log=transport != "sse")
950
1017
  register_settings_routes(_get_mcp(), _get_server(), secret_path=path)
951
1018
  _log_settings_url(host, port, path)
952
1019
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ha-mcp-dev
3
- Version: 7.7.0.dev697
3
+ Version: 7.7.0.dev698
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