ha-mcp-dev 7.3.0.dev397__tar.gz → 7.3.0.dev399__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.
- {ha_mcp_dev-7.3.0.dev397/src/ha_mcp_dev.egg-info → ha_mcp_dev-7.3.0.dev399}/PKG-INFO +1 -1
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/pyproject.toml +1 -1
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/__init__.py +3 -1
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/__main__.py +57 -2
- ha_mcp_dev-7.3.0.dev399/src/ha_mcp/_version.py +58 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/config.py +4 -6
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399/src/ha_mcp_dev.egg-info}/PKG-INFO +1 -1
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp_dev.egg-info/SOURCES.txt +1 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/LICENSE +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/MANIFEST.in +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/README.md +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/setup.cfg +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/_pypi_marker +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/auth/__init__.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/auth/consent_form.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/auth/provider.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/client/__init__.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/client/rest_client.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/client/websocket_client.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/client/websocket_listener.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/errors.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/py.typed +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/resources/skills-vendor/.claude/settings.json +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/resources/skills-vendor/.claude-plugin/marketplace.json +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/resources/skills-vendor/.claude-plugin/plugin.json +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/resources/skills-vendor/.github/ISSUE_TEMPLATE/skill-rca.md +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/resources/skills-vendor/AGENTS.md +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/resources/skills-vendor/CLAUDE.md +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/resources/skills-vendor/CONTRIBUTING.md +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/resources/skills-vendor/LICENSE +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/resources/skills-vendor/README.md +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/SKILL.md +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/evals/evals.json +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/automation-patterns.md +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-cards.md +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/dashboard-guide.md +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/device-control.md +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/domain-docs.md +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/examples.yaml +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/helper-selection.md +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/safe-refactoring.md +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/template-guidelines.md +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/server.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/smoke_test.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/__init__.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/backup.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/best_practice_checker.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/device_control.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/enhanced.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/helpers.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/reference_validator.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/registry.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/smart_search.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/tools_addons.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/tools_areas.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/tools_blueprints.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/tools_bug_report.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/tools_calendar.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/tools_camera.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/tools_categories.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/tools_config_automations.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/tools_config_dashboards.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/tools_config_entry_flow.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/tools_config_helpers.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/tools_config_scripts.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/tools_energy.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/tools_entities.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/tools_filesystem.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/tools_groups.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/tools_hacs.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/tools_history.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/tools_integrations.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/tools_labels.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/tools_mcp_component.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/tools_registry.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/tools_resources.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/tools_search.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/tools_service.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/tools_services.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/tools_system.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/tools_todo.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/tools_traces.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/tools_updates.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/tools_utility.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/tools_voice_assistant.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/tools_yaml_config.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/tools_zones.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/util_helpers.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/transforms/__init__.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/transforms/categorized_search.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/utils/__init__.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/utils/config_hash.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/utils/domain_handlers.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/utils/fuzzy_search.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/utils/operation_manager.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/utils/python_sandbox.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/utils/usage_logger.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp_dev.egg-info/dependency_links.txt +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp_dev.egg-info/entry_points.txt +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp_dev.egg-info/requires.txt +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp_dev.egg-info/top_level.txt +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/tests/__init__.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/tests/test_constants.py +0 -0
- {ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/tests/test_env_manager.py +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "ha-mcp-dev"
|
|
7
|
-
version = "7.3.0.
|
|
7
|
+
version = "7.3.0.dev399"
|
|
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"
|
|
@@ -5,7 +5,9 @@ A Model Context Protocol server that provides complete control over Home Assista
|
|
|
5
5
|
through REST API and WebSocket integration with 20+ enhanced tools.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
from ._version import get_version
|
|
9
|
+
|
|
10
|
+
__version__ = get_version()
|
|
9
11
|
__author__ = "Julien"
|
|
10
12
|
__license__ = "MIT"
|
|
11
13
|
|
|
@@ -30,6 +30,8 @@ import threading # noqa: E402
|
|
|
30
30
|
from collections.abc import Coroutine # noqa: E402
|
|
31
31
|
from typing import TYPE_CHECKING, Any # noqa: E402
|
|
32
32
|
|
|
33
|
+
from fastmcp.exceptions import ToolError # noqa: E402
|
|
34
|
+
from pydantic import ValidationError as PydanticValidationError # noqa: E402
|
|
33
35
|
from starlette.requests import Request # noqa: E402
|
|
34
36
|
from starlette.responses import PlainTextResponse # noqa: E402
|
|
35
37
|
|
|
@@ -281,6 +283,7 @@ def _setup_standard_mode() -> None:
|
|
|
281
283
|
settings = get_settings()
|
|
282
284
|
_validate_standard_credentials(settings)
|
|
283
285
|
_setup_logging(settings.log_level)
|
|
286
|
+
_log_startup_version()
|
|
284
287
|
|
|
285
288
|
|
|
286
289
|
def _http_run_kwargs(transport: str, port: int, path: str) -> dict:
|
|
@@ -365,6 +368,36 @@ class StatelessSessionLogFilter(logging.Filter):
|
|
|
365
368
|
return True
|
|
366
369
|
|
|
367
370
|
|
|
371
|
+
class ToolValidationLogFilter(logging.Filter):
|
|
372
|
+
"""Demote fastmcp tool-failure tracebacks to single-line warnings.
|
|
373
|
+
|
|
374
|
+
Pydantic ValidationError and tool-raised ToolError aren't server bugs,
|
|
375
|
+
so the traceback through fastmcp/pydantic internals is just noise. The
|
|
376
|
+
structured error detail is preserved in the WARNING message; stack is
|
|
377
|
+
intentionally dropped because these are user-input errors, not bugs.
|
|
378
|
+
"""
|
|
379
|
+
|
|
380
|
+
def filter(self, record: logging.LogRecord) -> bool:
|
|
381
|
+
if record.name != "fastmcp.server.server" or not record.exc_info:
|
|
382
|
+
return True
|
|
383
|
+
|
|
384
|
+
msg = record.getMessage()
|
|
385
|
+
err = record.exc_info[1]
|
|
386
|
+
if "Error validating tool" in msg and isinstance(err, PydanticValidationError):
|
|
387
|
+
record.msg = f"{msg}: {err.errors(include_url=False)}"
|
|
388
|
+
elif "Error calling tool" in msg and isinstance(err, ToolError):
|
|
389
|
+
record.msg = f"{msg}: {err}"
|
|
390
|
+
else:
|
|
391
|
+
return True
|
|
392
|
+
|
|
393
|
+
record.args = ()
|
|
394
|
+
record.levelno = logging.WARNING
|
|
395
|
+
record.levelname = "WARNING"
|
|
396
|
+
record.exc_info = None
|
|
397
|
+
record.exc_text = None
|
|
398
|
+
return True
|
|
399
|
+
|
|
400
|
+
|
|
368
401
|
def _setup_logging(log_level_str: str, force: bool = False) -> None:
|
|
369
402
|
"""Configure root logger with consistent timestamp format."""
|
|
370
403
|
logging.basicConfig(
|
|
@@ -376,6 +409,26 @@ def _setup_logging(log_level_str: str, force: bool = False) -> None:
|
|
|
376
409
|
logging.getLogger("mcp.server.streamable_http").addFilter(
|
|
377
410
|
StatelessSessionLogFilter()
|
|
378
411
|
)
|
|
412
|
+
logging.getLogger("fastmcp.server.server").addFilter(ToolValidationLogFilter())
|
|
413
|
+
|
|
414
|
+
|
|
415
|
+
def _log_startup_version() -> None:
|
|
416
|
+
"""Log ha-mcp version at startup, plus a dev-channel banner when relevant.
|
|
417
|
+
|
|
418
|
+
The dev banner only fires for standalone dev installs (Docker ``:dev`` /
|
|
419
|
+
``:latest``, or ``pip install ha-mcp-dev``). It is suppressed under the HA
|
|
420
|
+
Supervisor because add-on users already pick dev vs stable in the HAOS UI.
|
|
421
|
+
"""
|
|
422
|
+
from ha_mcp._version import get_version, is_dev_version, is_running_in_addon
|
|
423
|
+
|
|
424
|
+
version = get_version()
|
|
425
|
+
logger.info(f"ha-mcp {version}")
|
|
426
|
+
if is_dev_version(version) and not is_running_in_addon():
|
|
427
|
+
logger.warning(
|
|
428
|
+
"This is the dev channel. For the stable release use the "
|
|
429
|
+
"'ghcr.io/homeassistant-ai/ha-mcp:stable' Docker tag "
|
|
430
|
+
"(or 'pip install ha-mcp' on PyPI)."
|
|
431
|
+
)
|
|
379
432
|
|
|
380
433
|
|
|
381
434
|
def _get_timestamped_uvicorn_log_config() -> dict:
|
|
@@ -547,9 +600,9 @@ def main() -> None:
|
|
|
547
600
|
"""Run server via CLI using FastMCP's stdio transport."""
|
|
548
601
|
# Handle --version flag early, before server creation requires config
|
|
549
602
|
if "--version" in sys.argv or "-V" in sys.argv:
|
|
550
|
-
from
|
|
603
|
+
from ha_mcp._version import get_version
|
|
551
604
|
|
|
552
|
-
print(f"ha-mcp {
|
|
605
|
+
print(f"ha-mcp {get_version()}")
|
|
553
606
|
sys.exit(0)
|
|
554
607
|
|
|
555
608
|
# Check for smoke test flag
|
|
@@ -572,6 +625,7 @@ def main() -> None:
|
|
|
572
625
|
sys.exit(1)
|
|
573
626
|
|
|
574
627
|
_setup_logging(settings.log_level)
|
|
628
|
+
_log_startup_version()
|
|
575
629
|
|
|
576
630
|
_run_entrypoint(_run_with_graceful_shutdown(), "Server")
|
|
577
631
|
|
|
@@ -747,6 +801,7 @@ def main_oauth() -> None:
|
|
|
747
801
|
for logger_name in ["ha_mcp", "ha_mcp.auth", "ha_mcp.auth.provider"]:
|
|
748
802
|
logging.getLogger(logger_name).setLevel(getattr(logging, log_level))
|
|
749
803
|
logger.info(f"OAuth mode logging configured at {log_level} level")
|
|
804
|
+
_log_startup_version()
|
|
750
805
|
|
|
751
806
|
port, path = _get_http_runtime(default_port=8086)
|
|
752
807
|
base_url = os.getenv("MCP_BASE_URL")
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""Version resolution for the ha-mcp package.
|
|
2
|
+
|
|
3
|
+
Kept as a standalone module (no other ``ha_mcp`` imports) so it can be used from
|
|
4
|
+
``__init__.py`` and ``config.py`` without circular-import risk.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import importlib.metadata
|
|
10
|
+
import logging
|
|
11
|
+
import os
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def get_version() -> str:
|
|
17
|
+
"""Return the installed ha-mcp version.
|
|
18
|
+
|
|
19
|
+
Resolution order:
|
|
20
|
+
1. ``HA_MCP_BUILD_VERSION`` env var — set by Docker/add-on builds that can't
|
|
21
|
+
rewrite ``pyproject.toml`` before install, so the dev suffix still reaches
|
|
22
|
+
the running process. Stable builds leave it unset.
|
|
23
|
+
2. ``ha-mcp`` package metadata — stable PyPI + stable Docker.
|
|
24
|
+
3. ``ha-mcp-dev`` package metadata — PyPI dev channel (renamed package).
|
|
25
|
+
|
|
26
|
+
If none of the above resolve, logs a warning and returns ``"unknown"``.
|
|
27
|
+
The "unknown" string is itself diagnostic in bug reports and startup logs
|
|
28
|
+
— it tells triagers the install didn't register package metadata (e.g. a
|
|
29
|
+
source checkout without ``pip install -e .``, or a broken Docker layer).
|
|
30
|
+
"""
|
|
31
|
+
if override := os.environ.get("HA_MCP_BUILD_VERSION"):
|
|
32
|
+
return override
|
|
33
|
+
for pkg_name in ("ha-mcp", "ha-mcp-dev"):
|
|
34
|
+
try:
|
|
35
|
+
return importlib.metadata.version(pkg_name)
|
|
36
|
+
except importlib.metadata.PackageNotFoundError:
|
|
37
|
+
continue
|
|
38
|
+
logger.warning(
|
|
39
|
+
"ha-mcp package metadata not found and HA_MCP_BUILD_VERSION unset — "
|
|
40
|
+
"version will be reported as 'unknown'. Reinstall the package or set "
|
|
41
|
+
"HA_MCP_BUILD_VERSION if this is an intentional source-tree run."
|
|
42
|
+
)
|
|
43
|
+
return "unknown"
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def is_dev_version(version: str) -> bool:
|
|
47
|
+
"""Return True when the version string contains a PEP 440 ``.dev`` suffix."""
|
|
48
|
+
return ".dev" in version
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def is_running_in_addon() -> bool:
|
|
52
|
+
"""Return True when running inside a Home Assistant add-on container.
|
|
53
|
+
|
|
54
|
+
The HA Supervisor injects ``SUPERVISOR_TOKEN`` into every add-on's env.
|
|
55
|
+
Checked so the standalone-Docker ``:stable`` banner isn't shown to add-on
|
|
56
|
+
users, who already see the dev/stable distinction in the HAOS add-on UI.
|
|
57
|
+
"""
|
|
58
|
+
return bool(os.environ.get("SUPERVISOR_TOKEN"))
|
|
@@ -2,22 +2,20 @@
|
|
|
2
2
|
Configuration management for Home Assistant MCP Server.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
import importlib.metadata
|
|
6
5
|
import os
|
|
7
6
|
|
|
8
7
|
# Load environment variables from .env file with HAMCP_ENV_FILE support
|
|
9
8
|
# Use absolute path to ensure .env is found regardless of cwd
|
|
10
9
|
from pathlib import Path
|
|
11
10
|
|
|
12
|
-
try:
|
|
13
|
-
_PACKAGE_VERSION = importlib.metadata.version("ha-mcp")
|
|
14
|
-
except importlib.metadata.PackageNotFoundError:
|
|
15
|
-
_PACKAGE_VERSION = "unknown"
|
|
16
|
-
|
|
17
11
|
from dotenv import load_dotenv
|
|
18
12
|
from pydantic import Field, field_validator, model_validator
|
|
19
13
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
20
14
|
|
|
15
|
+
from ha_mcp._version import get_version
|
|
16
|
+
|
|
17
|
+
_PACKAGE_VERSION = get_version()
|
|
18
|
+
|
|
21
19
|
project_root = Path(__file__).parent.parent.parent
|
|
22
20
|
|
|
23
21
|
# Demo environment token - use HOMEASSISTANT_TOKEN="demo" to connect to the public demo
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/resources/skills-vendor/AGENTS.md
RENAMED
|
File without changes
|
{ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/resources/skills-vendor/CLAUDE.md
RENAMED
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/resources/skills-vendor/LICENSE
RENAMED
|
File without changes
|
{ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/resources/skills-vendor/README.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/best_practice_checker.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/tools_config_automations.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/tools_config_dashboards.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/tools_config_entry_flow.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/tools_config_helpers.py
RENAMED
|
File without changes
|
{ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/tools_config_scripts.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/tools/tools_voice_assistant.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp/transforms/categorized_search.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp_dev.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{ha_mcp_dev-7.3.0.dev397 → ha_mcp_dev-7.3.0.dev399}/src/ha_mcp_dev.egg-info/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|