ha-mcp-dev 7.4.1.dev504__tar.gz → 7.5.0.dev507__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 (111) hide show
  1. {ha_mcp_dev-7.4.1.dev504/src/ha_mcp_dev.egg-info → ha_mcp_dev-7.5.0.dev507}/PKG-INFO +1 -1
  2. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/pyproject.toml +1 -1
  3. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/client/rest_client.py +36 -12
  4. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/tools/tools_utility.py +71 -29
  5. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507/src/ha_mcp_dev.egg-info}/PKG-INFO +1 -1
  6. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/LICENSE +0 -0
  7. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/MANIFEST.in +0 -0
  8. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/README.md +0 -0
  9. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/setup.cfg +0 -0
  10. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/__init__.py +0 -0
  11. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/__main__.py +0 -0
  12. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/_pypi_marker +0 -0
  13. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/_version.py +0 -0
  14. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/auth/__init__.py +0 -0
  15. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/auth/consent_form.py +0 -0
  16. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/auth/provider.py +0 -0
  17. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/client/__init__.py +0 -0
  18. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/client/supervisor_client.py +0 -0
  19. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/client/websocket_client.py +0 -0
  20. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/client/websocket_listener.py +0 -0
  21. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/config.py +0 -0
  22. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/errors.py +0 -0
  23. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/py.typed +0 -0
  24. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/resources/skills-vendor/.claude/settings.json +0 -0
  25. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/resources/skills-vendor/.claude-plugin/marketplace.json +0 -0
  26. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/resources/skills-vendor/.claude-plugin/plugin.json +0 -0
  27. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/resources/skills-vendor/.github/ISSUE_TEMPLATE/skill-rca.md +0 -0
  28. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/resources/skills-vendor/AGENTS.md +0 -0
  29. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/resources/skills-vendor/CLAUDE.md +0 -0
  30. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/resources/skills-vendor/CONTRIBUTING.md +0 -0
  31. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/resources/skills-vendor/LICENSE +0 -0
  32. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/resources/skills-vendor/README.md +0 -0
  33. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/SKILL.md +0 -0
  34. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/evals/evals.json +0 -0
  35. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/automation-patterns.md +0 -0
  36. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-cards.md +0 -0
  37. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-guide.md +0 -0
  38. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/device-control.md +0 -0
  39. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/domain-docs.md +0 -0
  40. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/examples.yaml +0 -0
  41. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/helper-selection.md +0 -0
  42. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/safe-refactoring.md +0 -0
  43. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/template-guidelines.md +0 -0
  44. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/server.py +0 -0
  45. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/settings_ui.py +0 -0
  46. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/smoke_test.py +0 -0
  47. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/tools/__init__.py +0 -0
  48. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/tools/backup.py +0 -0
  49. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/tools/best_practice_checker.py +0 -0
  50. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/tools/device_control.py +0 -0
  51. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/tools/enhanced.py +0 -0
  52. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/tools/helpers.py +0 -0
  53. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/tools/reference_validator.py +0 -0
  54. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/tools/registry.py +0 -0
  55. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/tools/smart_search.py +0 -0
  56. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/tools/tools_addons.py +0 -0
  57. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/tools/tools_areas.py +0 -0
  58. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/tools/tools_blueprints.py +0 -0
  59. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/tools/tools_bug_report.py +0 -0
  60. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/tools/tools_calendar.py +0 -0
  61. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/tools/tools_camera.py +0 -0
  62. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/tools/tools_categories.py +0 -0
  63. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/tools/tools_code.py +0 -0
  64. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/tools/tools_config_automations.py +0 -0
  65. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/tools/tools_config_dashboards.py +0 -0
  66. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/tools/tools_config_entry_flow.py +0 -0
  67. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/tools/tools_config_helpers.py +0 -0
  68. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/tools/tools_config_scenes.py +0 -0
  69. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/tools/tools_config_scripts.py +0 -0
  70. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/tools/tools_energy.py +0 -0
  71. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/tools/tools_entities.py +0 -0
  72. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/tools/tools_filesystem.py +0 -0
  73. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/tools/tools_groups.py +0 -0
  74. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/tools/tools_hacs.py +0 -0
  75. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/tools/tools_history.py +0 -0
  76. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/tools/tools_integrations.py +0 -0
  77. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/tools/tools_labels.py +0 -0
  78. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/tools/tools_mcp_component.py +0 -0
  79. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/tools/tools_registry.py +0 -0
  80. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/tools/tools_resources.py +0 -0
  81. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/tools/tools_search.py +0 -0
  82. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/tools/tools_service.py +0 -0
  83. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/tools/tools_services.py +0 -0
  84. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/tools/tools_system.py +0 -0
  85. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/tools/tools_todo.py +0 -0
  86. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/tools/tools_traces.py +0 -0
  87. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/tools/tools_updates.py +0 -0
  88. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/tools/tools_voice_assistant.py +0 -0
  89. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/tools/tools_yaml_config.py +0 -0
  90. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/tools/tools_zones.py +0 -0
  91. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/tools/util_helpers.py +0 -0
  92. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/transforms/__init__.py +0 -0
  93. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/transforms/categorized_search.py +0 -0
  94. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/transforms/lite_docstrings.py +0 -0
  95. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/utils/__init__.py +0 -0
  96. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/utils/config_hash.py +0 -0
  97. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/utils/data_paths.py +0 -0
  98. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/utils/domain_handlers.py +0 -0
  99. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/utils/fuzzy_search.py +0 -0
  100. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/utils/kill_signal_diagnostics.py +0 -0
  101. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/utils/operation_manager.py +0 -0
  102. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/utils/python_sandbox.py +0 -0
  103. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp/utils/usage_logger.py +0 -0
  104. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp_dev.egg-info/SOURCES.txt +0 -0
  105. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp_dev.egg-info/dependency_links.txt +0 -0
  106. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp_dev.egg-info/entry_points.txt +0 -0
  107. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp_dev.egg-info/requires.txt +0 -0
  108. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/src/ha_mcp_dev.egg-info/top_level.txt +0 -0
  109. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/tests/__init__.py +0 -0
  110. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/tests/test_constants.py +0 -0
  111. {ha_mcp_dev-7.4.1.dev504 → ha_mcp_dev-7.5.0.dev507}/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.dev504
3
+ Version: 7.5.0.dev507
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.dev504"
7
+ version = "7.5.0.dev507"
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"
@@ -527,7 +527,7 @@ class HomeAssistantClient:
527
527
 
528
528
  - ``"addons/<slug>"`` for add-on container logs
529
529
  - ``"<service>"`` (where service ∈ {supervisor, host, core, dns, audio,
530
- multicast, observer}) for system-service logs
530
+ cli, multicast, observer}) for system-service logs
531
531
 
532
532
  Bypasses ``HomeAssistantClient.httpx_client`` because the Supervisor
533
533
  endpoint uses a different base URL (``http://supervisor``) and a
@@ -645,18 +645,42 @@ class HomeAssistantClient:
645
645
  return await self._supervisor_logs_get(f"addons/{slug}")
646
646
 
647
647
  async def _get_system_service_logs(self, service: str) -> str:
648
- """Fetch HA system-service logs directly from Supervisor's REST API.
649
-
650
- Hits ``http://supervisor/{service}/logs``. ``service`` must be one of
651
- the seven Supervisor-managed services: ``supervisor``, ``host``,
652
- ``core``, ``dns``, ``audio``, ``multicast``, ``observer``. Caller is
653
- responsible for validating ``service`` against the allowed set; this
654
- helper does no validation and will raise ``HomeAssistantAPIError`` on
655
- any unknown path (404 from Supervisor).
656
-
657
- Requires ``hassio_role: manager`` like the addon-logs path.
648
+ """Fetch HA system-service logs.
649
+
650
+ ``service`` must be one of the eight Supervisor-managed services:
651
+ ``supervisor``, ``host``, ``core``, ``dns``, ``audio``, ``cli``,
652
+ ``multicast``, ``observer``. Caller is responsible for validating
653
+ ``service`` against the allowed set; this helper does no validation
654
+ and will raise ``HomeAssistantAPIError`` on any unknown path (404).
655
+
656
+ Branch on ``is_running_in_addon()`` — mirror of ``get_addon_logs``:
657
+ inside the addon container goes directly to Supervisor at
658
+ ``http://supervisor/{service}/logs`` with the Supervisor token
659
+ (``hassio_role: manager`` required). On non-addon installs (Docker
660
+ without Supervisor, pyinstaller, pip pointing at a normal HA URL),
661
+ falls back to the HA Core proxy at ``/api/hassio/{service}/logs``.
662
+
663
+ All seven slugs are whitelisted in HA Core's hassio proxy
664
+ (``homeassistant/components/hassio/http.py`` — ``PATHS_ADMIN``), so
665
+ an admin LLA is sufficient to reach any of them from outside the
666
+ addon.
667
+
668
+ Closes #1260: pre-fix this method had only the addon-direct branch,
669
+ so non-addon installs (the Docker image, uvx ha-mcp, etc.) hit the
670
+ ``SUPERVISOR_TOKEN``-absent fail-fast in ``_supervisor_logs_get`` for
671
+ every service, while the sibling ``source="supervisor"`` (addon
672
+ logs) call kept working through its own Core-proxy fallback.
658
673
  """
659
- return await self._supervisor_logs_get(service)
674
+ if is_running_in_addon():
675
+ return await self._supervisor_logs_get(service)
676
+
677
+ logger.debug(f"Fetching {service} logs via HA Core proxy")
678
+ response = await self._raw_request(
679
+ "GET",
680
+ f"/hassio/{service}/logs",
681
+ headers={"Accept": "text/plain"},
682
+ )
683
+ return response.text
660
684
 
661
685
  async def test_connection(self) -> tuple[bool, str | None]:
662
686
  """
@@ -12,6 +12,7 @@ from typing import Any, Literal
12
12
 
13
13
  from fastmcp.exceptions import ToolError
14
14
 
15
+ from .._version import is_running_in_addon
15
16
  from ..client.rest_client import (
16
17
  HomeAssistantAPIError,
17
18
  HomeAssistantAuthError,
@@ -42,11 +43,12 @@ COMPACT_LOGBOOK_FIELDS = {
42
43
  }
43
44
 
44
45
 
45
- # Supervisor-managed system services exposed via /<slug>/logs. Stable set
46
- # in HA Core; if Supervisor adds e.g. /cli/logs in a future release, extend
47
- # here. See #1116.
46
+ # Supervisor-managed system services exposed via /<slug>/logs. Set mirrors
47
+ # HA Core's hassio HTTP proxy ``PATHS_ADMIN`` whitelist in
48
+ # ``homeassistant/components/hassio/http.py``. See #1116 (original 7-service
49
+ # scope) and #1260 (cli added — proxy supported it the whole time).
48
50
  SYSTEM_SERVICE_SLUGS = frozenset(
49
- {"supervisor", "host", "core", "dns", "audio", "multicast", "observer"}
51
+ {"supervisor", "host", "core", "dns", "audio", "cli", "multicast", "observer"}
50
52
  )
51
53
 
52
54
 
@@ -145,7 +147,7 @@ def register_utility_tools(mcp: Any, client: Any, **kwargs: Any) -> None:
145
147
  - "error_log": Raw home-assistant.log text
146
148
  - "supervisor": Add-on container logs (requires slug = add-on slug)
147
149
  - "system_service": HA-Supervisor-managed system service logs (requires
148
- slug ∈ {supervisor, host, core, dns, audio, multicast, observer})
150
+ slug ∈ {supervisor, host, core, dns, audio, cli, multicast, observer})
149
151
  - "logger": Effective log level per integration via logger/log_info (confirms logger.set_level changes took effect)
150
152
 
151
153
  **Shared params:** limit, search (keyword filter on entries/lines; matches integration domain for source='logger')
@@ -762,15 +764,29 @@ def register_utility_tools(mcp: Any, client: Any, **kwargs: Any) -> None:
762
764
  except HomeAssistantAuthError as e:
763
765
  # Listed before HomeAssistantAPIError because AuthError is a sibling,
764
766
  # not a subclass — without this explicit clause the 401 from
765
- # _supervisor_logs_get propagates raw to FastMCP and surfaces
766
- # without a structured `code` field.
767
+ # _supervisor_logs_get / _raw_request propagates raw to FastMCP and
768
+ # surfaces without a structured `code` field.
769
+ #
770
+ # Suggestions branch on is_running_in_addon(): addon installs go
771
+ # direct to Supervisor (the failure mode is a missing/rotated
772
+ # SUPERVISOR_TOKEN), non-addon installs hit HA Core's hassio
773
+ # proxy with the user's LLA (the failure mode is a non-admin or
774
+ # expired LLA — SUPERVISOR_TOKEN doesn't even apply).
775
+ if is_running_in_addon():
776
+ suggestions = [
777
+ "Verify SUPERVISOR_TOKEN is set correctly inside the add-on",
778
+ "Reinstall the add-on if the token may have rotated",
779
+ ]
780
+ else:
781
+ suggestions = [
782
+ "Verify HOMEASSISTANT_TOKEN is a valid admin Long-Lived "
783
+ "Access Token (Settings → Profile → Long-Lived Access Tokens)",
784
+ "Re-create the LLAT if it has expired or been revoked",
785
+ ]
767
786
  exception_to_structured_error(
768
787
  e,
769
788
  context={"source": "supervisor", "slug": slug},
770
- suggestions=[
771
- "Verify SUPERVISOR_TOKEN is set correctly inside the add-on",
772
- "Reinstall the add-on if the token may have rotated",
773
- ],
789
+ suggestions=suggestions,
774
790
  )
775
791
  except HomeAssistantAPIError as e:
776
792
  status = getattr(e, "status_code", None)
@@ -832,13 +848,15 @@ def register_utility_tools(mcp: Any, client: Any, **kwargs: Any) -> None:
832
848
  ) -> dict[str, Any]:
833
849
  """Fetch HA system-service logs from Supervisor's per-service endpoint.
834
850
 
835
- ``service`` ∈ {supervisor, host, core, dns, audio, multicast, observer}.
851
+ ``service`` ∈ ``SYSTEM_SERVICE_SLUGS`` (the eight Supervisor-managed
852
+ services: supervisor, host, core, dns, audio, cli, multicast, observer).
836
853
  Caller (``ha_get_logs(source='system_service')``) validates against
837
- ``SYSTEM_SERVICE_SLUGS`` before dispatch. Hits
838
- ``http://supervisor/<service>/logs`` directly via
839
- ``HomeAssistantClient._get_system_service_logs`` same direct-Supervisor
840
- path #1116's add-on fix uses, just with a different URL prefix.
841
- Requires ``hassio_role: manager`` in the addon manifest.
854
+ ``SYSTEM_SERVICE_SLUGS`` before dispatch. Routed through
855
+ ``HomeAssistantClient._get_system_service_logs`` which gates on
856
+ ``is_running_in_addon()``: addon installs hit Supervisor directly at
857
+ ``http://supervisor/<service>/logs`` (requires ``hassio_role: manager``
858
+ in the addon manifest), non-addon installs fall back to the HA Core
859
+ proxy at ``/api/hassio/<service>/logs`` (requires an admin LLA).
842
860
  """
843
861
  effective_limit = _coerce_limit(
844
862
  limit, default=DEFAULT_LOG_LIMIT, suggestion_example="100"
@@ -877,29 +895,53 @@ def register_utility_tools(mcp: Any, client: Any, **kwargs: Any) -> None:
877
895
  except HomeAssistantAuthError as e:
878
896
  # Listed before HomeAssistantAPIError because AuthError is a sibling,
879
897
  # not a subclass — without this explicit clause the 401 from
880
- # _supervisor_logs_get propagates raw to FastMCP and surfaces
881
- # without a structured `code` field.
898
+ # _supervisor_logs_get / _raw_request propagates raw to FastMCP and
899
+ # surfaces without a structured `code` field.
900
+ #
901
+ # Suggestions branch on is_running_in_addon() (see _get_supervisor_log
902
+ # for the rationale): SUPERVISOR_TOKEN suggestions only make sense
903
+ # inside the addon container; non-addon installs need admin-LLA hints.
904
+ if is_running_in_addon():
905
+ suggestions = [
906
+ "Verify SUPERVISOR_TOKEN is set correctly inside the add-on",
907
+ "Reinstall the add-on if the token may have rotated",
908
+ ]
909
+ else:
910
+ suggestions = [
911
+ "Verify HOMEASSISTANT_TOKEN is a valid admin Long-Lived "
912
+ "Access Token (Settings → Profile → Long-Lived Access Tokens)",
913
+ "Re-create the LLAT if it has expired or been revoked",
914
+ ]
882
915
  exception_to_structured_error(
883
916
  e,
884
917
  context={"source": "system_service", "slug": service},
885
- suggestions=[
886
- "Verify SUPERVISOR_TOKEN is set correctly inside the add-on",
887
- "Reinstall the add-on if the token may have rotated",
888
- ],
918
+ suggestions=suggestions,
889
919
  )
890
920
  except HomeAssistantAPIError as e:
891
921
  status = getattr(e, "status_code", None)
892
922
  if status == 403:
893
- # Same role-too-low cause as the addon-logs branch.
894
- exception_to_structured_error(
895
- e,
896
- context={"source": "system_service", "slug": service},
897
- suggestions=[
923
+ # In-addon: Supervisor returns 403 when the addon's hassio_role
924
+ # is below 'manager'. Non-addon: HA Core's hassio proxy returns
925
+ # 403 when the LLA's user lacks admin — completely different
926
+ # remediation. Branch on the gate accordingly.
927
+ if is_running_in_addon():
928
+ suggestions = [
898
929
  "Addon's hassio_role must be 'manager' or higher to "
899
930
  "read /<service>/logs",
900
931
  "Verify the addon was reinstalled after the role bump "
901
932
  "took effect",
902
- ],
933
+ ]
934
+ else:
935
+ suggestions = [
936
+ "The Long-Lived Access Token must belong to a user "
937
+ "with admin privileges",
938
+ "Generate a new LLAT under an admin account and set "
939
+ "HOMEASSISTANT_TOKEN to it",
940
+ ]
941
+ exception_to_structured_error(
942
+ e,
943
+ context={"source": "system_service", "slug": service},
944
+ suggestions=suggestions,
903
945
  )
904
946
  if status == 404:
905
947
  exception_to_structured_error(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ha-mcp-dev
3
- Version: 7.4.1.dev504
3
+ Version: 7.5.0.dev507
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