update_todo
Update an existing todo's properties: title, notes, schedule, deadline, tags, completion status, or move it to another project or heading.
Instructions
Update an existing todo in Things
Args: id: ID of the todo to update title: New title notes: New notes when: New schedule (today, tomorrow, evening, anytime, someday, or YYYY-MM-DD). Use YYYY-MM-DD@HH:MM format to add a reminder (e.g., 2024-01-15@14:30) deadline: New deadline (YYYY-MM-DD) tags: New tags completed: Mark as completed canceled: Mark as canceled list: The title of a project or area to move the to-do into list_id: The ID of a project or area to move the to-do into (takes precedence over list) heading: The heading title to move the to-do under heading_id: The heading ID to move the to-do under (takes precedence over heading)
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | ||
| title | No | ||
| notes | No | ||
| when | No | ||
| deadline | No | ||
| tags | No | ||
| completed | No | ||
| canceled | No | ||
| list | No | ||
| list_id | No | ||
| heading | No | ||
| heading_id | No |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| result | Yes |
Implementation Reference
- src/things_mcp/server.py:428-475 (handler)The MCP tool handler function 'update_todo' decorated with @mcp.tool that accepts parameters (id, title, notes, when, deadline, tags, completed, canceled, list, list_id, heading, heading_id), calls url_scheme.update_todo() to build the Things URL, executes it, and returns a confirmation string.
@mcp.tool async def update_todo( id: str, title: str = None, notes: str = None, when: str = None, deadline: str = None, tags: List[str] = None, completed: bool = None, canceled: bool = None, list: str = None, list_id: str = None, heading: str = None, heading_id: str = None ) -> str: """Update an existing todo in Things Args: id: ID of the todo to update title: New title notes: New notes when: New schedule (today, tomorrow, evening, anytime, someday, or YYYY-MM-DD). Use YYYY-MM-DD@HH:MM format to add a reminder (e.g., 2024-01-15@14:30) deadline: New deadline (YYYY-MM-DD) tags: New tags completed: Mark as completed canceled: Mark as canceled list: The title of a project or area to move the to-do into list_id: The ID of a project or area to move the to-do into (takes precedence over list) heading: The heading title to move the to-do under heading_id: The heading ID to move the to-do under (takes precedence over heading) """ url = url_scheme.update_todo( id=id, title=title, notes=notes, when=when, deadline=deadline, tags=tags, completed=completed, canceled=canceled, list=list, list_id=list_id, heading=heading, heading_id=heading_id ) url_scheme.execute_url(url) return f"Updated todo with ID: {id}" - src/things_mcp/url_scheme.py:150-189 (helper)The URL construction helper function 'update_todo' that builds a Things URL for updating an existing todo. Accepts all update parameters, constructs params dict, and calls construct_url('update', ...) with non-None values.
def update_todo(id: str, title: Optional[str] = None, notes: Optional[str] = None, when: Optional[str] = None, deadline: Optional[str] = None, tags: Optional[list[str]] = None, completed: Optional[bool] = None, canceled: Optional[bool] = None, list: Optional[str] = None, list_id: Optional[str] = None, heading: Optional[str] = None, heading_id: Optional[str] = None) -> str: """Construct URL to update an existing todo. Args: id: UUID of the todo to update title: New title notes: New notes when: Reschedule the todo. Accepts: - Keywords: "today", "tomorrow", "evening", "anytime", "someday" - Date: "yyyy-mm-dd" or natural language ("in 3 days", "next tuesday") - DateTime (adds reminder): "yyyy-mm-dd@HH:MM" (e.g., "2024-01-15@14:30") deadline: New deadline (yyyy-mm-dd) tags: New tags (replaces existing) completed: Mark as completed canceled: Mark as canceled list: Title of project/area to move to list_id: UUID of project/area to move to (takes precedence over list) heading: Heading title to move under heading_id: UUID of heading to move under (takes precedence over heading) """ params = { 'id': id, 'title': title, 'notes': notes, 'when': when, 'deadline': deadline, 'tags': tags, 'completed': completed, 'canceled': canceled, 'list': list, 'list-id': list_id, 'heading': heading, 'heading-id': heading_id } return construct_url('update', {k: v for k, v in params.items() if v is not None}) - src/things_mcp/server.py:19-19 (registration)The FastMCP server instance 'mcp = FastMCP("Things")' which handles the @mcp.tool decorator that registers the update_todo function as an MCP tool.
mcp = FastMCP("Things") - tests/test_url_scheme.py:174-215 (helper)Tests for the update_todo URL construction helper, covering minimal parameters and all parameters including tags, boolean flags, list/heading IDs.
class TestUpdateTodo: """Test the update_todo function.""" @patch('things.token') def test_update_todo_minimal(self, mock_token): """Test updating todo with minimal parameters.""" mock_token.return_value = "auth-token" url = update_todo("todo-123") assert "id=todo-123" in url assert "auth-token=auth-token" in url @patch('things.token') def test_update_todo_full(self, mock_token): """Test updating todo with all parameters.""" mock_token.return_value = "auth-token" url = update_todo( id="todo-123", title="Updated Title", notes="Updated notes", when="tomorrow", deadline="2024-02-01", tags=["updated", "tag"], completed=True, canceled=False, list="Inbox", list_id="inbox-id", heading="New Heading", heading_id="heading-uuid" ) assert "id=todo-123" in url assert "title=Updated%20Title" in url assert "notes=Updated%20notes" in url assert "when=tomorrow" in url assert "deadline=2024-02-01" in url assert "tags=updated%2Ctag" in url assert "completed=true" in url assert "canceled=false" in url assert "list=Inbox" in url assert "list-id=inbox-id" in url assert "heading=New%20Heading" in url assert "heading-id=heading-uuid" in url