Merge pull request #567 from eyaltoledano/parse-prd-research

v0.15 improvements & new features
This commit is contained in:
Eyal Toledano
2025-05-23 20:42:41 -04:00
committed by GitHub
60 changed files with 8003 additions and 645 deletions

View File

@@ -49,6 +49,24 @@ export function registerAnalyzeProjectComplexityTool(server) {
.describe(
'Path to the tasks file relative to project root (default: tasks/tasks.json).'
),
ids: z
.string()
.optional()
.describe(
'Comma-separated list of task IDs to analyze specifically (e.g., "1,3,5").'
),
from: z.coerce
.number()
.int()
.positive()
.optional()
.describe('Starting task ID in a range to analyze.'),
to: z.coerce
.number()
.int()
.positive()
.optional()
.describe('Ending task ID in a range to analyze.'),
projectRoot: z
.string()
.describe('The directory of the project. Must be an absolute path.')
@@ -107,7 +125,10 @@ export function registerAnalyzeProjectComplexityTool(server) {
outputPath: outputPath,
threshold: args.threshold,
research: args.research,
projectRoot: args.projectRoot
projectRoot: args.projectRoot,
ids: args.ids,
from: args.from,
to: args.to
},
log,
{ session }

View File

@@ -28,6 +28,7 @@ import { registerAddDependencyTool } from './add-dependency.js';
import { registerRemoveTaskTool } from './remove-task.js';
import { registerInitializeProjectTool } from './initialize-project.js';
import { registerModelsTool } from './models.js';
import { registerMoveTaskTool } from './move-task.js';
/**
* Register all Task Master tools with the MCP server
@@ -61,6 +62,7 @@ export function registerTaskMasterTools(server) {
registerRemoveTaskTool(server);
registerRemoveSubtaskTool(server);
registerClearSubtasksTool(server);
registerMoveTaskTool(server);
// Group 5: Task Analysis & Expansion
registerAnalyzeProjectComplexityTool(server);

View File

@@ -0,0 +1,129 @@
/**
* tools/move-task.js
* Tool for moving tasks or subtasks to a new position
*/
import { z } from 'zod';
import {
handleApiResult,
createErrorResponse,
withNormalizedProjectRoot
} from './utils.js';
import { moveTaskDirect } from '../core/task-master-core.js';
import { findTasksJsonPath } from '../core/utils/path-utils.js';
/**
* Register the moveTask tool with the MCP server
* @param {Object} server - FastMCP server instance
*/
export function registerMoveTaskTool(server) {
server.addTool({
name: 'move_task',
description: 'Move a task or subtask to a new position',
parameters: z.object({
from: z
.string()
.describe(
'ID of the task/subtask to move (e.g., "5" or "5.2"). Can be comma-separated to move multiple tasks (e.g., "5,6,7")'
),
to: z
.string()
.describe(
'ID of the destination (e.g., "7" or "7.3"). Must match the number of source IDs if comma-separated'
),
file: z.string().optional().describe('Custom path to tasks.json file'),
projectRoot: z
.string()
.optional()
.describe(
'Root directory of the project (typically derived from session)'
)
}),
execute: withNormalizedProjectRoot(async (args, { log, session }) => {
try {
// Find tasks.json path if not provided
let tasksJsonPath = args.file;
if (!tasksJsonPath) {
tasksJsonPath = findTasksJsonPath(args, log);
}
// Parse comma-separated IDs
const fromIds = args.from.split(',').map((id) => id.trim());
const toIds = args.to.split(',').map((id) => id.trim());
// Validate matching IDs count
if (fromIds.length !== toIds.length) {
return createErrorResponse(
'The number of source and destination IDs must match',
'MISMATCHED_ID_COUNT'
);
}
// If moving multiple tasks
if (fromIds.length > 1) {
const results = [];
// Move tasks one by one, only generate files on the last move
for (let i = 0; i < fromIds.length; i++) {
const fromId = fromIds[i];
const toId = toIds[i];
// Skip if source and destination are the same
if (fromId === toId) {
log.info(`Skipping ${fromId} -> ${toId} (same ID)`);
continue;
}
const shouldGenerateFiles = i === fromIds.length - 1;
const result = await moveTaskDirect(
{
sourceId: fromId,
destinationId: toId,
tasksJsonPath,
projectRoot: args.projectRoot
},
log,
{ session }
);
if (!result.success) {
log.error(
`Failed to move ${fromId} to ${toId}: ${result.error.message}`
);
} else {
results.push(result.data);
}
}
return {
success: true,
data: {
moves: results,
message: `Successfully moved ${results.length} tasks`
}
};
} else {
// Moving a single task
return handleApiResult(
await moveTaskDirect(
{
sourceId: args.from,
destinationId: args.to,
tasksJsonPath,
projectRoot: args.projectRoot
},
log,
{ session }
),
log
);
}
} catch (error) {
return createErrorResponse(
`Failed to move task: ${error.message}`,
'MOVE_TASK_ERROR'
);
}
})
});
}

View File

@@ -49,6 +49,13 @@ export function registerParsePRDTool(server) {
.optional()
.default(false)
.describe('Append generated tasks to existing file.'),
research: z
.boolean()
.optional()
.default(false)
.describe(
'Use the research model for research-backed task generation, providing more comprehensive, accurate and up-to-date task details.'
),
projectRoot: z
.string()
.describe('The directory of the project. Must be an absolute path.')
@@ -68,6 +75,7 @@ export function registerParsePRDTool(server) {
numTasks: args.numTasks,
force: args.force,
append: args.append,
research: args.research,
projectRoot: args.projectRoot
},
log,