ha-mcp-dev 7.14.2.dev2115__tar.gz → 7.14.2.dev2117__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 (190) hide show
  1. {ha_mcp_dev-7.14.2.dev2115/src/ha_mcp_dev.egg-info → ha_mcp_dev-7.14.2.dev2117}/PKG-INFO +1 -1
  2. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/pyproject.toml +1 -1
  3. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/auth/provider.py +83 -10
  4. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117/src/ha_mcp_dev.egg-info}/PKG-INFO +1 -1
  5. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/LICENSE +0 -0
  6. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/MANIFEST.in +0 -0
  7. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/README.md +0 -0
  8. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/setup.cfg +0 -0
  9. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/__init__.py +0 -0
  10. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/__main__.py +0 -0
  11. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/_pypi_marker +0 -0
  12. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/_version.py +0 -0
  13. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/auth/__init__.py +0 -0
  14. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/auth/consent_form.py +0 -0
  15. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/backup_manager.py +0 -0
  16. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/browser_landing.py +0 -0
  17. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/client/__init__.py +0 -0
  18. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/client/rest_client.py +0 -0
  19. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/client/supervisor_client.py +0 -0
  20. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/client/websocket_client.py +0 -0
  21. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/client/websocket_listener.py +0 -0
  22. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/config.py +0 -0
  23. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/dashboard_screenshot/__init__.py +0 -0
  24. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/dashboard_screenshot/capture.py +0 -0
  25. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/dashboard_screenshot/content.py +0 -0
  26. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/dashboard_screenshot/paths.py +0 -0
  27. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/dashboard_screenshot/provision.py +0 -0
  28. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/dashboard_screenshot/theme_guard.py +0 -0
  29. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/errors.py +0 -0
  30. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/llm_exposure.py +0 -0
  31. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/policy/__init__.py +0 -0
  32. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/policy/approval_queue.py +0 -0
  33. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/policy/evaluator.py +0 -0
  34. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/policy/handlers.py +0 -0
  35. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/policy/middleware.py +0 -0
  36. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/policy/model.py +0 -0
  37. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/policy/persistence.py +0 -0
  38. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/policy/value_sources.py +0 -0
  39. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/py.typed +0 -0
  40. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/read_only.py +0 -0
  41. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/resources/skills-vendor/.claude/settings.json +0 -0
  42. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/resources/skills-vendor/.claude-plugin/marketplace.json +0 -0
  43. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/resources/skills-vendor/.claude-plugin/plugin.json +0 -0
  44. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/resources/skills-vendor/.github/ISSUE_TEMPLATE/skill-rca.md +0 -0
  45. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/resources/skills-vendor/.github/pull_request_template.md +0 -0
  46. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/resources/skills-vendor/AGENTS.md +0 -0
  47. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/resources/skills-vendor/CLAUDE.md +0 -0
  48. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/resources/skills-vendor/CONTRIBUTING.md +0 -0
  49. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/resources/skills-vendor/LICENSE +0 -0
  50. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/resources/skills-vendor/README.md +0 -0
  51. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/SKILL.md +0 -0
  52. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/evals/evals.json +0 -0
  53. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/appdaemon.md +0 -0
  54. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/automation-patterns.md +0 -0
  55. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/blueprint-guide.md +0 -0
  56. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-cards.md +0 -0
  57. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-guide.md +0 -0
  58. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/device-control.md +0 -0
  59. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/domain-docs.md +0 -0
  60. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/examples.yaml +0 -0
  61. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/helper-selection.md +0 -0
  62. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/safe-refactoring.md +0 -0
  63. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/scenes.md +0 -0
  64. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/template-guidelines.md +0 -0
  65. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/yaml-only-integrations.md +0 -0
  66. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/server.py +0 -0
  67. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/settings_ui/__init__.py +0 -0
  68. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/settings_ui/_handlers_advanced.py +0 -0
  69. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/settings_ui/_handlers_backups.py +0 -0
  70. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/settings_ui/_handlers_fs.py +0 -0
  71. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/settings_ui/_handlers_server.py +0 -0
  72. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/settings_ui/_handlers_theme.py +0 -0
  73. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/settings_ui/_handlers_tools.py +0 -0
  74. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/settings_ui/_i18n.py +0 -0
  75. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/settings_ui/_persistence.py +0 -0
  76. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/settings_ui/_supervisor.py +0 -0
  77. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/settings_ui/_theme.py +0 -0
  78. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/settings_ui/_tools_meta.py +0 -0
  79. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/settings_ui/locales/README.md +0 -0
  80. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/settings_ui/locales/de.json +0 -0
  81. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/settings_ui/locales/en.json +0 -0
  82. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/settings_ui/locales/ru.json +0 -0
  83. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/settings_ui/locales/zh-Hans.json +0 -0
  84. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/settings_ui/settings.css +0 -0
  85. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/settings_ui/settings.html +0 -0
  86. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/settings_ui/settings.js +0 -0
  87. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/smoke_test.py +0 -0
  88. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/stdio_settings_sidecar.py +0 -0
  89. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/strict_bps.py +0 -0
  90. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/__init__.py +0 -0
  91. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/auto_backup.py +0 -0
  92. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/backup.py +0 -0
  93. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/best_practice_checker.py +0 -0
  94. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/component_api.py +0 -0
  95. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/component_config_reads.py +0 -0
  96. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/component_devices.py +0 -0
  97. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/component_registries.py +0 -0
  98. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/component_registry_lookup.py +0 -0
  99. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/config_entry_flow.py +0 -0
  100. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/device_control.py +0 -0
  101. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/enhanced.py +0 -0
  102. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/helpers.py +0 -0
  103. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/radio/__init__.py +0 -0
  104. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/radio/base.py +0 -0
  105. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/radio/matter.py +0 -0
  106. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/radio/thread.py +0 -0
  107. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/radio/zigbee.py +0 -0
  108. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/radio/zwave.py +0 -0
  109. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/reference_validator.py +0 -0
  110. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/registry.py +0 -0
  111. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/smart_search/__init__.py +0 -0
  112. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/smart_search/_base.py +0 -0
  113. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/smart_search/_config.py +0 -0
  114. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/smart_search/_deep.py +0 -0
  115. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/smart_search/_entities.py +0 -0
  116. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/smart_search/_fetch.py +0 -0
  117. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/smart_search/_overview.py +0 -0
  118. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/smart_search/_scenes.py +0 -0
  119. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/smart_search/_scoring.py +0 -0
  120. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/tool_search_hint_middleware.py +0 -0
  121. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/tools_addons.py +0 -0
  122. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/tools_areas.py +0 -0
  123. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/tools_blueprints.py +0 -0
  124. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/tools_bug_report.py +0 -0
  125. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/tools_calendar.py +0 -0
  126. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/tools_camera.py +0 -0
  127. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/tools_categories.py +0 -0
  128. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/tools_code.py +0 -0
  129. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/tools_config_automations.py +0 -0
  130. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/tools_config_dashboards.py +0 -0
  131. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/tools_config_helpers.py +0 -0
  132. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/tools_config_scenes.py +0 -0
  133. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/tools_config_scripts.py +0 -0
  134. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/tools_dashboard_screenshot.py +0 -0
  135. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/tools_dev.py +0 -0
  136. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/tools_energy.py +0 -0
  137. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/tools_entities.py +0 -0
  138. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/tools_filesystem.py +0 -0
  139. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/tools_groups.py +0 -0
  140. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/tools_hacs.py +0 -0
  141. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/tools_history.py +0 -0
  142. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/tools_integrations.py +0 -0
  143. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/tools_labels.py +0 -0
  144. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/tools_radio.py +0 -0
  145. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/tools_registry.py +0 -0
  146. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/tools_resources.py +0 -0
  147. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/tools_search.py +0 -0
  148. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/tools_service.py +0 -0
  149. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/tools_services.py +0 -0
  150. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/tools_system.py +0 -0
  151. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/tools_themes.py +0 -0
  152. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/tools_todo.py +0 -0
  153. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/tools_traces.py +0 -0
  154. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/tools_updates.py +0 -0
  155. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/tools_utility.py +0 -0
  156. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/tools_voice_assistant.py +0 -0
  157. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/tools_yaml_config.py +0 -0
  158. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/tools_yaml_read.py +0 -0
  159. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/tools_zones.py +0 -0
  160. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/util_helpers.py +0 -0
  161. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/tools/validation_middleware.py +0 -0
  162. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/transforms/__init__.py +0 -0
  163. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/transforms/categorized_search.py +0 -0
  164. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/transforms/lite_docstrings.py +0 -0
  165. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/transport_security.py +0 -0
  166. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/update_check.py +0 -0
  167. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/utils/__init__.py +0 -0
  168. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/utils/config_hash.py +0 -0
  169. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/utils/config_write_lock.py +0 -0
  170. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/utils/data_paths.py +0 -0
  171. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/utils/domain_handlers.py +0 -0
  172. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/utils/fuzzy_search.py +0 -0
  173. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/utils/kill_signal_diagnostics.py +0 -0
  174. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/utils/operation_manager.py +0 -0
  175. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/utils/python_sandbox.py +0 -0
  176. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/utils/skill_loader.py +0 -0
  177. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/utils/usage_logger.py +0 -0
  178. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/visibility/__init__.py +0 -0
  179. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/visibility/enforcement.py +0 -0
  180. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/visibility/model.py +0 -0
  181. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/visibility/persistence.py +0 -0
  182. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp/visibility/resolver.py +0 -0
  183. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp_dev.egg-info/SOURCES.txt +0 -0
  184. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp_dev.egg-info/dependency_links.txt +0 -0
  185. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp_dev.egg-info/entry_points.txt +0 -0
  186. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp_dev.egg-info/requires.txt +0 -0
  187. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/src/ha_mcp_dev.egg-info/top_level.txt +0 -0
  188. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/tests/__init__.py +0 -0
  189. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/tests/test_constants.py +0 -0
  190. {ha_mcp_dev-7.14.2.dev2115 → ha_mcp_dev-7.14.2.dev2117}/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.14.2.dev2115
3
+ Version: 7.14.2.dev2117
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.14.2.dev2115"
7
+ version = "7.14.2.dev2117"
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
@@ -16,9 +16,10 @@ import os
16
16
  import secrets
17
17
  import time
18
18
  from base64 import urlsafe_b64decode, urlsafe_b64encode
19
+ from collections.abc import Awaitable, Callable
19
20
  from pathlib import Path
20
21
  from typing import Any
21
- from urllib.parse import urlencode
22
+ from urllib.parse import parse_qs, urlencode, urlparse, urlunparse
22
23
 
23
24
  from fastmcp.server.auth.auth import (
24
25
  AccessToken, # FastMCP version has claims field
@@ -370,6 +371,58 @@ class HomeAssistantOAuthProvider(OAuthProvider):
370
371
  logger.debug(f"Failed to decode token: {e}")
371
372
  return None
372
373
 
374
+ def _issuer(self) -> str:
375
+ """The issuer identifier this authorization server advertises.
376
+
377
+ Single source for the ``issuer`` field of the metadata document served
378
+ below and for the RFC 9207 ``iss`` authorization-response parameter,
379
+ which RFC 9207 §2 requires to equal the advertised issuer exactly.
380
+ """
381
+ return str(AnyHttpUrl(str(self.base_url).rstrip("/")))
382
+
383
+ def _ensure_single_iss(self, url: str) -> str:
384
+ """Return ``url`` carrying the RFC 9207 ``iss`` parameter exactly once.
385
+
386
+ A registered redirect URI may itself carry an ``iss`` query parameter;
387
+ blindly appending ours would produce an ambiguous double-``iss``
388
+ response — and common parsers take the FIRST value, which is precisely
389
+ the issuer mix-up RFC 9207 exists to prevent. Any pre-existing ``iss``
390
+ is dropped so the one this server stamps is authoritative.
391
+ """
392
+ parsed = urlparse(url)
393
+ params = [
394
+ (k, v) for k, vs in parse_qs(parsed.query).items() for v in vs if k != "iss"
395
+ ]
396
+ params.append(("iss", self._issuer()))
397
+ return urlunparse(parsed._replace(query=urlencode(params)))
398
+
399
+ def _wrap_authorize_with_iss(
400
+ self, endpoint: "Callable[[Request], Awaitable[Response]]"
401
+ ) -> "Callable[[Request], Awaitable[Response]]":
402
+ """Wrap the SDK's ``/authorize`` endpoint to stamp ``iss`` on its
403
+ error redirects.
404
+
405
+ The SDK's ``AuthorizationHandler`` builds OAuth error authorization
406
+ responses (invalid scope, ``authorize()`` raising after redirect-URI
407
+ validation) itself, without the RFC 9207 ``iss`` parameter — only our
408
+ consent-form success path carries it otherwise. Success on this route
409
+ is a same-origin redirect to the consent form (no ``error``), which is
410
+ not an authorization response and stays untouched.
411
+ """
412
+
413
+ async def authorize_with_iss(request: Request) -> Response:
414
+ response: Response = await endpoint(request)
415
+ location = response.headers.get("location", "")
416
+ if (
417
+ response.status_code in (302, 303, 307)
418
+ and location
419
+ and "error" in parse_qs(urlparse(location).query)
420
+ ):
421
+ response.headers["location"] = self._ensure_single_iss(location)
422
+ return response
423
+
424
+ return authorize_with_iss
425
+
373
426
  def get_routes(self, mcp_path: str | None = None) -> list[Route]:
374
427
  """
375
428
  Get OAuth routes including custom consent form routes.
@@ -391,12 +444,9 @@ class HomeAssistantOAuthProvider(OAuthProvider):
391
444
  """Enhanced OAuth metadata handler with Claude.ai compatibility."""
392
445
  from mcp.server.auth.routes import build_metadata
393
446
 
394
- # Get base URL
395
- base = str(self.base_url).rstrip("/")
396
-
397
447
  # Get base metadata from MCP SDK
398
448
  metadata = build_metadata(
399
- issuer_url=AnyHttpUrl(base),
449
+ issuer_url=AnyHttpUrl(self._issuer()),
400
450
  service_documentation_url=AnyHttpUrl(
401
451
  "https://github.com/homeassistant-ai/ha-mcp"
402
452
  ),
@@ -411,6 +461,11 @@ class HomeAssistantOAuthProvider(OAuthProvider):
411
461
  # Add response_modes_supported (required by some OAuth clients)
412
462
  metadata_dict["response_modes_supported"] = ["query"]
413
463
 
464
+ # RFC 9207 §3: advertise that authorization responses carry the
465
+ # ``iss`` parameter — omission means "not supported" to
466
+ # discovery-driven clients even though redirects now include it.
467
+ metadata_dict["authorization_response_iss_parameter_supported"] = True
468
+
414
469
  # Add "none" auth method for public clients with PKCE (used by Claude.ai)
415
470
  if "token_endpoint_auth_methods_supported" in metadata_dict:
416
471
  if "none" not in metadata_dict["token_endpoint_auth_methods_supported"]:
@@ -448,6 +503,16 @@ class HomeAssistantOAuthProvider(OAuthProvider):
448
503
  methods=["GET", "OPTIONS"],
449
504
  )
450
505
  )
506
+ elif isinstance(route, Route) and route.path == "/authorize":
507
+ # RFC 9207: the SDK handler's own error redirects must carry
508
+ # ``iss`` too — see _wrap_authorize_with_iss.
509
+ enhanced_routes.append(
510
+ Route(
511
+ path=route.path,
512
+ endpoint=self._wrap_authorize_with_iss(route.endpoint),
513
+ methods=list(route.methods or []),
514
+ )
515
+ )
451
516
  else:
452
517
  enhanced_routes.append(route)
453
518
 
@@ -697,11 +762,19 @@ class HomeAssistantOAuthProvider(OAuthProvider):
697
762
  # Clean up pending authorization
698
763
  del self.pending_authorizations[str(txn_id)]
699
764
 
700
- # Redirect back to client with auth code
701
- redirect_uri = construct_redirect_uri(
702
- pending["redirect_uri"],
703
- code=auth_code_value,
704
- state=pending.get("state"),
765
+ # Redirect back to client with auth code. RFC 9207: the authorization
766
+ # response carries the issuer that produced it, so a client registered
767
+ # with several authorization servers cannot be fed a code minted by a
768
+ # different one. _ensure_single_iss (rather than an ``iss=`` kwarg
769
+ # here) collapses any ``iss`` baked into the registered redirect URI —
770
+ # construct_redirect_uri appends blindly, and a double ``iss`` is
771
+ # ambiguous to strict clients.
772
+ redirect_uri = self._ensure_single_iss(
773
+ construct_redirect_uri(
774
+ pending["redirect_uri"],
775
+ code=auth_code_value,
776
+ state=pending.get("state"),
777
+ )
705
778
  )
706
779
 
707
780
  logger.info(f"Authorization successful for client {client_id}")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ha-mcp-dev
3
- Version: 7.14.2.dev2115
3
+ Version: 7.14.2.dev2117
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