Add todo item management functionality
- Add create, update, delete, complete, and uncomplete methods to basecamp_client.py - Add tool definitions and execution logic to mcp_server_cli.py - Add async todo management functions to basecamp_fastmcp.py - Support all optional fields: description, assignees, due dates, notifications - Use lambda wrapper for proper keyword argument handling in FastMCP 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -159,6 +159,141 @@ class BasecampClient:
|
||||
else:
|
||||
raise Exception(f"Failed to get todo: {response.status_code} - {response.text}")
|
||||
|
||||
def create_todo(self, project_id, todolist_id, content, description=None, assignee_ids=None,
|
||||
completion_subscriber_ids=None, notify=False, due_on=None, starts_on=None):
|
||||
"""
|
||||
Create a new todo item in a todolist.
|
||||
|
||||
Args:
|
||||
project_id (str): Project ID
|
||||
todolist_id (str): Todolist ID
|
||||
content (str): The todo item's text (required)
|
||||
description (str, optional): HTML description
|
||||
assignee_ids (list, optional): List of person IDs to assign
|
||||
completion_subscriber_ids (list, optional): List of person IDs to notify on completion
|
||||
notify (bool, optional): Whether to notify assignees
|
||||
due_on (str, optional): Due date in YYYY-MM-DD format
|
||||
starts_on (str, optional): Start date in YYYY-MM-DD format
|
||||
|
||||
Returns:
|
||||
dict: The created todo
|
||||
"""
|
||||
endpoint = f'buckets/{project_id}/todolists/{todolist_id}/todos.json'
|
||||
data = {'content': content}
|
||||
|
||||
if description:
|
||||
data['description'] = description
|
||||
if assignee_ids:
|
||||
data['assignee_ids'] = assignee_ids
|
||||
if completion_subscriber_ids:
|
||||
data['completion_subscriber_ids'] = completion_subscriber_ids
|
||||
if notify:
|
||||
data['notify'] = notify
|
||||
if due_on:
|
||||
data['due_on'] = due_on
|
||||
if starts_on:
|
||||
data['starts_on'] = starts_on
|
||||
|
||||
response = self.post(endpoint, data)
|
||||
if response.status_code == 201:
|
||||
return response.json()
|
||||
else:
|
||||
raise Exception(f"Failed to create todo: {response.status_code} - {response.text}")
|
||||
|
||||
def update_todo(self, project_id, todo_id, content=None, description=None, assignee_ids=None,
|
||||
completion_subscriber_ids=None, due_on=None, starts_on=None):
|
||||
"""
|
||||
Update an existing todo item.
|
||||
|
||||
Args:
|
||||
project_id (str): Project ID
|
||||
todo_id (str): Todo ID
|
||||
content (str, optional): The todo item's text
|
||||
description (str, optional): HTML description
|
||||
assignee_ids (list, optional): List of person IDs to assign
|
||||
completion_subscriber_ids (list, optional): List of person IDs to notify on completion
|
||||
due_on (str, optional): Due date in YYYY-MM-DD format
|
||||
starts_on (str, optional): Start date in YYYY-MM-DD format
|
||||
|
||||
Returns:
|
||||
dict: The updated todo
|
||||
"""
|
||||
endpoint = f'buckets/{project_id}/todos/{todo_id}.json'
|
||||
data = {}
|
||||
|
||||
if content:
|
||||
data['content'] = content
|
||||
if description:
|
||||
data['description'] = description
|
||||
if assignee_ids:
|
||||
data['assignee_ids'] = assignee_ids
|
||||
if completion_subscriber_ids:
|
||||
data['completion_subscriber_ids'] = completion_subscriber_ids
|
||||
if due_on:
|
||||
data['due_on'] = due_on
|
||||
if starts_on:
|
||||
data['starts_on'] = starts_on
|
||||
|
||||
response = self.put(endpoint, data)
|
||||
if response.status_code == 200:
|
||||
return response.json()
|
||||
else:
|
||||
raise Exception(f"Failed to update todo: {response.status_code} - {response.text}")
|
||||
|
||||
def delete_todo(self, project_id, todo_id):
|
||||
"""
|
||||
Delete a todo item.
|
||||
|
||||
Args:
|
||||
project_id (str): Project ID
|
||||
todo_id (str): Todo ID
|
||||
|
||||
Returns:
|
||||
bool: True if successful
|
||||
"""
|
||||
endpoint = f'buckets/{project_id}/todos/{todo_id}.json'
|
||||
response = self.delete(endpoint)
|
||||
if response.status_code == 204:
|
||||
return True
|
||||
else:
|
||||
raise Exception(f"Failed to delete todo: {response.status_code} - {response.text}")
|
||||
|
||||
def complete_todo(self, project_id, todo_id):
|
||||
"""
|
||||
Mark a todo as complete.
|
||||
|
||||
Args:
|
||||
project_id (str): Project ID
|
||||
todo_id (str): Todo ID
|
||||
|
||||
Returns:
|
||||
dict: Completion details
|
||||
"""
|
||||
endpoint = f'buckets/{project_id}/todos/{todo_id}/completion.json'
|
||||
response = self.post(endpoint)
|
||||
if response.status_code == 201:
|
||||
return response.json()
|
||||
else:
|
||||
raise Exception(f"Failed to complete todo: {response.status_code} - {response.text}")
|
||||
|
||||
def uncomplete_todo(self, project_id, todo_id):
|
||||
"""
|
||||
Mark a todo as incomplete.
|
||||
|
||||
Args:
|
||||
project_id (str): Project ID
|
||||
todo_id (str): Todo ID
|
||||
|
||||
Returns:
|
||||
bool: True if successful
|
||||
"""
|
||||
endpoint = f'buckets/{project_id}/todos/{todo_id}/completion.json'
|
||||
response = self.delete(endpoint)
|
||||
if response.status_code == 204:
|
||||
return True
|
||||
else:
|
||||
raise Exception(f"Failed to uncomplete todo: {response.status_code} - {response.text}")
|
||||
|
||||
# People methods
|
||||
def get_people(self):
|
||||
"""Get all people in the account."""
|
||||
|
||||
Reference in New Issue
Block a user