/**
* tools/update.js
* Tool to update tasks based on new context/prompt
*/
import {
createErrorResponse,
handleApiResult,
withNormalizedProjectRoot
} from '@tm/mcp';
import { z } from 'zod';
import { resolveTag } from '../../../scripts/modules/utils.js';
import { updateTasksDirect } from '../core/task-master-core.js';
import { findTasksPath } from '../core/utils/path-utils.js';
/**
* Register the update tool with the MCP server
* @param {Object} server - FastMCP server instance
*/
export function registerUpdateTool(server) {
server.addTool({
name: 'update',
description:
"Update multiple upcoming tasks (with ID >= 'from' ID) based on new context or changes provided in the prompt. Use 'update_task' instead for a single specific task or 'update_subtask' for subtasks.",
parameters: z.object({
from: z
.string()
.describe(
"Task ID from which to start updating (inclusive). IMPORTANT: This tool uses 'from', not 'id'"
),
prompt: z
.string()
.describe('Explanation of changes or new context to apply'),
research: z
.boolean()
.optional()
.describe('Use Perplexity AI for research-backed updates'),
file: z
.string()
.optional()
.describe('Path to the tasks file relative to project root'),
projectRoot: z
.string()
.optional()
.describe(
'The directory of the project. (Optional, usually from session)'
),
tag: z.string().optional().describe('Tag context to operate on')
}),
execute: withNormalizedProjectRoot(async (args, { log, session }) => {
const toolName = 'update';
const { from, prompt, research, file, projectRoot, tag } = args;
const resolvedTag = resolveTag({
projectRoot: args.projectRoot,
tag: args.tag
});
try {
log.info(
`Executing ${toolName} tool with normalized root: ${projectRoot}`
);
let tasksJsonPath;
try {
tasksJsonPath = findTasksPath({ projectRoot, file }, log);
log.info(`${toolName}: Resolved tasks path: ${tasksJsonPath}`);
} catch (error) {
log.error(`${toolName}: Error finding tasks.json: ${error.message}`);
return createErrorResponse(
`Failed to find tasks.json within project root '${projectRoot}': ${error.message}`
);
}
const result = await updateTasksDirect(
{
tasksJsonPath: tasksJsonPath,
from: from,
prompt: prompt,
research: research,
projectRoot: projectRoot,
tag: resolvedTag
},
log,
{ session }
);
log.info(
`${toolName}: Direct function result: success=${result.success}`
);
return handleApiResult({
result,
log: log,
errorPrefix: 'Error updating tasks',
projectRoot: args.projectRoot
});
} catch (error) {
log.error(
`Critical error in ${toolName} tool execute: ${error.message}`
);
return createErrorResponse(
`Internal tool error (${toolName}): ${error.message}`
);
}
})
});
}