ha-mcp-dev 7.6.0.dev640__tar.gz → 7.6.0.dev641__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 (136) hide show
  1. {ha_mcp_dev-7.6.0.dev640/src/ha_mcp_dev.egg-info → ha_mcp_dev-7.6.0.dev641}/PKG-INFO +1 -1
  2. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/pyproject.toml +1 -1
  3. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/tools_bug_report.py +8 -2
  4. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/utils/usage_logger.py +71 -1
  5. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641/src/ha_mcp_dev.egg-info}/PKG-INFO +1 -1
  6. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/LICENSE +0 -0
  7. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/MANIFEST.in +0 -0
  8. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/README.md +0 -0
  9. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/setup.cfg +0 -0
  10. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/__init__.py +0 -0
  11. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/__main__.py +0 -0
  12. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/_pypi_marker +0 -0
  13. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/_version.py +0 -0
  14. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/auth/__init__.py +0 -0
  15. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/auth/consent_form.py +0 -0
  16. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/auth/provider.py +0 -0
  17. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/backup_manager.py +0 -0
  18. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/client/__init__.py +0 -0
  19. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/client/rest_client.py +0 -0
  20. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/client/supervisor_client.py +0 -0
  21. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/client/websocket_client.py +0 -0
  22. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/client/websocket_listener.py +0 -0
  23. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/config.py +0 -0
  24. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/errors.py +0 -0
  25. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/policy/__init__.py +0 -0
  26. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/policy/approval_queue.py +0 -0
  27. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/policy/evaluator.py +0 -0
  28. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/policy/handlers.py +0 -0
  29. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/policy/middleware.py +0 -0
  30. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/policy/model.py +0 -0
  31. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/policy/persistence.py +0 -0
  32. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/policy/value_sources.py +0 -0
  33. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/py.typed +0 -0
  34. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/resources/skills-vendor/.claude/settings.json +0 -0
  35. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/resources/skills-vendor/.claude-plugin/marketplace.json +0 -0
  36. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/resources/skills-vendor/.claude-plugin/plugin.json +0 -0
  37. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/resources/skills-vendor/.github/ISSUE_TEMPLATE/skill-rca.md +0 -0
  38. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/resources/skills-vendor/.github/pull_request_template.md +0 -0
  39. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/resources/skills-vendor/AGENTS.md +0 -0
  40. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/resources/skills-vendor/CLAUDE.md +0 -0
  41. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/resources/skills-vendor/CONTRIBUTING.md +0 -0
  42. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/resources/skills-vendor/LICENSE +0 -0
  43. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/resources/skills-vendor/README.md +0 -0
  44. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/SKILL.md +0 -0
  45. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/evals/evals.json +0 -0
  46. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/automation-patterns.md +0 -0
  47. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-cards.md +0 -0
  48. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-guide.md +0 -0
  49. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/device-control.md +0 -0
  50. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/domain-docs.md +0 -0
  51. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/examples.yaml +0 -0
  52. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/helper-selection.md +0 -0
  53. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/safe-refactoring.md +0 -0
  54. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/template-guidelines.md +0 -0
  55. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/yaml-only-integrations.md +0 -0
  56. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/server.py +0 -0
  57. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/settings.css +0 -0
  58. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/settings.js +0 -0
  59. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/settings_ui.py +0 -0
  60. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/smoke_test.py +0 -0
  61. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/stdio_settings_sidecar.py +0 -0
  62. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/__init__.py +0 -0
  63. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/auto_backup.py +0 -0
  64. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/backup.py +0 -0
  65. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/best_practice_checker.py +0 -0
  66. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/device_control.py +0 -0
  67. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/enhanced.py +0 -0
  68. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/helpers.py +0 -0
  69. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/reference_validator.py +0 -0
  70. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/registry.py +0 -0
  71. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/smart_search/__init__.py +0 -0
  72. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/smart_search/_base.py +0 -0
  73. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/smart_search/_config.py +0 -0
  74. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/smart_search/_deep.py +0 -0
  75. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/smart_search/_entities.py +0 -0
  76. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/smart_search/_fetch.py +0 -0
  77. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/smart_search/_overview.py +0 -0
  78. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/smart_search/_scenes.py +0 -0
  79. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/smart_search/_scoring.py +0 -0
  80. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/tools_addons.py +0 -0
  81. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/tools_areas.py +0 -0
  82. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/tools_blueprints.py +0 -0
  83. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/tools_calendar.py +0 -0
  84. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/tools_camera.py +0 -0
  85. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/tools_categories.py +0 -0
  86. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/tools_code.py +0 -0
  87. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/tools_config_automations.py +0 -0
  88. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/tools_config_dashboards.py +0 -0
  89. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/tools_config_entry_flow.py +0 -0
  90. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/tools_config_helpers.py +0 -0
  91. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/tools_config_scenes.py +0 -0
  92. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/tools_config_scripts.py +0 -0
  93. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/tools_energy.py +0 -0
  94. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/tools_entities.py +0 -0
  95. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/tools_filesystem.py +0 -0
  96. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/tools_groups.py +0 -0
  97. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/tools_hacs.py +0 -0
  98. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/tools_history.py +0 -0
  99. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/tools_integrations.py +0 -0
  100. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/tools_labels.py +0 -0
  101. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/tools_mcp_component.py +0 -0
  102. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/tools_registry.py +0 -0
  103. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/tools_resources.py +0 -0
  104. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/tools_search.py +0 -0
  105. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/tools_service.py +0 -0
  106. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/tools_services.py +0 -0
  107. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/tools_system.py +0 -0
  108. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/tools_todo.py +0 -0
  109. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/tools_traces.py +0 -0
  110. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/tools_updates.py +0 -0
  111. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/tools_utility.py +0 -0
  112. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/tools_voice_assistant.py +0 -0
  113. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/tools_yaml_config.py +0 -0
  114. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/tools_zones.py +0 -0
  115. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/util_helpers.py +0 -0
  116. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/tools/validation_middleware.py +0 -0
  117. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/transforms/__init__.py +0 -0
  118. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/transforms/categorized_search.py +0 -0
  119. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/transforms/lite_docstrings.py +0 -0
  120. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/utils/__init__.py +0 -0
  121. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/utils/config_hash.py +0 -0
  122. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/utils/data_paths.py +0 -0
  123. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/utils/domain_handlers.py +0 -0
  124. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/utils/fuzzy_search.py +0 -0
  125. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/utils/kill_signal_diagnostics.py +0 -0
  126. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/utils/operation_manager.py +0 -0
  127. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/utils/python_sandbox.py +0 -0
  128. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp/utils/skill_loader.py +0 -0
  129. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp_dev.egg-info/SOURCES.txt +0 -0
  130. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp_dev.egg-info/dependency_links.txt +0 -0
  131. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp_dev.egg-info/entry_points.txt +0 -0
  132. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp_dev.egg-info/requires.txt +0 -0
  133. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/src/ha_mcp_dev.egg-info/top_level.txt +0 -0
  134. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/tests/__init__.py +0 -0
  135. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/tests/test_constants.py +0 -0
  136. {ha_mcp_dev-7.6.0.dev640 → ha_mcp_dev-7.6.0.dev641}/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.6.0.dev640
3
+ Version: 7.6.0.dev641
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.6.0.dev640"
7
+ version = "7.6.0.dev641"
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"
@@ -508,7 +508,8 @@ class BugReportTools:
508
508
  **OUTPUT:**
509
509
  Returns both templates plus diagnostic data. Key fields:
510
510
  - `runtime_bug_template`, `agent_behavior_template` — pick based on context
511
- - `recent_logs`, `startup_logs`captured ha-mcp tool/server log entries
511
+ - `recent_logs` — recent ha-mcp tool calls (secret parameters redacted);
512
+ startup log entries are summarised in `formatted_report`, not returned raw
512
513
  - `addon_logs` — addon container stdout/stderr (HA add-on installs only;
513
514
  empty string otherwise)
514
515
  - `suggested_title`, `duplicate_check_urls`, `anonymization_guide`
@@ -622,8 +623,13 @@ class BugReportTools:
622
623
  return {
623
624
  "success": True,
624
625
  "diagnostic_info": diagnostic_info,
626
+ # ``recent_logs`` entries are redacted at the logging chokepoint
627
+ # (UsageLogger.log_tool_usage), so the tool parameters here carry no
628
+ # secrets. ``startup_logs`` come from a separate StartupLogCollector
629
+ # that is NOT redacted at source, so the raw entries are
630
+ # intentionally omitted — the sanitized view lives in
631
+ # ``formatted_report`` (via ``_format_startup_logs``).
625
632
  "recent_logs": recent_logs,
626
- "startup_logs": startup_logs,
627
633
  "addon_logs": addon_logs,
628
634
  "log_count": len(recent_logs),
629
635
  "startup_log_count": len(startup_logs),
@@ -94,6 +94,72 @@ def get_startup_logs() -> list[dict[str, Any]]:
94
94
  return _startup_collector.get_logs()
95
95
 
96
96
 
97
+ # Parameter keys whose values are masked before a tool call is recorded to the
98
+ # in-memory ring buffer or persisted to disk. Tool kwargs can carry secrets
99
+ # (alarm/lock ``code``, tokens, passwords); these must never reach the usage
100
+ # log, which ``ha_report_issue`` surfaces and which is written verbatim to
101
+ # plaintext ``mcp_usage.jsonl``. Matching is by key name (case-insensitive) and
102
+ # recursive, so a secret nested under a non-sensitive key — e.g.
103
+ # ``ha_call_service(data={"code": ...})`` — is caught while ``data`` siblings
104
+ # like ``entity_id``/``brightness`` survive for debugging.
105
+ _SENSITIVE_PARAM_KEYS = frozenset(
106
+ {
107
+ "code",
108
+ "pin",
109
+ "password",
110
+ "passwd",
111
+ "secret",
112
+ "token",
113
+ "access_token",
114
+ "refresh_token",
115
+ "api_key",
116
+ "apikey",
117
+ "client_secret",
118
+ "authorization",
119
+ }
120
+ )
121
+ # Suffix match only for families with a low false-positive rate. Deliberately
122
+ # excludes ``_code``/``_key`` so ``status_code``/``cache_key`` stay readable;
123
+ # the exact ``code``/``pin``/``api_key`` entries above already cover the real
124
+ # Home Assistant service-call surface.
125
+ _SENSITIVE_KEY_SUFFIXES = ("_token", "_secret", "_password", "_passwd")
126
+ _REDACTED_VALUE = "[REDACTED]"
127
+ _MAX_REDACT_DEPTH = 6
128
+
129
+
130
+ def _is_sensitive_key(key: Any) -> bool:
131
+ """Return True if a parameter key's value should be masked."""
132
+ if not isinstance(key, str):
133
+ return False
134
+ lowered = key.lower()
135
+ return lowered in _SENSITIVE_PARAM_KEYS or lowered.endswith(_SENSITIVE_KEY_SUFFIXES)
136
+
137
+
138
+ def _redact_parameters(value: Any, _depth: int = 0) -> Any:
139
+ """Return a copy of ``value`` with sensitive values masked by key name.
140
+
141
+ Never mutates the input: it is the live tool ``kwargs`` dict, still
142
+ referenced by the caller after this returns. Recurses through nested
143
+ dicts/lists/tuples so secrets nested under non-sensitive keys are caught
144
+ (a tuple is returned as a list). Fails closed past ``_MAX_REDACT_DEPTH`` —
145
+ a subtree too deep to walk is masked wholesale rather than returned verbatim.
146
+ """
147
+ if _depth > _MAX_REDACT_DEPTH:
148
+ return _REDACTED_VALUE
149
+ if isinstance(value, dict):
150
+ return {
151
+ key: (
152
+ _REDACTED_VALUE
153
+ if _is_sensitive_key(key)
154
+ else _redact_parameters(item, _depth + 1)
155
+ )
156
+ for key, item in value.items()
157
+ }
158
+ if isinstance(value, (list, tuple)):
159
+ return [_redact_parameters(item, _depth + 1) for item in value]
160
+ return value
161
+
162
+
97
163
  @dataclass
98
164
  class ToolUsageLog:
99
165
  """Single tool usage log entry."""
@@ -201,10 +267,14 @@ class UsageLogger:
201
267
  if not self._enabled:
202
268
  return
203
269
  try:
270
+ # Mask secrets (alarm/lock codes, tokens, passwords) before the entry
271
+ # reaches the ring buffer or disk. Returns a copy — never mutates the
272
+ # caller's live kwargs dict.
273
+ redacted_parameters = _redact_parameters(parameters)
204
274
  log_entry = ToolUsageLog(
205
275
  timestamp=datetime.now(UTC).isoformat(),
206
276
  tool_name=tool_name,
207
- parameters=parameters,
277
+ parameters=redacted_parameters,
208
278
  execution_time_ms=execution_time_ms,
209
279
  success=success,
210
280
  error_message=error_message,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ha-mcp-dev
3
- Version: 7.6.0.dev640
3
+ Version: 7.6.0.dev641
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