Skip to content

Commit 1fe6418

Browse files
Merge branch 'master' into docs/fields-projection-docstring-completeness
2 parents 8714f89 + e2067e4 commit 1fe6418

4 files changed

Lines changed: 228 additions & 57 deletions

File tree

homeassistant-addon-dev/config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: "Home Assistant MCP Server (Dev)"
22
description: "Development channel - AI assistant integration via MCP (unstable)"
3-
version: "7.5.0.dev346"
3+
version: "7.5.0.dev347"
44
slug: "ha_mcp_dev"
55
url: "https://github.com/homeassistant-ai/ha-mcp"
66
stage: experimental

site/src/data/tools.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -529,7 +529,7 @@
529529
{
530530
"name": "ha_config_remove_calendar_event",
531531
"title": "Remove Calendar Event",
532-
"description": "Delete an event from a calendar.\n\nDeletes a calendar event using the calendar.delete_event service.\n\n**Parameters:**\n- entity_id: Calendar entity ID (e.g., 'calendar.family')\n- uid: Unique identifier of the event to delete\n- recurrence_id: Optional recurrence ID for recurring events\n- recurrence_range: Optional recurrence range ('THIS_AND_FUTURE' to delete this and future occurrences)\n\n**Example Usage:**\n```python\n# Delete a single event\nresult = ha_config_remove_calendar_event(\n \"calendar.family\",\n uid=\"event-12345\"\n)\n\n# Delete a recurring event instance and future occurrences\nresult = ha_config_remove_calendar_event(\n \"calendar.work\",\n uid=\"recurring-event-67890\",\n recurrence_id=\"20240115T100000\",\n recurrence_range=\"THIS_AND_FUTURE\"\n)\n```\n\n**Note:**\nTo get the event UID, first use ha_config_get_calendar_events() to list events.\nThe UID is returned in each event's data.\n\n**Returns:**\n- Success status and deletion confirmation",
532+
"description": "Delete an event from a calendar.\n\nDeletes a calendar event via the WebSocket ``calendar/event/delete``\ncommand. HA's calendar component only registers ``create_event`` and\n``get_events`` as REST services — delete and update live on the\nWebSocket API only.\n\n**Parameters:**\n- entity_id: Calendar entity ID (e.g., 'calendar.family')\n- uid: Unique identifier of the event to delete\n- recurrence_id: Optional recurrence ID for recurring events\n- recurrence_range: Optional recurrence range ('THIS_AND_FUTURE' to delete this and future occurrences)\n\n**Example Usage:**\n```python\n# Delete a single event\nresult = ha_config_remove_calendar_event(\n \"calendar.family\",\n uid=\"event-12345\"\n)\n\n# Delete a recurring event instance and future occurrences\nresult = ha_config_remove_calendar_event(\n \"calendar.work\",\n uid=\"recurring-event-67890\",\n recurrence_id=\"20240115T100000\",\n recurrence_range=\"THIS_AND_FUTURE\"\n)\n```\n\n**Note:**\nTo get the event UID, first use ha_config_get_calendar_events() to list events.\nThe UID is returned in each event's data.\n\n**Returns:**\n- Success status and deletion confirmation",
533533
"inputSchema": {
534534
"properties": {
535535
"entity_id": {

src/ha_mcp/tools/tools_calendar.py

Lines changed: 43 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from .auto_backup import with_auto_backup
2020
from .helpers import (
2121
exception_to_structured_error,
22+
get_connected_ws_client,
2223
log_tool_usage,
2324
raise_tool_error,
2425
register_tool_methods,
@@ -354,7 +355,10 @@ async def ha_config_remove_calendar_event(
354355
"""
355356
Delete an event from a calendar.
356357
357-
Deletes a calendar event using the calendar.delete_event service.
358+
Deletes a calendar event via the WebSocket ``calendar/event/delete``
359+
command. HA's calendar component only registers ``create_event`` and
360+
``get_events`` as REST services — delete and update live on the
361+
WebSocket API only.
358362
359363
**Parameters:**
360364
- entity_id: Calendar entity ID (e.g., 'calendar.family')
@@ -402,8 +406,8 @@ async def ha_config_remove_calendar_event(
402406
)
403407

404408
# entity_id format-check above does not cover the ``uid`` parameter.
405-
# Empty/whitespace uid would flow through to ``calendar.delete_event``
406-
# and HA returns a misleading "event not found".
409+
# Empty/whitespace uid would flow through to the WS command and HA
410+
# returns a misleading "event not found".
407411
validate_identifier_not_empty(
408412
uid,
409413
"uid",
@@ -413,21 +417,46 @@ async def ha_config_remove_calendar_event(
413417
context={"entity_id": entity_id},
414418
)
415419

416-
# Build service data
417-
service_data: dict[str, Any] = {
418-
"entity_id": entity_id,
419-
"uid": uid,
420-
}
421-
420+
# ``calendar.delete_event`` is NOT a REST service — HA only
421+
# registers ``calendar.create_event`` and ``calendar.get_events``.
422+
# Delete is exposed exclusively via the WebSocket command
423+
# ``calendar/event/delete`` (see HA Core
424+
# ``homeassistant/components/calendar/__init__.py``).
425+
ws_kwargs: dict[str, Any] = {"entity_id": entity_id, "uid": uid}
422426
if recurrence_id:
423-
service_data["recurrence_id"] = recurrence_id
427+
ws_kwargs["recurrence_id"] = recurrence_id
424428
if recurrence_range:
425-
service_data["recurrence_range"] = recurrence_range
429+
ws_kwargs["recurrence_range"] = recurrence_range
426430

427-
# Call the calendar.delete_event service
428-
result = await self._client.call_service(
429-
"calendar", "delete_event", service_data
431+
ws_client, conn_error = await get_connected_ws_client(
432+
self._client.base_url,
433+
self._client.token,
434+
verify_ssl=self._client.verify_ssl,
430435
)
436+
if conn_error or ws_client is None:
437+
raise_tool_error(
438+
conn_error
439+
or create_error_response(
440+
ErrorCode.CONNECTION_FAILED,
441+
"Failed to connect to Home Assistant WebSocket",
442+
context={"entity_id": entity_id, "uid": uid},
443+
)
444+
)
445+
446+
try:
447+
result = await ws_client.send_command(
448+
"calendar/event/delete", **ws_kwargs
449+
)
450+
finally:
451+
# Guard disconnect: a transport-teardown error here would
452+
# otherwise replace the original send_command exception.
453+
try:
454+
await ws_client.disconnect()
455+
except Exception as disconnect_error:
456+
logger.debug(
457+
f"WebSocket disconnect after delete_event for "
458+
f"{entity_id} uid={uid}: {disconnect_error}"
459+
)
431460

432461
return {
433462
"success": True,

0 commit comments

Comments
 (0)