ha-mcp-dev 7.4.1.dev444__tar.gz → 7.4.1.dev445__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 (107) hide show
  1. {ha_mcp_dev-7.4.1.dev444/src/ha_mcp_dev.egg-info → ha_mcp_dev-7.4.1.dev445}/PKG-INFO +1 -1
  2. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/pyproject.toml +1 -1
  3. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/settings_ui.py +60 -29
  4. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/tools/tools_bug_report.py +4 -1
  5. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445/src/ha_mcp_dev.egg-info}/PKG-INFO +1 -1
  6. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/LICENSE +0 -0
  7. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/MANIFEST.in +0 -0
  8. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/README.md +0 -0
  9. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/setup.cfg +0 -0
  10. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/__init__.py +0 -0
  11. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/__main__.py +0 -0
  12. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/_pypi_marker +0 -0
  13. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/_version.py +0 -0
  14. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/auth/__init__.py +0 -0
  15. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/auth/consent_form.py +0 -0
  16. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/auth/provider.py +0 -0
  17. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/client/__init__.py +0 -0
  18. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/client/rest_client.py +0 -0
  19. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/client/websocket_client.py +0 -0
  20. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/client/websocket_listener.py +0 -0
  21. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/config.py +0 -0
  22. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/errors.py +0 -0
  23. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/py.typed +0 -0
  24. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/resources/skills-vendor/.claude/settings.json +0 -0
  25. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/resources/skills-vendor/.claude-plugin/marketplace.json +0 -0
  26. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/resources/skills-vendor/.claude-plugin/plugin.json +0 -0
  27. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/resources/skills-vendor/.github/ISSUE_TEMPLATE/skill-rca.md +0 -0
  28. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/resources/skills-vendor/AGENTS.md +0 -0
  29. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/resources/skills-vendor/CLAUDE.md +0 -0
  30. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/resources/skills-vendor/CONTRIBUTING.md +0 -0
  31. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/resources/skills-vendor/LICENSE +0 -0
  32. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/resources/skills-vendor/README.md +0 -0
  33. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/SKILL.md +0 -0
  34. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/evals/evals.json +0 -0
  35. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/automation-patterns.md +0 -0
  36. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-cards.md +0 -0
  37. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-guide.md +0 -0
  38. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/device-control.md +0 -0
  39. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/domain-docs.md +0 -0
  40. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/examples.yaml +0 -0
  41. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/helper-selection.md +0 -0
  42. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/safe-refactoring.md +0 -0
  43. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/template-guidelines.md +0 -0
  44. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/server.py +0 -0
  45. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/smoke_test.py +0 -0
  46. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/tools/__init__.py +0 -0
  47. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/tools/backup.py +0 -0
  48. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/tools/best_practice_checker.py +0 -0
  49. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/tools/device_control.py +0 -0
  50. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/tools/enhanced.py +0 -0
  51. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/tools/helpers.py +0 -0
  52. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/tools/reference_validator.py +0 -0
  53. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/tools/registry.py +0 -0
  54. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/tools/smart_search.py +0 -0
  55. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/tools/tools_addons.py +0 -0
  56. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/tools/tools_areas.py +0 -0
  57. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/tools/tools_blueprints.py +0 -0
  58. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/tools/tools_calendar.py +0 -0
  59. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/tools/tools_camera.py +0 -0
  60. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/tools/tools_categories.py +0 -0
  61. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/tools/tools_config_automations.py +0 -0
  62. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/tools/tools_config_dashboards.py +0 -0
  63. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/tools/tools_config_entry_flow.py +0 -0
  64. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/tools/tools_config_helpers.py +0 -0
  65. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/tools/tools_config_scripts.py +0 -0
  66. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/tools/tools_energy.py +0 -0
  67. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/tools/tools_entities.py +0 -0
  68. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/tools/tools_filesystem.py +0 -0
  69. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/tools/tools_groups.py +0 -0
  70. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/tools/tools_hacs.py +0 -0
  71. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/tools/tools_history.py +0 -0
  72. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/tools/tools_integrations.py +0 -0
  73. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/tools/tools_labels.py +0 -0
  74. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/tools/tools_mcp_component.py +0 -0
  75. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/tools/tools_registry.py +0 -0
  76. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/tools/tools_resources.py +0 -0
  77. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/tools/tools_search.py +0 -0
  78. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/tools/tools_service.py +0 -0
  79. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/tools/tools_services.py +0 -0
  80. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/tools/tools_system.py +0 -0
  81. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/tools/tools_todo.py +0 -0
  82. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/tools/tools_traces.py +0 -0
  83. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/tools/tools_updates.py +0 -0
  84. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/tools/tools_utility.py +0 -0
  85. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/tools/tools_voice_assistant.py +0 -0
  86. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/tools/tools_yaml_config.py +0 -0
  87. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/tools/tools_zones.py +0 -0
  88. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/tools/util_helpers.py +0 -0
  89. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/transforms/__init__.py +0 -0
  90. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/transforms/categorized_search.py +0 -0
  91. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/utils/__init__.py +0 -0
  92. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/utils/config_hash.py +0 -0
  93. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/utils/data_paths.py +0 -0
  94. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/utils/domain_handlers.py +0 -0
  95. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/utils/fuzzy_search.py +0 -0
  96. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/utils/kill_signal_diagnostics.py +0 -0
  97. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/utils/operation_manager.py +0 -0
  98. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/utils/python_sandbox.py +0 -0
  99. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp/utils/usage_logger.py +0 -0
  100. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp_dev.egg-info/SOURCES.txt +0 -0
  101. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp_dev.egg-info/dependency_links.txt +0 -0
  102. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp_dev.egg-info/entry_points.txt +0 -0
  103. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp_dev.egg-info/requires.txt +0 -0
  104. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/src/ha_mcp_dev.egg-info/top_level.txt +0 -0
  105. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/tests/__init__.py +0 -0
  106. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/tests/test_constants.py +0 -0
  107. {ha_mcp_dev-7.4.1.dev444 → ha_mcp_dev-7.4.1.dev445}/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.4.1.dev444
3
+ Version: 7.4.1.dev445
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.4.1.dev444"
7
+ version = "7.4.1.dev445"
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"
@@ -50,6 +50,7 @@ class ToolStub(TypedDict):
50
50
  destructiveHint: NotRequired[bool]
51
51
  disabled_by: NotRequired[str]
52
52
 
53
+
53
54
  _VALID_STATES = frozenset({"enabled", "disabled", "pinned"})
54
55
 
55
56
  logger = logging.getLogger(__name__)
@@ -261,7 +262,9 @@ def _render_stub(name: str, meta: ToolStub) -> dict[str, Any]:
261
262
  return rendered
262
263
 
263
264
 
264
- async def _get_tool_metadata(server: HomeAssistantSmartMCPServer) -> list[dict[str, Any]]:
265
+ async def _get_tool_metadata(
266
+ server: HomeAssistantSmartMCPServer,
267
+ ) -> list[dict[str, Any]]:
265
268
  """Extract metadata for all registered tools from the server.
266
269
 
267
270
  Uses FastMCP's internal ``local_provider._list_tools()`` because the
@@ -291,14 +294,16 @@ async def _get_tool_metadata(server: HomeAssistantSmartMCPServer) -> list[dict[s
291
294
  title = getattr(tool, "title", None) or tool.name
292
295
  if tool.annotations and getattr(tool.annotations, "title", None):
293
296
  title = tool.annotations.title
294
- tools.append({
295
- "name": tool.name,
296
- "title": title,
297
- "description": (tool.description or "")[:200],
298
- "tags": tags,
299
- "primary_tag": primary,
300
- "annotations": annotations,
301
- })
297
+ tools.append(
298
+ {
299
+ "name": tool.name,
300
+ "title": title,
301
+ "description": (tool.description or "")[:200],
302
+ "tags": tags,
303
+ "primary_tag": primary,
304
+ "annotations": annotations,
305
+ }
306
+ )
302
307
 
303
308
  registered_names = {t["name"] for t in tools}
304
309
 
@@ -362,7 +367,8 @@ def apply_tool_visibility(
362
367
  return pinned_names
363
368
 
364
369
 
365
- _SETTINGS_HTML = """\
370
+ _SETTINGS_HTML = (
371
+ """\
366
372
  <!DOCTYPE html>
367
373
  <html lang="en">
368
374
  <head>
@@ -525,8 +531,12 @@ async function restartAddon() {
525
531
  }
526
532
  }
527
533
 
528
- const DEFAULT_PINNED = """ + json.dumps(list(DEFAULT_PINNED_TOOLS)) + """;
529
- const MANDATORY = """ + json.dumps(list(MANDATORY_TOOLS)) + """;
534
+ const DEFAULT_PINNED = """
535
+ + json.dumps(list(DEFAULT_PINNED_TOOLS))
536
+ + """;
537
+ const MANDATORY = """
538
+ + json.dumps(list(MANDATORY_TOOLS))
539
+ + """;
530
540
 
531
541
  function getState(name) {
532
542
  if (toolStates[name]) return toolStates[name];
@@ -763,6 +773,7 @@ loadTools();
763
773
  </body>
764
774
  </html>
765
775
  """
776
+ )
766
777
 
767
778
 
768
779
  def register_settings_routes(
@@ -868,15 +879,18 @@ def register_settings_routes(
868
879
  pinned_count = sum(1 for s in states.values() if s == "pinned")
869
880
  logger.info(
870
881
  "Saved tool config (restart required to apply): %d disabled, %d pinned",
871
- disabled_count, pinned_count,
882
+ disabled_count,
883
+ pinned_count,
872
884
  )
873
885
 
874
- return JSONResponse({
875
- "success": True,
876
- "disabled": disabled_count,
877
- "pinned": pinned_count,
878
- "restart_required": True,
879
- })
886
+ return JSONResponse(
887
+ {
888
+ "success": True,
889
+ "disabled": disabled_count,
890
+ "pinned": pinned_count,
891
+ "restart_required": True,
892
+ }
893
+ )
880
894
 
881
895
  async def _restart_addon(_: Request) -> JSONResponse:
882
896
  token = os.environ.get("SUPERVISOR_TOKEN")
@@ -892,13 +906,20 @@ def register_settings_routes(
892
906
  # Short timeout — the supervisor kills our process during restart so
893
907
  # the connection will drop. A connection drop is actually success.
894
908
  try:
895
- async with httpx.AsyncClient(timeout=5.0) as client:
909
+ async with httpx.AsyncClient(
910
+ timeout=5.0, verify=server.settings.verify_ssl
911
+ ) as client:
896
912
  resp = await client.post(
897
913
  "http://supervisor/addons/self/restart",
898
914
  headers={"Authorization": f"Bearer {token}"},
899
915
  )
900
- except (httpx.ReadError, httpx.RemoteProtocolError, httpx.ConnectError):
901
- # Connection dropped mid-request — restart is happening
916
+ except (httpx.ReadError, httpx.RemoteProtocolError):
917
+ # Connection dropped mid-request — restart is happening.
918
+ # `ConnectError` is deliberately NOT in this tuple: it fires
919
+ # before a connection is established (DNS failure, TCP refused,
920
+ # Supervisor socket misconfigured) and means the restart was
921
+ # never initiated. Falls through to the `httpx.HTTPError`
922
+ # handler below, which returns 502 + CONNECTION_FAILED.
902
923
  logger.info("Restart request connection dropped (expected during restart)")
903
924
  return JSONResponse({"success": True, "message": "Restart initiated"})
904
925
  except httpx.HTTPError as e:
@@ -924,9 +945,11 @@ def register_settings_routes(
924
945
  return JSONResponse({"success": True, "message": "Restart initiated"})
925
946
 
926
947
  async def _settings_info(_: Request) -> JSONResponse:
927
- return JSONResponse({
928
- "is_addon": is_running_in_addon(),
929
- })
948
+ return JSONResponse(
949
+ {
950
+ "is_addon": is_running_in_addon(),
951
+ }
952
+ )
930
953
 
931
954
  secret_prefix = secret_path.rstrip("/") if secret_path else ""
932
955
  is_addon = is_running_in_addon()
@@ -958,7 +981,15 @@ def register_settings_routes(
958
981
  # endpoint. The frontend uses relative fetches (./api/settings/...)
959
982
  # so the JS works at either prefix unchanged.
960
983
  mcp.custom_route(f"{secret_prefix}/settings", methods=["GET"])(_settings_page)
961
- mcp.custom_route(f"{secret_prefix}/api/settings/tools", methods=["GET"])(_get_tools)
962
- mcp.custom_route(f"{secret_prefix}/api/settings/tools", methods=["POST"])(_save_tools)
963
- mcp.custom_route(f"{secret_prefix}/api/settings/restart", methods=["POST"])(_restart_addon)
964
- mcp.custom_route(f"{secret_prefix}/api/settings/info", methods=["GET"])(_settings_info)
984
+ mcp.custom_route(f"{secret_prefix}/api/settings/tools", methods=["GET"])(
985
+ _get_tools
986
+ )
987
+ mcp.custom_route(f"{secret_prefix}/api/settings/tools", methods=["POST"])(
988
+ _save_tools
989
+ )
990
+ mcp.custom_route(f"{secret_prefix}/api/settings/restart", methods=["POST"])(
991
+ _restart_addon
992
+ )
993
+ mcp.custom_route(f"{secret_prefix}/api/settings/info", methods=["GET"])(
994
+ _settings_info
995
+ )
@@ -19,6 +19,7 @@ from pydantic import Field
19
19
 
20
20
  from ha_mcp import __version__
21
21
 
22
+ from ..config import get_global_settings
22
23
  from ..utils.usage_logger import (
23
24
  AVG_LOG_ENTRIES_PER_TOOL,
24
25
  get_recent_logs,
@@ -181,7 +182,9 @@ async def _fetch_addon_logs() -> str:
181
182
  return ""
182
183
 
183
184
  try:
184
- async with httpx.AsyncClient(timeout=10.0) as http_client:
185
+ async with httpx.AsyncClient(
186
+ timeout=10.0, verify=get_global_settings().verify_ssl
187
+ ) as http_client:
185
188
  resp = await http_client.get(
186
189
  "http://supervisor/addons/self/logs",
187
190
  headers={"Authorization": f"Bearer {token}"},
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ha-mcp-dev
3
- Version: 7.4.1.dev444
3
+ Version: 7.4.1.dev445
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