list_todos
Retrieve and manage tasks by filtering, searching, sorting, and paginating todo items based on status, priority, tags, due dates, and other criteria.
Instructions
List todos with filtering, search, sorting, and pagination
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| completed | No | Filter by completion status (deprecated; use status) | |
| status | No | Filter by status | |
| query | No | Search text in title, description, or tags | |
| priority | No | Filter by priority level | |
| tag | No | Filter by tag (must contain) | |
| dueBefore | No | Filter todos due before this date (ISO format) | |
| dueAfter | No | Filter todos due after this date (ISO format) | |
| sortBy | No | Sort results by field | |
| order | No | Sort order (default: asc) | |
| limit | No | Max number of results to return (default: 50) | |
| offset | No | Number of results to skip |
Implementation Reference
- src/tools/list_todos.ts:169-203 (handler)Main handler function that processes filters, fetches todos, sorts, paginates, computes stats, and returns formatted response.async function handleListTodos( filters: ListTodosFilters ): Promise<CallToolResult> { const normalized = normalizeFilters(filters); const allTodos = await getTodos({ completed: normalized.completed, priority: normalized.priority, tag: normalized.tag, dueBefore: normalized.dueBefore, dueAfter: normalized.dueAfter, query: normalized.query, }); const todayIso = getTodayIso(); const counts = computeCounts(allTodos, todayIso); const sorted = sortTodos(allTodos, normalized.sortBy, normalized.order); const paged = paginateTodos(sorted, normalized.offset, normalized.limit); const summary = buildSummary(counts, paged.length); return createToolResponse({ ok: true, result: { items: paged, summary, counts: { total: counts.total, pending: counts.pending, completed: counts.completed, overdue: counts.overdue, }, limit: normalized.limit, offset: normalized.offset, }, }); }
- src/schemas/inputs.ts:134-178 (schema)Zod schema defining input filters for the list_todos tool, including status, query, priority, tags, dates, sorting, and pagination.export const ListTodosFilterSchema = z .object({ completed: z .boolean() .optional() .describe('Filter by completion status (deprecated; use status)'), status: z .enum(['pending', 'completed', 'all']) .optional() .describe('Filter by status'), query: z .string() .min(1) .max(200) .optional() .describe('Search text in title, description, or tags'), priority: z .enum(['low', 'normal', 'high']) .optional() .describe('Filter by priority level'), tag: TagSchema.optional().describe('Filter by tag (must contain)'), dueBefore: IsoDateSchema.optional().describe( 'Filter todos due before this date (ISO format)' ), dueAfter: IsoDateSchema.optional().describe( 'Filter todos due after this date (ISO format)' ), sortBy: SortBySchema.optional().describe('Sort results by field'), order: SortOrderSchema.optional().describe('Sort order (default: asc)'), limit: z .number() .int() .min(1) .max(200) .optional() .describe('Max number of results to return (default: 50)'), offset: z .number() .int() .min(0) .max(10000) .optional() .describe('Number of results to skip'), }) .strict();
- src/tools/list_todos.ts:205-226 (registration)Registers the 'list_todos' tool with the MCP server, specifying title, description, schemas, annotations, and handler.export function registerListTodos(server: McpServer): void { server.registerTool( 'list_todos', { title: 'List Todos', description: 'List todos with filtering, search, sorting, and pagination', inputSchema: ListTodosFilterSchema, outputSchema: DefaultOutputSchema, annotations: { readOnlyHint: true, idempotentHint: true, }, }, async (filters) => { try { return await handleListTodos(filters); } catch (err) { return createErrorResponse('E_LIST_TODOS', getErrorMessage(err)); } } ); }
- src/tools/list_todos.ts:104-117 (helper)Helper function to normalize and provide defaults for list_todos input filters.function normalizeFilters(filters: ListTodosFilters): NormalizedFilters { return { completed: resolveCompletedFilter(filters.status, filters.completed), priority: filters.priority, tag: filters.tag, dueBefore: filters.dueBefore, dueAfter: filters.dueAfter, query: normalizeQuery(filters.query), sortBy: filters.sortBy ?? 'createdAt', order: filters.order ?? 'asc', limit: filters.limit ?? DEFAULT_LIMIT, offset: filters.offset ?? DEFAULT_OFFSET, }; }