diff --git a/Dockerfile b/Dockerfile index ada5bc4..418269f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,4 +20,4 @@ RUN pip install --no-cache-dir -r requirements.txt COPY . . CMD ["python", "main.py"] -#harbor.freshbrewed.science/library/vikunjamcp:0.16 +#harbor.freshbrewed.science/library/vikunjamcp:0.17 diff --git a/gemini-extension.json b/gemini-extension.json index 46e036e..946e4d9 100644 --- a/gemini-extension.json +++ b/gemini-extension.json @@ -1,6 +1,6 @@ { "name": "vikunja", - "version": "1.0.16", + "version": "1.0.17", "mcpServers": { "nodeServer": { "command": "docker", @@ -14,7 +14,7 @@ "VIKUNJA_USERNAME", "-e", "VIKUNJA_PASSWORD", - "harbor.freshbrewed.science/library/vikunjamcp:0.16" + "harbor.freshbrewed.science/library/vikunjamcp:0.17" ], "env": { "VIKUNJA_URL": "$VIKUNJA_URL", diff --git a/main.py b/main.py index c62888c..3511fbb 100644 --- a/main.py +++ b/main.py @@ -136,6 +136,82 @@ def add_task(project_id: int, title: str, description: str = ""): except requests.exceptions.RequestException as e: return f"Error adding task: {e}" +@mcp.tool() +def update_task_title(task_id: int, title: str): + """ + Updates an existing title on a task. + + :param task_id: The ID of the task. + :param title: The updated title text. + """ + if "Authorization" not in session.headers: + return "Please run the 'login' command first." + + if not (title or "").strip(): + return "Title cannot be empty." + + task_payload = { + "title": title + } + + try: + response = session.post( + f"{VIKUNJA_URL}/api/v1/tasks/{task_id}", + json=task_payload + ) + response.raise_for_status() + return response.json() + except requests.exceptions.RequestException as e: + logger.exception("update_task_title: request failed for task_id=%s", task_id) + return f"Error updating task title: {e}" + +@mcp.tool() +def update_task_description(task_id: int, description: str): + """ + Updates an existing description on a task. + + :param task_id: The ID of the task. + :param description: The updated description text. + """ + if "Authorization" not in session.headers: + return "Please run the 'login' command first." + + if not (description or "").strip(): + return "Description cannot be empty." + + task_payload = { + "description": description + } + + try: + response = session.post( + f"{VIKUNJA_URL}/api/v1/tasks/{task_id}", + json=task_payload + ) + response.raise_for_status() + return response.json() + except requests.exceptions.RequestException as e: + logger.exception("update_task_description: request failed for task_id=%s", task_id) + return f"Error updating task description: {e}" + +@mcp.tool() +def delete_task(task_id: int): + """ + Deletes an existing task. + + :param task_id: The ID of the task. + """ + if "Authorization" not in session.headers: + return "Please run the 'login' command first." + + try: + response = session.delete(f"{VIKUNJA_URL}/api/v1/tasks/{task_id}") + response.raise_for_status() + return response.json() + except requests.exceptions.RequestException as e: + logger.exception("delete_task: request failed for task_id=%s", task_id) + return f"Error deleting task: {e}" + @mcp.tool() def close_task(task_id: int): """