From 5c95a27bb066beb5161065785d6441a6214ee9b7 Mon Sep 17 00:00:00 2001 From: Isaac Johnson Date: Mon, 13 Oct 2025 12:58:05 -0500 Subject: [PATCH] 0.18, add an active_tasks tool --- Dockerfile | 2 +- gemini-extension.json | 4 ++-- main.py | 43 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 418269f..ddbe391 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.17 +#harbor.freshbrewed.science/library/vikunjamcp:0.18 diff --git a/gemini-extension.json b/gemini-extension.json index 946e4d9..2afd612 100644 --- a/gemini-extension.json +++ b/gemini-extension.json @@ -1,6 +1,6 @@ { "name": "vikunja", - "version": "1.0.17", + "version": "1.0.18", "mcpServers": { "nodeServer": { "command": "docker", @@ -14,7 +14,7 @@ "VIKUNJA_USERNAME", "-e", "VIKUNJA_PASSWORD", - "harbor.freshbrewed.science/library/vikunjamcp:0.17" + "harbor.freshbrewed.science/library/vikunjamcp:0.18" ], "env": { "VIKUNJA_URL": "$VIKUNJA_URL", diff --git a/main.py b/main.py index 3511fbb..e4babb5 100644 --- a/main.py +++ b/main.py @@ -108,6 +108,49 @@ def search_tasks(query: str): logger.exception("search_tasks: request failed") return f"Error searching tasks: {e}" + +@mcp.tool() +def active_tasks(project_id: int = None): + """ + Returns a list of active tasks (where 'done' is False) from Vikunja. + + :param project_id: Optional project ID to filter tasks by project. + """ + if "Authorization" not in session.headers: + return "Please run the 'login' command first." + + try: + logger.info("active_tasks: fetching all tasks from %s", f"{VIKUNJA_URL}/api/v1/tasks/all") + + all_tasks = [] + page = 1 + per_page = 50 + + while True: + response = session.get(f"{VIKUNJA_URL}/api/v1/tasks/all?page={page}&limit={per_page}") + response.raise_for_status() + data = response.json() + tasks = data if isinstance(data, list) else data.get("tasks", []) + if not tasks: + break + all_tasks.extend(tasks) + page += 1 + + # Filter active tasks (not done) + active = [t for t in all_tasks if not t.get("done", False)] + + # If project_id provided, further filter by task's project_id + if project_id is not None: + before = len(active) + active = [t for t in active if t.get("project_id") == project_id or t.get("projectID") == project_id] + logger.info("active_tasks: filtered by project_id=%s before=%d after=%d", project_id, before, len(active)) + + logger.info("active_tasks: fetched=%d active=%d", len(all_tasks), len(active)) + return active + except requests.exceptions.RequestException as e: + logger.exception("active_tasks: request failed") + return f"Error retrieving active tasks: {e}" + @mcp.tool() def add_task(project_id: int, title: str, description: str = ""): """