setTaskStatus
Update the status of multiple tasks in a project using project ID, task IDs, and target status. Validates task existence and returns the count of updated tasks.
Instructions
Updates the status ('todo', 'in-progress', 'review', 'done') for one or more tasks within a specified project. Requires the project ID, an array of task IDs (1-100), and the target status. Verifies all tasks exist in the project before updating. Returns the count of updated tasks.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| project_id | Yes | The unique identifier (UUID) of the project containing the tasks. | |
| status | Yes | The target status to set for the specified tasks. | |
| task_ids | Yes | An array of task IDs (1-100) whose status should be updated. |
Implementation Reference
- src/tools/setTaskStatusTool.ts:16-49 (handler)Handler function processRequest that executes the setTaskStatus tool logic: logs request, calls TaskService.setTaskStatus, returns JSON response with updated count, handles NotFoundError as InvalidParams and other errors as InternalError.const processRequest = async (args: SetTaskStatusArgs) => { logger.info(`[${TOOL_NAME}] Received request with args:`, args); try { // Call the service method to update the status const updatedCount = await taskService.setTaskStatus( args.project_id, args.task_ids, args.status ); // Format the successful response const responsePayload = { success: true, updated_count: updatedCount }; logger.info(`[${TOOL_NAME}] Updated status for ${updatedCount} tasks in project ${args.project_id}`); return { content: [{ type: "text" as const, text: JSON.stringify(responsePayload) }] }; } catch (error: unknown) { // Handle potential errors logger.error(`[${TOOL_NAME}] Error processing request:`, error); if (error instanceof NotFoundError) { // Specific error if the project or any task wasn't found // Map to InvalidParams as the provided ID(s) are invalid throw new McpError(ErrorCode.InvalidParams, error.message); } else { // Generic internal error const message = error instanceof Error ? error.message : 'An unknown error occurred while setting task status.'; throw new McpError(ErrorCode.InternalError, message); } } };
- Schema definitions: TOOL_NAME, TOOL_DESCRIPTION, Zod TOOL_PARAMS for input validation (project_id UUID, task_ids array 1-100 strings, status enum), and inferred SetTaskStatusArgs type.export const TOOL_NAME = "setTaskStatus"; export const TOOL_DESCRIPTION = ` Updates the status ('todo', 'in-progress', 'review', 'done') for one or more tasks within a specified project. Requires the project ID, an array of task IDs (1-100), and the target status. Verifies all tasks exist in the project before updating. Returns the count of updated tasks. `; // Re-use enum from other param files const TaskStatusEnum = z.enum(['todo', 'in-progress', 'review', 'done']); // Zod schema for the parameters, matching FR-005 and setTaskStatusTool.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 containing the tasks."), // Required, UUID format task_ids: z.array( z.string().min(1, "Task ID cannot be empty.") // Add .uuid() if task IDs are UUIDs .describe("A unique identifier of a task to update.") ) .min(1, "At least one task ID must be provided.") .max(100, "Cannot update more than 100 tasks per call.") .describe("An array of task IDs (1-100) whose status should be updated."), // Required, array of strings, limits status: TaskStatusEnum .describe("The target status to set for the specified tasks."), // Required, enum }); // Define the expected type for arguments based on the Zod schema export type SetTaskStatusArgs = z.infer<typeof TOOL_PARAMS>;
- src/tools/setTaskStatusTool.ts:14-55 (registration)Registration function setTaskStatusTool that defines the handler, registers it with MCP server.tool(TOOL_NAME, DESCRIPTION, PARAMS.shape, handler), and logs success.export const setTaskStatusTool = (server: McpServer, taskService: TaskService): void => { const processRequest = async (args: SetTaskStatusArgs) => { logger.info(`[${TOOL_NAME}] Received request with args:`, args); try { // Call the service method to update the status const updatedCount = await taskService.setTaskStatus( args.project_id, args.task_ids, args.status ); // Format the successful response const responsePayload = { success: true, updated_count: updatedCount }; logger.info(`[${TOOL_NAME}] Updated status for ${updatedCount} tasks in project ${args.project_id}`); return { content: [{ type: "text" as const, text: JSON.stringify(responsePayload) }] }; } catch (error: unknown) { // Handle potential errors logger.error(`[${TOOL_NAME}] Error processing request:`, error); if (error instanceof NotFoundError) { // Specific error if the project or any task wasn't found // Map to InvalidParams as the provided ID(s) are invalid throw new McpError(ErrorCode.InvalidParams, error.message); } else { // Generic internal error const message = error instanceof Error ? error.message : 'An unknown error occurred while setting task status.'; 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:57-57 (registration)Top-level call to setTaskStatusTool during registerTools to initialize and register the tool with dependencies.setTaskStatusTool(server, taskService);
- src/services/TaskService.ts:168-194 (helper)Supporting TaskService.setTaskStatus method: validates project/tasks exist, updates statuses via repository, returns updated count.public async setTaskStatus(projectId: string, taskIds: string[], status: TaskData['status']): Promise<number> { logger.info(`[TaskService] Attempting to set status to '${status}' for ${taskIds.length} tasks in project ${projectId}`); const projectExists = this.projectRepository.findById(projectId); if (!projectExists) { logger.warn(`[TaskService] Project not found: ${projectId}`); throw new NotFoundError(`Project with ID ${projectId} not found.`); } const existenceCheck = this.taskRepository.checkTasksExist(projectId, taskIds); if (!existenceCheck.allExist) { logger.warn(`[TaskService] One or more tasks not found in project ${projectId}:`, existenceCheck.missingIds); throw new NotFoundError(`One or more tasks not found in project ${projectId}: ${existenceCheck.missingIds.join(', ')}`); } try { const now = new Date().toISOString(); const updatedCount = this.taskRepository.updateStatus(projectId, taskIds, status, now); if (updatedCount !== taskIds.length) { logger.warn(`[TaskService] Expected to update ${taskIds.length} tasks, but ${updatedCount} were affected.`); } logger.info(`[TaskService] Successfully updated status for ${updatedCount} tasks in project ${projectId}`); return updatedCount; } catch (error) { logger.error(`[TaskService] Error setting status for tasks in project ${projectId}:`, error); throw error; } }