listTasks
Retrieve tasks for a specific project on the MCP Task Manager Server. Filter by task status and optionally include nested subtasks for detailed task management.
Instructions
Retrieves a list of tasks for a specified project. Allows optional filtering by task status ('todo', 'in-progress', 'review', 'done'). Provides an option to include nested subtasks directly within their parent task objects in the response. Returns an array of task objects.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| include_subtasks | No | Optional flag (default false). If true, the response will include subtasks nested within their parent tasks. | |
| project_id | Yes | The unique identifier (UUID) of the project whose tasks are to be listed. This project must exist. | |
| status | No | Optional filter to return only tasks matching the specified status. |
Implementation Reference
- src/tools/listTasksTool.ts:16-47 (handler)The handler function that executes the listTasks tool: logs request, calls TaskService.listTasks with args, returns JSON-stringified tasks or throws MCP errors.const processRequest = async (args: ListTasksArgs) => { logger.info(`[${TOOL_NAME}] Received request with args:`, args); try { // Call the service method to list tasks const tasks = await taskService.listTasks({ project_id: args.project_id, status: args.status, include_subtasks: args.include_subtasks, }); // Format the successful response logger.info(`[${TOOL_NAME}] Found ${tasks.length} tasks for project ${args.project_id}`); return { content: [{ type: "text" as const, text: JSON.stringify(tasks) // Return the array of task objects }] }; } catch (error: unknown) { // Handle potential errors logger.error(`[${TOOL_NAME}] Error processing request:`, error); if (error instanceof NotFoundError) { // Specific error if the project wasn't found throw new McpError(ErrorCode.InvalidParams, error.message); // Map NotFound to InvalidParams for project_id } else { // Generic internal error const message = error instanceof Error ? error.message : 'An unknown error occurred while listing tasks.'; throw new McpError(ErrorCode.InternalError, message); } } };
- src/tools/listTasksParams.ts:13-32 (schema)Zod schema (TOOL_PARAMS) and type (ListTasksArgs) for listTasks tool inputs: required project_id UUID, optional status enum, optional include_subtasks bool (default false). Includes TOOL_NAME = 'listTasks'.const TaskStatusEnum = z.enum(['todo', 'in-progress', 'review', 'done']); // Zod schema for the parameters, matching FR-003 and listTasksTool.md spec export const TOOL_PARAMS = z.object({ project_id: z.string() .uuid("The project_id must be a valid UUID.") .describe("The unique identifier (UUID) of the project whose tasks are to be listed. This project must exist."), // Required, UUID format status: TaskStatusEnum .optional() .describe("Optional filter to return only tasks matching the specified status."), // Optional, enum include_subtasks: z.boolean() .optional() .default(false) // Default value .describe("Optional flag (default false). If true, the response will include subtasks nested within their parent tasks."), // Optional, boolean, default }); // Define the expected type for arguments based on the Zod schema export type ListTasksArgs = z.infer<typeof TOOL_PARAMS>;
- src/tools/listTasksTool.ts:14-53 (registration)The registration function listTasksTool that defines the handler and calls server.tool to register 'listTasks' with MCP server.export const listTasksTool = (server: McpServer, taskService: TaskService): void => { const processRequest = async (args: ListTasksArgs) => { logger.info(`[${TOOL_NAME}] Received request with args:`, args); try { // Call the service method to list tasks const tasks = await taskService.listTasks({ project_id: args.project_id, status: args.status, include_subtasks: args.include_subtasks, }); // Format the successful response logger.info(`[${TOOL_NAME}] Found ${tasks.length} tasks for project ${args.project_id}`); return { content: [{ type: "text" as const, text: JSON.stringify(tasks) // Return the array of task objects }] }; } catch (error: unknown) { // Handle potential errors logger.error(`[${TOOL_NAME}] Error processing request:`, error); if (error instanceof NotFoundError) { // Specific error if the project wasn't found throw new McpError(ErrorCode.InvalidParams, error.message); // Map NotFound to InvalidParams for project_id } else { // Generic internal error const message = error instanceof Error ? error.message : 'An unknown error occurred while listing tasks.'; throw new McpError(ErrorCode.InternalError, message); } } }; // Register the tool with the server server.tool(TOOL_NAME, TOOL_DESCRIPTION, TOOL_PARAMS.shape, processRequest); logger.info(`[${TOOL_NAME}] Tool registered successfully.`); };
- src/tools/index.ts:13-55 (registration)Imports and invokes listTasksTool during overall tool registration in the tools index.import { listTasksTool } from "./listTasksTool.js"; import { showTaskTool } from "./showTaskTool.js"; import { setTaskStatusTool } from "./setTaskStatusTool.js"; import { expandTaskTool } from "./expandTaskTool.js"; import { getNextTaskTool } from "./getNextTaskTool.js"; import { exportProjectTool } from "./exportProjectTool.js"; import { importProjectTool } from "./importProjectTool.js"; import { updateTaskTool } from "./updateTaskTool.js"; // Import the new tool import { deleteTaskTool } from "./deleteTaskTool.js"; // Import deleteTask tool import { deleteProjectTool } from "./deleteProjectTool.js"; // Import deleteProject tool // import { yourTool } from "./yourTool.js"; // Add other new tool imports here /** * Register all defined tools with the MCP server instance. * This function centralizes tool registration logic. * It also instantiates necessary services and repositories. */ export function registerTools(server: McpServer): void { logger.info("Registering tools..."); const configManager = ConfigurationManager.getInstance(); // --- Instantiate Dependencies --- // Note: Consider dependency injection frameworks for larger applications try { const dbManager = DatabaseManager.getInstance(); const db = dbManager.getDb(); // Get the initialized DB connection // Instantiate Repositories const projectRepository = new ProjectRepository(db); const taskRepository = new TaskRepository(db); // Instantiate TaskRepository // Instantiate Services const projectService = new ProjectService(db, projectRepository, taskRepository); // Pass db and both repos const taskService = new TaskService(db, taskRepository, projectRepository); // Instantiate TaskService, passing db and repos // --- Register Tools --- // Register each tool, passing necessary services // exampleTool(server, configManager.getExampleServiceConfig()); // Example commented out createProjectTool(server, projectService); addTaskTool(server, taskService); listTasksTool(server, taskService);
- src/services/TaskService.ts:100-136 (helper)TaskService.listTasks method: validates project, fetches tasks from repo, filters top-level or builds nested structure with subtasks if requested.public async listTasks(options: ListTasksOptions): Promise<TaskData[] | StructuredTaskData[]> { logger.info(`[TaskService] Attempting to list tasks for project: ${options.project_id}`, options); const projectExists = this.projectRepository.findById(options.project_id); if (!projectExists) { logger.warn(`[TaskService] Project not found: ${options.project_id}`); throw new NotFoundError(`Project with ID ${options.project_id} not found.`); } try { const allTasks = this.taskRepository.findByProjectId(options.project_id, options.status); if (!options.include_subtasks) { const topLevelTasks = allTasks.filter(task => !task.parent_task_id); logger.info(`[TaskService] Found ${topLevelTasks.length} top-level tasks for project ${options.project_id}`); return topLevelTasks; } else { const taskMap: Map<string, StructuredTaskData> = new Map(); const rootTasks: StructuredTaskData[] = []; for (const task of allTasks) { taskMap.set(task.task_id, { ...task, subtasks: [] }); } for (const task of allTasks) { if (task.parent_task_id && taskMap.has(task.parent_task_id)) { const parent = taskMap.get(task.parent_task_id)!; parent.subtasks!.push(taskMap.get(task.task_id)!); } else if (!task.parent_task_id) { rootTasks.push(taskMap.get(task.task_id)!); } } logger.info(`[TaskService] Found ${rootTasks.length} structured root tasks for project ${options.project_id}`); return rootTasks; } } catch (error) { logger.error(`[TaskService] Error listing tasks for project ${options.project_id}:`, error); throw error; } }