Problem: The MCP tool previously handled project root acquisition and path resolution within its method, leading to potential inconsistencies and repetition. Solution: Refactored the tool () to utilize the new Higher-Order Function (HOF) from . Specific Changes: - Imported HOF. - Updated the Zod schema for the parameter to be optional, as the HOF handles deriving it from the session if not provided. - Wrapped the entire function body with the HOF. - Removed the manual call to from within the function body. - Destructured the from the object received by the wrapped function, ensuring it's the normalized path provided by the HOF. - Used the normalized variable when calling and when passing arguments to . This change standardizes project root handling for the tool, simplifies its method, and ensures consistent path normalization. This serves as the pattern for refactoring other MCP tools.
95 lines
2.6 KiB
JavaScript
95 lines
2.6 KiB
JavaScript
/**
|
|
* tools/update.js
|
|
* Tool to update tasks based on new context/prompt
|
|
*/
|
|
|
|
import { z } from 'zod';
|
|
import {
|
|
handleApiResult,
|
|
createErrorResponse,
|
|
withNormalizedProjectRoot
|
|
} from './utils.js';
|
|
import { updateTasksDirect } from '../core/task-master-core.js';
|
|
import { findTasksJsonPath } 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)'
|
|
)
|
|
}),
|
|
execute: withNormalizedProjectRoot(async (args, { log, session }) => {
|
|
const toolName = 'update';
|
|
const { from, prompt, research, file, projectRoot } = args;
|
|
|
|
try {
|
|
log.info(
|
|
`Executing ${toolName} tool with normalized root: ${projectRoot}`
|
|
);
|
|
|
|
let tasksJsonPath;
|
|
try {
|
|
tasksJsonPath = findTasksJsonPath({ 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
|
|
},
|
|
log,
|
|
{ session }
|
|
);
|
|
|
|
log.info(
|
|
`${toolName}: Direct function result: success=${result.success}`
|
|
);
|
|
return handleApiResult(result, log, 'Error updating tasks');
|
|
} catch (error) {
|
|
log.error(
|
|
`Critical error in ${toolName} tool execute: ${error.message}`
|
|
);
|
|
return createErrorResponse(
|
|
`Internal tool error (${toolName}): ${error.message}`
|
|
);
|
|
}
|
|
})
|
|
});
|
|
}
|