get_next_todo_task
Retrieve the next incomplete task from a TODO list for sequential execution. Use this tool to identify pending tasks, continue interrupted work, or follow task order efficiently while managing projects.
Instructions
Get the next incomplete task in a TODO list for sequential execution.
When to use this tool:
Working through TODO sequentially
Finding next task to implement
Checking for remaining work
Continuing interrupted work
Following task order
Key features:
Returns first incomplete task
Provides task number and description
Indicates when all complete
Maintains task sequence
You should:
Use after completing current task
Follow sequential task order
Handle "all complete" case
Read full task details if needed
Mark complete before getting next
DO NOT use when:
Need specific task (not next)
Want full TODO overview
All tasks already complete
Returns: {success: bool, task?: {number: int, description: str}, message?: str, error?: str}
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| project_id | Yes | The project identifier | |
| todo_number | Yes | The TODO list number |
Implementation Reference
- The core handler function that implements the logic for 'get_next_todo_task'. It locates the next incomplete task in the specified TODO list by scanning task files, parsing metadata, and returning task details or completion status.async getNextTodoTaskAsync(params: { project_id: z.infer<typeof secureProjectIdSchema>; todo_number: z.infer<typeof secureTodoNumberSchema>; }): Promise<string> { const context = this.createContext('get_next_todo_task', params); try { const { project_id, todo_number } = params; const projectInfo = await getProjectDirectoryAsync(this.storagePath, project_id); if (!projectInfo) { throw new MCPError(MCPErrorCode.PROJECT_NOT_FOUND, `Project ${project_id} not found`, { project_id, traceId: context.traceId, }); } const [, projectPath] = projectInfo; const todoDir = join(projectPath, 'TODO', todo_number.toString()); // Check if TODO exists try { await access(todoDir); } catch { throw new MCPError(MCPErrorCode.TODO_NOT_FOUND, `TODO #${todo_number} not found`, { project_id, todo_number, traceId: context.traceId, }); } // Find all task files const taskFiles = await this.getTaskFilesAsync(todoDir); // Look for first incomplete task for (const taskFile of taskFiles) { const taskPath = join(todoDir, taskFile); const content = await readFile(taskPath, 'utf8'); const parsed = fm<TaskMetadata>(content); if (!parsed.attributes.completed) { const taskNumber = this.extractTaskNumber(taskFile); const taskData = await this.parseTaskDataAsync(taskPath); this.logSuccess( 'get_next_todo_task', { project_id, todo_number, task_number: taskNumber }, context ); return this.formatSuccessResponse({ task: { number: taskNumber, description: taskData.title, }, }); } } // No incomplete tasks this.logSuccess('get_next_todo_task', { project_id, todo_number, found: false }, context); return this.formatSuccessResponse({ message: 'All tasks completed', }); } catch (error) { this.logError('get_next_todo_task', params, error as MCPError, context); return this.formatErrorResponse(error, context); } }
- src/knowledge-mcp/server.ts:740-760 (registration)Registers the 'get_next_todo_task' tool with the MCP server, specifying title, description, input schema, and the handler function that delegates to TodoToolHandler.getNextTodoTaskAsync.'get_next_todo_task', { title: 'Get Next TODO Task', description: TOOL_DESCRIPTIONS.get_next_todo_task, inputSchema: { project_id: secureProjectIdSchema.describe('The project identifier'), todo_number: secureTodoNumberSchema.describe('The TODO list number'), }, }, async ({ project_id, todo_number }) => { const result = await todoHandler.getNextTodoTaskAsync({ project_id, todo_number }); return { content: [ { type: 'text', text: result, }, ], }; } );
- src/knowledge-mcp/server.ts:744-747 (schema)Defines the input schema for the tool using Zod schemas for project_id and todo_number with descriptions.inputSchema: { project_id: secureProjectIdSchema.describe('The project identifier'), todo_number: secureTodoNumberSchema.describe('The TODO list number'), },
- Helper method to extract the task number from task filenames like 'TASK-001-slug.md', used in the handler to identify tasks.private extractTaskNumber(filename: string): number { const match = filename.match(/^TASK-(\d{3})-.*\.md$/); return match ? parseInt(match[1], 10) : 0; }
- Async helper to list and sort task files (.md starting with TASK-) in a TODO directory, crucial for scanning tasks in the handler.private async getTaskFilesAsync(todoDir: string): Promise<string[]> { const files = await readdir(todoDir); return files.filter((file) => file.startsWith('TASK-') && file.endsWith('.md')).sort(); }