list_todos
Retrieve and organize tasks with filtering by status, priority, tags, due dates, search queries, sorting, and pagination controls.
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:206-226 (handler)Core handler function that normalizes filters, fetches todos from storage, computes counts, sorts and paginates them, and builds the 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 = canReuseOrder(normalized.sortBy, normalized.order, counts) ? allTodos : sortTodos(allTodos, normalized.sortBy, normalized.order); const paged = paginateTodos(sorted, normalized.offset, normalized.limit); return buildListResponse(paged, counts, normalized); }
- src/schemas/inputs.ts:228-269 (schema)Input schema using Zod for validating filters like status, query, priority, pagination for the list_todos tool.export const ListTodosFilterSchema: ZodType<ListTodosFilterInput> = z.strictObject({ 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 .int() .min(1) .max(200) .optional() .describe('Max number of results to return (default: 50)'), offset: z .int() .min(0) .max(10000) .optional() .describe('Number of results to skip'), });
- src/tools/list_todos.ts:228-249 (registration)Registers the 'list_todos' tool with the MCP server, specifying title, description, schemas, and the handler function.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/index.ts:11-19 (registration)Top-level registration function that calls registerListTodos among others to set up all tools on the server.export function registerAllTools(server: McpServer): void { registerAddTodo(server); registerAddTodos(server); registerListTodos(server); registerUpdateTodo(server); registerCompleteTodo(server); registerDeleteTodo(server); registerDeleteTodos(server); }