Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions nextcloud_mcp_server/server/calendar.py
Original file line number Diff line number Diff line change
Expand Up @@ -1104,6 +1104,50 @@ async def nc_calendar_delete_todo(
client = await get_client(ctx)
return await client.calendar.delete_todo(calendar_name, todo_uid)

@mcp.tool(
title="Complete Todo Task",
annotations=ToolAnnotations(idempotentHint=True, openWorldHint=True),
)
@require_scopes("todo.write", "calendar.read")
@instrument_tool
async def nc_calendar_complete_todo(
calendar_name: str,
todo_uid: str,
ctx: Context,
completed_at: Optional[str] = None,
):
"""Mark a todo/task as completed.

Convenience wrapper around nc_calendar_update_todo that sets
STATUS=COMPLETED, PERCENT-COMPLETE=100, and the COMPLETED
timestamp in one call. Equivalent to invoking update_todo with
those three fields populated; useful for AI clients where
"complete this task" is a more natural phrasing than "set status
to COMPLETED, set percent_complete to 100, set completed
timestamp".

Args:
calendar_name: Name of the calendar containing the todo
todo_uid: UID of the todo to mark complete
ctx: MCP context
completed_at: Optional ISO 8601 completion timestamp.
Defaults to the current UTC time if not provided.

Returns:
Dict with the update result.
"""
client = await get_client(ctx)
if completed_at is None:
completed_at = dt.datetime.now(dt.timezone.utc).isoformat()
todo_data = {
"status": "COMPLETED",
"percent_complete": 100,
"completed": completed_at,
}
return await client.calendar.update_todo(
calendar_name, todo_uid, todo_data
)

@mcp.tool(
title="Search Todo Tasks",
annotations=ToolAnnotations(readOnlyHint=True, openWorldHint=True),
Expand Down