ha-mcp-dev 7.0.0.dev280__tar.gz → 7.1.0.dev283__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 (95) hide show
  1. {ha_mcp_dev-7.0.0.dev280/src/ha_mcp_dev.egg-info → ha_mcp_dev-7.1.0.dev283}/PKG-INFO +1 -1
  2. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/pyproject.toml +1 -1
  3. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/__init__.py +1 -1
  4. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/tools/tools_config_helpers.py +71 -29
  5. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283/src/ha_mcp_dev.egg-info}/PKG-INFO +1 -1
  6. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/LICENSE +0 -0
  7. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/MANIFEST.in +0 -0
  8. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/README.md +0 -0
  9. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/setup.cfg +0 -0
  10. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/__main__.py +0 -0
  11. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/_pypi_marker +0 -0
  12. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/auth/__init__.py +0 -0
  13. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/auth/consent_form.py +0 -0
  14. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/auth/provider.py +0 -0
  15. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/client/__init__.py +0 -0
  16. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/client/rest_client.py +0 -0
  17. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/client/websocket_client.py +0 -0
  18. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/client/websocket_listener.py +0 -0
  19. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/config.py +0 -0
  20. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/errors.py +0 -0
  21. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/py.typed +0 -0
  22. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/resources/card_types.json +0 -0
  23. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/resources/dashboard_guide.md +0 -0
  24. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/resources/skills-vendor/.claude/settings.json +0 -0
  25. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/resources/skills-vendor/.claude-plugin/marketplace.json +0 -0
  26. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/resources/skills-vendor/.claude-plugin/plugin.json +0 -0
  27. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/resources/skills-vendor/.github/ISSUE_TEMPLATE/skill-rca.md +0 -0
  28. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/resources/skills-vendor/AGENTS.md +0 -0
  29. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/resources/skills-vendor/CLAUDE.md +0 -0
  30. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/resources/skills-vendor/CONTRIBUTING.md +0 -0
  31. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/resources/skills-vendor/LICENSE +0 -0
  32. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/resources/skills-vendor/README.md +0 -0
  33. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/SKILL.md +0 -0
  34. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/automation-patterns.md +0 -0
  35. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/device-control.md +0 -0
  36. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/examples.yaml +0 -0
  37. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/helper-selection.md +0 -0
  38. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/safe-refactoring.md +0 -0
  39. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/resources/skills-vendor/skills/home-assistant-best-practices/references/template-guidelines.md +0 -0
  40. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/server.py +0 -0
  41. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/smoke_test.py +0 -0
  42. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/tools/__init__.py +0 -0
  43. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/tools/backup.py +0 -0
  44. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/tools/best_practice_checker.py +0 -0
  45. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/tools/device_control.py +0 -0
  46. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/tools/enhanced.py +0 -0
  47. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/tools/helpers.py +0 -0
  48. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/tools/registry.py +0 -0
  49. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/tools/smart_search.py +0 -0
  50. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/tools/tools_addons.py +0 -0
  51. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/tools/tools_areas.py +0 -0
  52. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/tools/tools_blueprints.py +0 -0
  53. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/tools/tools_bug_report.py +0 -0
  54. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/tools/tools_calendar.py +0 -0
  55. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/tools/tools_camera.py +0 -0
  56. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/tools/tools_config_automations.py +0 -0
  57. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/tools/tools_config_dashboards.py +0 -0
  58. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/tools/tools_config_entry_flow.py +0 -0
  59. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/tools/tools_config_info.py +0 -0
  60. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/tools/tools_config_scripts.py +0 -0
  61. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/tools/tools_entities.py +0 -0
  62. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/tools/tools_filesystem.py +0 -0
  63. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/tools/tools_groups.py +0 -0
  64. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/tools/tools_hacs.py +0 -0
  65. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/tools/tools_history.py +0 -0
  66. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/tools/tools_integrations.py +0 -0
  67. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/tools/tools_labels.py +0 -0
  68. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/tools/tools_mcp_component.py +0 -0
  69. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/tools/tools_registry.py +0 -0
  70. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/tools/tools_resources.py +0 -0
  71. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/tools/tools_search.py +0 -0
  72. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/tools/tools_service.py +0 -0
  73. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/tools/tools_services.py +0 -0
  74. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/tools/tools_system.py +0 -0
  75. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/tools/tools_todo.py +0 -0
  76. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/tools/tools_traces.py +0 -0
  77. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/tools/tools_updates.py +0 -0
  78. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/tools/tools_utility.py +0 -0
  79. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/tools/tools_voice_assistant.py +0 -0
  80. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/tools/tools_zones.py +0 -0
  81. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/tools/util_helpers.py +0 -0
  82. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/utils/__init__.py +0 -0
  83. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/utils/domain_handlers.py +0 -0
  84. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/utils/fuzzy_search.py +0 -0
  85. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/utils/operation_manager.py +0 -0
  86. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/utils/python_sandbox.py +0 -0
  87. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp/utils/usage_logger.py +0 -0
  88. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp_dev.egg-info/SOURCES.txt +0 -0
  89. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp_dev.egg-info/dependency_links.txt +0 -0
  90. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp_dev.egg-info/entry_points.txt +0 -0
  91. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp_dev.egg-info/requires.txt +0 -0
  92. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/src/ha_mcp_dev.egg-info/top_level.txt +0 -0
  93. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/tests/__init__.py +0 -0
  94. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/tests/test_constants.py +0 -0
  95. {ha_mcp_dev-7.0.0.dev280 → ha_mcp_dev-7.1.0.dev283}/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.0.0.dev280
3
+ Version: 7.1.0.dev283
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.0.0.dev280"
7
+ version = "7.1.0.dev283"
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,7 @@ 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
- __version__ = "7.0.0"
8
+ __version__ = "7.1.0"
9
9
  __author__ = "Julien"
10
10
  __license__ = "MIT"
11
11
 
@@ -25,6 +25,48 @@ from .util_helpers import (
25
25
  logger = logging.getLogger(__name__)
26
26
 
27
27
 
28
+ def _format_schedule_days(
29
+ monday: list | None,
30
+ tuesday: list | None,
31
+ wednesday: list | None,
32
+ thursday: list | None,
33
+ friday: list | None,
34
+ saturday: list | None,
35
+ sunday: list | None,
36
+ ) -> dict[str, list[dict[str, Any]]]:
37
+ """Format schedule day data, ensuring time strings include seconds.
38
+
39
+ Returns a dict of day_name -> formatted time ranges, only for days
40
+ where data was provided (not None).
41
+ """
42
+ day_params = {
43
+ "monday": monday,
44
+ "tuesday": tuesday,
45
+ "wednesday": wednesday,
46
+ "thursday": thursday,
47
+ "friday": friday,
48
+ "saturday": saturday,
49
+ "sunday": sunday,
50
+ }
51
+ formatted_days: dict[str, list[dict[str, Any]]] = {}
52
+ for day_name, day_schedule in day_params.items():
53
+ if day_schedule is not None:
54
+ formatted_ranges = []
55
+ for time_range in day_schedule:
56
+ formatted_range: dict[str, Any] = {}
57
+ for key in ["from", "to"]:
58
+ if key in time_range:
59
+ time_val = time_range[key]
60
+ if isinstance(time_val, str) and time_val.count(":") == 1:
61
+ time_val = f"{time_val}:00"
62
+ formatted_range[key] = time_val
63
+ if "data" in time_range:
64
+ formatted_range["data"] = time_range["data"]
65
+ formatted_ranges.append(formatted_range)
66
+ formatted_days[day_name] = formatted_ranges
67
+ return formatted_days
68
+
69
+
28
70
  def register_config_helper_tools(mcp: Any, client: Any, **kwargs: Any) -> None:
29
71
  """Register Home Assistant helper configuration tools."""
30
72
 
@@ -552,34 +594,10 @@ def register_config_helper_tools(mcp: Any, client: Any, **kwargs: Any) -> None:
552
594
  # Schedule parameters: monday-sunday with time ranges
553
595
  # Each day is a list of {"from": "HH:MM:SS", "to": "HH:MM:SS"}
554
596
  # with optional "data" dict for additional attributes
555
- day_params = {
556
- "monday": monday,
557
- "tuesday": tuesday,
558
- "wednesday": wednesday,
559
- "thursday": thursday,
560
- "friday": friday,
561
- "saturday": saturday,
562
- "sunday": sunday,
563
- }
564
- for day_name, day_schedule in day_params.items():
565
- if day_schedule is not None:
566
- # Ensure time format has seconds
567
- formatted_ranges = []
568
- for time_range in day_schedule:
569
- formatted_range = {}
570
- for key in ["from", "to"]:
571
- if key in time_range:
572
- time_val = time_range[key]
573
- # Add seconds if not present
574
- if time_val.count(":") == 1:
575
- time_val = f"{time_val}:00"
576
- formatted_range[key] = time_val
577
- # Pass through the optional 'data' dict
578
- # for additional attributes (e.g. mode, brightness)
579
- if "data" in time_range:
580
- formatted_range["data"] = time_range["data"]
581
- formatted_ranges.append(formatted_range)
582
- message[day_name] = formatted_ranges
597
+ message.update(_format_schedule_days(
598
+ monday, tuesday, wednesday, thursday,
599
+ friday, saturday, sunday,
600
+ ))
583
601
 
584
602
  elif helper_type == "zone":
585
603
  # Zone parameters - HA validates required fields (latitude, longitude)
@@ -677,7 +695,7 @@ def register_config_helper_tools(mcp: Any, client: Any, **kwargs: Any) -> None:
677
695
  # Person and zone have entity registry entries with unique_id
678
696
  # used as the config store identifier. Tags use their own tag
679
697
  # registry and don't have entity registry entries.
680
- config_store_types = {"person", "zone"}
698
+ config_store_types = {"person", "zone", "schedule"}
681
699
 
682
700
  updated_data: dict[str, Any] = {}
683
701
 
@@ -836,6 +854,30 @@ def register_config_helper_tools(mcp: Any, client: Any, **kwargs: Any) -> None:
836
854
  ))
837
855
  updated_data = result.get("result", {})
838
856
 
857
+ elif helper_type == "schedule":
858
+ update_msg = {
859
+ "type": "schedule/update",
860
+ "schedule_id": unique_id,
861
+ }
862
+ if name is not None:
863
+ update_msg["name"] = name
864
+ if icon is not None:
865
+ update_msg["icon"] = icon
866
+
867
+ update_msg.update(_format_schedule_days(
868
+ monday, tuesday, wednesday, thursday,
869
+ friday, saturday, sunday,
870
+ ))
871
+
872
+ result = await client.send_websocket_message(update_msg)
873
+ if not result.get("success"):
874
+ raise_tool_error(create_error_response(
875
+ ErrorCode.SERVICE_CALL_FAILED,
876
+ f"Failed to update schedule config: {result.get('error', 'Unknown error')}",
877
+ context={"helper_type": helper_type, "entity_id": entity_id},
878
+ ))
879
+ updated_data = result.get("result", {})
880
+
839
881
  # Also update entity registry for icon, area, and labels
840
882
  if icon or area_id or labels:
841
883
  registry_update: dict[str, Any] = {
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ha-mcp-dev
3
- Version: 7.0.0.dev280
3
+ Version: 7.1.0.dev283
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