get_todos
Retrieve all todo checklist items across tasks and projects with completion status, assignee details, due dates, and time tracking for comprehensive task management.
Instructions
Get all todo checklist items across all tasks and projects.
Returns comprehensive todo data including:
Checkbox items within tasks for granular tracking
Completion status and assignee information
Parent task details with project context
Due dates and priority relative to parent task
Estimated vs actual time for checklist items
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| extra_filters | No | Additional Productive query filters (e.g. {'filter[status]': '1'}) | |
| page_number | No | Page number for pagination | |
| page_size | No | Number of todos per page (max 200) | |
| task_id | No | Productive task ID to filter todos by |
Implementation Reference
- tools.py:278-316 (handler)Core implementation of the get_todos tool handler. Builds specific API parameters for pagination and task filtering, calls the Productive API client, sanitizes the response using filter_response, logs progress, and handles API and unexpected errors.async def get_todos( ctx: Context, task_id: int = None, page_number: int = None, page_size: int = config.items_per_page, extra_filters: dict = None ) -> ToolResult: """List todo checklist items with optional filters. Developer notes: - task_id is an int; API expects filter[task_id] to be array or scalar; we send scalar. - Enforces configurable default page[size] when not provided. - Use extra_filters for status ints (1=open, 2=closed) or assignee filters. - Sorting not supported by API - uses default order. - Applies utils.filter_response. """ try: await ctx.info("Fetching todos") params = {} if page_number is not None: params["page[number]"] = page_number params["page[size]"] = page_size if task_id is not None: params["filter[task_id]"] = [task_id] if extra_filters: params.update(extra_filters) result = await client.get_todos(params=params if params else None) await ctx.info("Successfully retrieved todos") filtered = filter_response(result) return filtered except ProductiveAPIError as e: await _handle_productive_api_error(ctx, e, "todos") except Exception as e: await ctx.error(f"Unexpected error fetching todos: {str(e)}") raise e
- server.py:375-407 (registration)MCP tool registration for 'get_todos' using @mcp.tool decorator. Defines input schema via Annotated parameters with descriptions and delegates execution to the core handler in tools.py.@mcp.tool async def get_todos( ctx: Context, task_id: Annotated[ int, Field(description="Productive task ID to filter todos by") ] = None, page_number: Annotated[int, Field(description="Page number for pagination")] = None, page_size: Annotated[ int, Field(description="Optional number of todos per page (max 200)") ] = None, extra_filters: Annotated[ dict, Field( description="Additional Productive query filters using API syntax. Common filters: filter[task_id][eq] (ID), filter[status][eq] (1: open, 2: closed), filter[assignee_id][eq] (ID)." ), ] = None, ) -> Dict[str, Any]: """Get all todo checklist items across all tasks and projects. Returns comprehensive todo data including: - Checkbox items within tasks for granular tracking - Completion status and assignee information - Parent task details with project context - Due dates and priority relative to parent task - Estimated vs actual time for checklist items """ return await tools.get_todos( ctx, task_id=task_id, page_number=page_number, page_size=page_size, extra_filters=extra_filters, )
- productive_client.py:99-102 (helper)API client method that performs the HTTP GET request to the Productive /todos endpoint with optional parameters, used by the tool handler.async def get_todos(self, params: Optional[dict] = None) -> Dict[str, Any]: """Get all todos """ return await self._request("GET", "/todos", params=params)