feat: implement add-task MCP command

- Create direct function wrapper in add-task.js with prompt and dependency handling

- Add MCP tool integration for creating new tasks via AI

- Update task-master-core.js to expose addTaskDirect function

- Update changeset to document the new command
This commit is contained in:
Eyal Toledano
2025-03-31 12:50:14 -04:00
parent 04c2dee593
commit 43022d7010
7 changed files with 140 additions and 22 deletions

View File

@@ -10,4 +10,5 @@
- Implement show-task MCP command for displaying detailed task information
- Implement next-task MCP command for finding the next task to work on
- Implement expand-task MCP command for breaking down tasks into subtasks
- Implement add-task MCP command for creating new tasks using AI assistance
- Document MCP server naming conventions in architecture.mdc and mcp.mdc files (file names use kebab-case, direct functions use camelCase with Direct suffix, tool registration functions use camelCase with Tool suffix, and MCP tool names use snake_case)

View File

@@ -0,0 +1,67 @@
/**
* add-task.js
* Direct function implementation for adding a new task
*/
import { addTask } from '../../../../scripts/modules/task-manager.js';
import { findTasksJsonPath } from '../utils/path-utils.js';
/**
* Direct function wrapper for adding a new task with error handling.
*
* @param {Object} args - Command arguments
* @param {string} args.prompt - Description of the task to add
* @param {Array<number>} [args.dependencies=[]] - Task dependencies as array of IDs
* @param {string} [args.priority='medium'] - Task priority (high, medium, low)
* @param {string} [args.file] - Path to the tasks file
* @param {string} [args.projectRoot] - Project root directory
* @param {Object} log - Logger object
* @returns {Promise<Object>} - Result object { success: boolean, data?: any, error?: { code: string, message: string } }
*/
export async function addTaskDirect(args, log) {
try {
// Resolve the tasks file path
const tasksPath = findTasksJsonPath(args.file, args.projectRoot);
// Check required parameters
if (!args.prompt) {
log.error('Missing required parameter: prompt');
return {
success: false,
error: {
code: 'MISSING_PARAMETER',
message: 'The prompt parameter is required for adding a task'
}
};
}
// Extract and prepare parameters
const prompt = args.prompt;
const dependencies = Array.isArray(args.dependencies)
? args.dependencies
: (args.dependencies ? String(args.dependencies).split(',').map(id => parseInt(id.trim(), 10)) : []);
const priority = args.priority || 'medium';
log.info(`Adding new task with prompt: "${prompt}", dependencies: [${dependencies.join(', ')}], priority: ${priority}`);
// Call the addTask function
const newTaskId = await addTask(tasksPath, prompt, dependencies, priority);
return {
success: true,
data: {
taskId: newTaskId,
message: `Successfully added new task #${newTaskId}`
}
};
} catch (error) {
log.error(`Error in addTaskDirect: ${error.message}`);
return {
success: false,
error: {
code: 'ADD_TASK_ERROR',
message: error.message
}
};
}
}

View File

@@ -16,11 +16,28 @@ import { setTaskStatusDirect } from './direct-functions/set-task-status.js';
import { showTaskDirect } from './direct-functions/show-task.js';
import { nextTaskDirect } from './direct-functions/next-task.js';
import { expandTaskDirect } from './direct-functions/expand-task.js';
import { addTaskDirect } from './direct-functions/add-task.js';
// Re-export utility functions
export { findTasksJsonPath } from './utils/path-utils.js';
// Re-export all direct functions
// Use Map for potential future enhancements like introspection or dynamic dispatch
export const directFunctions = new Map([
['listTasksDirect', listTasksDirect],
['getCacheStatsDirect', getCacheStatsDirect],
['parsePRDDirect', parsePRDDirect],
['updateTasksDirect', updateTasksDirect],
['updateTaskByIdDirect', updateTaskByIdDirect],
['updateSubtaskByIdDirect', updateSubtaskByIdDirect],
['generateTaskFilesDirect', generateTaskFilesDirect],
['setTaskStatusDirect', setTaskStatusDirect],
['showTaskDirect', showTaskDirect],
['nextTaskDirect', nextTaskDirect],
['expandTaskDirect', expandTaskDirect],
['addTaskDirect', addTaskDirect]
]);
// Re-export all direct function implementations
export {
listTasksDirect,
getCacheStatsDirect,
@@ -33,23 +50,5 @@ export {
showTaskDirect,
nextTaskDirect,
expandTaskDirect,
};
/**
* Maps Task Master functions to their direct implementation
* This map is used by tools to look up the appropriate function by name
*/
export const directFunctions = {
list: listTasksDirect,
cacheStats: getCacheStatsDirect,
parsePRD: parsePRDDirect,
update: updateTasksDirect,
updateTask: updateTaskByIdDirect,
updateSubtask: updateSubtaskByIdDirect,
generate: generateTaskFilesDirect,
setStatus: setTaskStatusDirect,
showTask: showTaskDirect,
nextTask: nextTaskDirect,
expandTask: expandTaskDirect,
// Add more functions as we implement them
addTaskDirect
};

View File

@@ -0,0 +1,47 @@
/**
* tools/add-task.js
* Tool to add a new task using AI
*/
import { z } from "zod";
import {
handleApiResult,
createErrorResponse
} from "./utils.js";
import { addTaskDirect } from "../core/task-master-core.js";
/**
* Register the add-task tool with the MCP server
* @param {Object} server - FastMCP server instance
*/
export function registerAddTaskTool(server) {
server.addTool({
name: "add_task",
description: "Add a new task using AI",
parameters: z.object({
prompt: z.string().describe("Description of the task to add"),
dependencies: z.string().optional().describe("Comma-separated list of task IDs this task depends on"),
priority: z.string().optional().describe("Task priority (high, medium, low)"),
file: z.string().optional().describe("Path to the tasks file"),
projectRoot: z.string().optional().describe("Root directory of the project (default: current working directory)")
}),
execute: async ({ prompt, dependencies, priority, file, projectRoot }, log) => {
try {
log.info(`MCP add_task called with prompt: "${prompt}"`);
const result = await addTaskDirect({
prompt,
dependencies,
priority,
file,
projectRoot
}, log);
return handleApiResult(result);
} catch (error) {
log.error(`Error in add_task MCP tool: ${error.message}`);
return createErrorResponse(error.message, "ADD_TASK_ERROR");
}
}
});
}

View File

@@ -14,6 +14,7 @@ import { registerGenerateTool } from "./generate.js";
import { registerShowTaskTool } from "./show-task.js";
import { registerNextTaskTool } from "./next-task.js";
import { registerExpandTaskTool } from "./expand-task.js";
import { registerAddTaskTool } from "./add-task.js";
/**
* Register all Task Master tools with the MCP server
@@ -30,6 +31,9 @@ export function registerTaskMasterTools(server) {
registerShowTaskTool(server);
registerNextTaskTool(server);
registerExpandTaskTool(server);
registerAddTaskTool(server);
logger.info("Registered all Task Master tools with MCP server");
}
export default {

View File

@@ -604,7 +604,7 @@ Following MCP implementation standards:
- Unit test for expandTaskDirect.js
- Integration test for MCP tool
## 25. Implement add-task MCP command [in-progress]
## 25. Implement add-task MCP command [done]
### Dependencies: None
### Description: Create direct function wrapper and MCP tool for adding new tasks.
### Details:

View File

@@ -1573,7 +1573,7 @@
"title": "Implement add-task MCP command",
"description": "Create direct function wrapper and MCP tool for adding new tasks.",
"details": "Following MCP implementation standards:\n\n1. Create addTaskDirect.js in mcp-server/src/core/direct-functions/:\n - Import addTask from task-manager.js\n - Handle file paths using findTasksJsonPath utility\n - Process arguments: prompt, priority, dependencies\n - Validate inputs and handle errors with try/catch\n - Return standardized { success, data/error } object\n\n2. Export from task-master-core.js:\n - Import the function from its file\n - Add to directFunctions map\n\n3. Create add-task.js MCP tool in mcp-server/src/tools/:\n - Import z from zod for parameter schema\n - Import executeMCPToolAction from ./utils.js\n - Import addTaskDirect from task-master-core.js\n - Define parameters matching CLI options using zod schema\n - Implement registerAddTaskTool(server) with server.addTool\n - Use executeMCPToolAction in execute method\n\n4. Register in tools/index.js with tool name 'add_task'\n\n5. Add to .cursor/mcp.json with appropriate schema\n\n6. Write tests following testing guidelines:\n - Unit test for addTaskDirect.js\n - Integration test for MCP tool",
"status": "in-progress",
"status": "done",
"dependencies": [],
"parentTaskId": 23
},