list_all_tasks
Retrieve all active tasks from every list in one request, avoiding multiple list-specific calls.
Instructions
Fetch every active task across every list in a single round-trip (uses Graph $batch internally). Use this for the question "what are all my tasks?" instead of N×list_tasks calls. Optional filter is an OData filter applied per list (e.g. "importance eq 'high'"). By default status ne 'completed' is appended unless include_completed is true.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| filter | No | ||
| top_per_list | No | ||
| include_completed | No | ||
| verbose | No | If true: returns full JSON. Otherwise: compact text format (default, saves tokens). |
Implementation Reference
- src/graph.ts:626-647 (handler)The main handler function for the 'list_all_tasks' tool. Fetches all lists via listTaskLists(), builds a filter (appending 'status ne completed' unless includeCompleted), then calls fetchTasksAcrossLists() to get tasks from each list in parallel or via batch. Returns ListWithTasks[] with list metadata, tasks, and optional errors per list.
export async function listAllTasks( opts: { filter?: string; topPerList?: number; includeCompleted?: boolean; } = {} ): Promise<ListWithTasks[]> { const lists = await listTaskLists(); const filterParts: string[] = []; if (opts.filter) filterParts.push(opts.filter); if (!opts.includeCompleted) filterParts.push("status ne 'completed'"); const filter = filterParts.length > 0 ? filterParts.join(" and ") : undefined; const perList = await fetchTasksAcrossLists(lists, { filter, top: opts.topPerList ?? 50, }); return perList.map((r) => ({ list: { id: r.list.id, displayName: r.list.displayName }, tasks: r.tasks, error: r.error, })); } - src/graph.ts:488-537 (helper)Helper function fetchTasksAcrossLists() that either parallelizes direct calls (for <=5 lists) or uses a single Graph $batch call (for >5 lists) to fetch tasks from multiple lists efficiently.
async function fetchTasksAcrossLists( lists: TodoTaskList[], opts: { filter?: string; top?: number } = {} ): Promise<Array<{ list: TodoTaskList; tasks: TodoTask[]; error?: string }>> { const top = opts.top ?? 25; // Few lists: just parallelize direct calls (low HTTP overhead, MSAL refresh once) if (lists.length <= PARALLEL_THRESHOLD) { return Promise.all( lists.map(async (list) => { try { const tasks = await listTasks(list.id, { filter: opts.filter, top }); return { list, tasks }; } catch (err: any) { return { list, tasks: [] as TodoTask[], error: err.message ?? String(err) }; } }) ); } // Many lists: 1 HTTP call via $batch (still chunked by 20 internally) // No $select: rejected by Graph on tasks collection for personal accounts. const qs = buildOData({ filter: opts.filter, top, }); const requests: BatchRequest[] = lists.map((list, idx) => ({ id: String(idx), method: "GET", url: `/me/todo/lists/${enc(list.id)}/tasks${qs}`, })); const responses = await graphBatch(requests); const results: Array<{ list: TodoTaskList; tasks: TodoTask[]; error?: string }> = new Array( lists.length ); for (const r of responses) { const idx = Number(r.id); if (r.status >= 200 && r.status < 300) { const body = r.body as GraphCollection<TodoTask>; results[idx] = { list: lists[idx], tasks: body.value ?? [] }; } else { const body = r.body as GraphErrorBody | undefined; const err = body?.error ? `${body.error.code ?? r.status}: ${body.error.message ?? "(no message)"}` : `HTTP ${r.status}`; results[idx] = { list: lists[idx], tasks: [], error: err }; } } return results; } - src/index.ts:212-217 (schema)Zod schema for the list_all_tasks tool input: optional filter (OData string), top_per_list (int, max 200), include_completed (boolean), and a verbose field.
list_all_tasks: z.object({ filter: z.string().optional(), top_per_list: z.number().int().positive().max(200).optional(), include_completed: z.boolean().optional(), ...verboseField, }), - src/index.ts:646-658 (registration)Tool registration with name 'list_all_tasks', description explaining it uses Graph $batch internally, and JSON Schema input definition (filter, top_per_list, include_completed).
name: "list_all_tasks", description: "Fetch every active task across every list in a single round-trip (uses Graph $batch internally). Use this for the question \"what are all my tasks?\" instead of N×list_tasks calls. Optional `filter` is an OData filter applied per list (e.g. \"importance eq 'high'\"). By default `status ne 'completed'` is appended unless `include_completed` is true.", inputSchema: { type: "object", properties: { filter: { type: "string" }, top_per_list: { type: "number" }, include_completed: { type: "boolean" }, ...verboseJsonProp, }, }, }, - src/formatters.ts:127-140 (helper)Formatting helper that converts ListWithTasks[] into a compact human-readable string for the tool output, listing each list's name and its tasks.
export function formatAllTasksCompact(perList: ListWithTasks[]): string { const total = perList.reduce((s, l) => s + l.tasks.length, 0); const lines: string[] = [t.allTasksHeader(perList.length, total)]; for (const { list, tasks, error } of perList) { if (error) { lines.push(`\n${JSON.stringify(list.displayName)} (${list.id}) — ${t.error(error)}`); continue; } if (tasks.length === 0) continue; lines.push(`\n${JSON.stringify(list.displayName)} (${list.id}) — ${tasks.length}:`); for (const task of tasks) lines.push(` ${formatTaskCompact(task)}`); } return lines.join("\n"); } - src/graph.ts:617-621 (schema)ListWithTasks interface: the return type containing list metadata (id, displayName), tasks array, and optional error string.
export interface ListWithTasks { list: { id: string; displayName: string }; tasks: TodoTask[]; error?: string; }