get_tasks
Retrieve all tasks from Task Master, with options to filter by status, include subtasks, and specify project details for AI-driven development workflows.
Instructions
Get all tasks from Task Master, optionally filtering by status and including subtasks.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| complexityReport | No | Path to the complexity report file (relative to project root or absolute) | |
| file | No | Path to the tasks file (relative to project root or absolute) | |
| projectRoot | Yes | The directory of the project. Must be an absolute path. | |
| status | No | Filter tasks by status (e.g., 'pending', 'done') or multiple statuses separated by commas (e.g., 'blocked,deferred') | |
| tag | No | Tag context to operate on | |
| withSubtasks | No | Include subtasks nested within their parent tasks in the response |
Implementation Reference
- The main handler function for the get_tasks tool, which fetches tasks from tmCore.tasks.list, applies filters, computes statistics including completion percentages for tasks and subtasks, and returns structured results or error handling.execute: withToolContext( 'get-tasks', async (args: GetTasksArgs, { log, tmCore }: ToolContext) => { const { projectRoot, status, withSubtasks, tag } = args; try { log.info( `Getting tasks from ${projectRoot}${status ? ` with status filter: ${status}` : ''}${tag ? ` for tag: ${tag}` : ''}` ); // Build filter const filter = status && status !== 'all' ? { status: status .split(',') .map((s: string) => s.trim() as TaskStatus) } : undefined; // Call tm-core tasks.list() const result = await tmCore.tasks.list({ tag, filter, includeSubtasks: withSubtasks }); log.info( `Retrieved ${result.tasks?.length || 0} tasks (${result.filtered} filtered, ${result.total} total)` ); // Calculate stats using reduce for cleaner code const tasks = result.tasks ?? []; const totalTasks = result.total; const taskCounts = tasks.reduce( (acc, task) => { acc[task.status] = (acc[task.status] || 0) + 1; return acc; }, {} as Record<string, number> ); const completionPercentage = totalTasks > 0 ? ((taskCounts.done || 0) / totalTasks) * 100 : 0; // Count subtasks using reduce const subtaskCounts = tasks.reduce( (acc, task) => { task.subtasks?.forEach((st) => { acc.total++; acc[st.status] = (acc[st.status] || 0) + 1; }); return acc; }, { total: 0 } as Record<string, number> ); const subtaskCompletionPercentage = subtaskCounts.total > 0 ? ((subtaskCounts.done || 0) / subtaskCounts.total) * 100 : 0; return handleApiResult({ result: { success: true, data: { tasks: tasks as Task[], filter: status || 'all', stats: { total: totalTasks, completed: taskCounts.done || 0, inProgress: taskCounts['in-progress'] || 0, pending: taskCounts.pending || 0, blocked: taskCounts.blocked || 0, deferred: taskCounts.deferred || 0, cancelled: taskCounts.cancelled || 0, review: taskCounts.review || 0, completionPercentage, subtasks: { total: subtaskCounts.total, completed: subtaskCounts.done || 0, inProgress: subtaskCounts['in-progress'] || 0, pending: subtaskCounts.pending || 0, blocked: subtaskCounts.blocked || 0, deferred: subtaskCounts.deferred || 0, cancelled: subtaskCounts.cancelled || 0, completionPercentage: subtaskCompletionPercentage } } } }, log, projectRoot, tag: result.tag }); } catch (error: any) { log.error(`Error in get-tasks: ${error.message}`); if (error.stack) { log.debug(error.stack); } return handleApiResult({ result: { success: false, error: { message: `Failed to get tasks: ${error.message}` } }, log, projectRoot }); } } )
- Zod schema defining input parameters for the get_tasks tool: projectRoot (required), status (optional filter), withSubtasks (optional boolean), tag (optional).const GetTasksSchema = z.object({ projectRoot: z .string() .describe('The directory of the project. Must be an absolute path.'), status: z .string() .optional() .describe( "Filter tasks by status (e.g., 'pending', 'done') or multiple statuses separated by commas (e.g., 'blocked,deferred')" ), withSubtasks: z .boolean() .optional() .describe('Include subtasks nested within their parent tasks in the response'), tag: z.string().optional().describe('Tag context to operate on') });
- apps/mcp/src/tools/tasks/get-tasks.tool.ts:37-157 (registration)Registration function that adds the 'get_tasks' tool to the FastMCP server, specifying name, description, parameters schema, and execute handler.export function registerGetTasksTool(server: FastMCP) { server.addTool({ name: 'get_tasks', description: 'Get all tasks from Task Master, optionally filtering by status and including subtasks.', parameters: GetTasksSchema, execute: withToolContext( 'get-tasks', async (args: GetTasksArgs, { log, tmCore }: ToolContext) => { const { projectRoot, status, withSubtasks, tag } = args; try { log.info( `Getting tasks from ${projectRoot}${status ? ` with status filter: ${status}` : ''}${tag ? ` for tag: ${tag}` : ''}` ); // Build filter const filter = status && status !== 'all' ? { status: status .split(',') .map((s: string) => s.trim() as TaskStatus) } : undefined; // Call tm-core tasks.list() const result = await tmCore.tasks.list({ tag, filter, includeSubtasks: withSubtasks }); log.info( `Retrieved ${result.tasks?.length || 0} tasks (${result.filtered} filtered, ${result.total} total)` ); // Calculate stats using reduce for cleaner code const tasks = result.tasks ?? []; const totalTasks = result.total; const taskCounts = tasks.reduce( (acc, task) => { acc[task.status] = (acc[task.status] || 0) + 1; return acc; }, {} as Record<string, number> ); const completionPercentage = totalTasks > 0 ? ((taskCounts.done || 0) / totalTasks) * 100 : 0; // Count subtasks using reduce const subtaskCounts = tasks.reduce( (acc, task) => { task.subtasks?.forEach((st) => { acc.total++; acc[st.status] = (acc[st.status] || 0) + 1; }); return acc; }, { total: 0 } as Record<string, number> ); const subtaskCompletionPercentage = subtaskCounts.total > 0 ? ((subtaskCounts.done || 0) / subtaskCounts.total) * 100 : 0; return handleApiResult({ result: { success: true, data: { tasks: tasks as Task[], filter: status || 'all', stats: { total: totalTasks, completed: taskCounts.done || 0, inProgress: taskCounts['in-progress'] || 0, pending: taskCounts.pending || 0, blocked: taskCounts.blocked || 0, deferred: taskCounts.deferred || 0, cancelled: taskCounts.cancelled || 0, review: taskCounts.review || 0, completionPercentage, subtasks: { total: subtaskCounts.total, completed: subtaskCounts.done || 0, inProgress: subtaskCounts['in-progress'] || 0, pending: subtaskCounts.pending || 0, blocked: subtaskCounts.blocked || 0, deferred: subtaskCounts.deferred || 0, cancelled: subtaskCounts.cancelled || 0, completionPercentage: subtaskCompletionPercentage } } } }, log, projectRoot, tag: result.tag }); } catch (error: any) { log.error(`Error in get-tasks: ${error.message}`); if (error.stack) { log.debug(error.stack); } return handleApiResult({ result: { success: false, error: { message: `Failed to get tasks: ${error.message}` } }, log, projectRoot }); } } ) }); }
- mcp-server/src/tools/tool-registry.js:70-70 (registration)Tool registry mapping 'get_tasks' to its registration function imported from @tm/mcp.get_tasks: registerGetTasksTool,