Files
claude-task-master/mcp-server/src/tools/get-task.js

116 lines
3.1 KiB
JavaScript

/**
* tools/get-task.js
* Tool to get task details by ID
*/
import { z } from 'zod';
import {
handleApiResult,
createErrorResponse,
withNormalizedProjectRoot
} from './utils.js';
import { showTaskDirect } from '../core/task-master-core.js';
import { findTasksJsonPath } from '../core/utils/path-utils.js';
/**
* Custom processor function that removes allTasks from the response
* @param {Object} data - The data returned from showTaskDirect
* @returns {Object} - The processed data with allTasks removed
*/
function processTaskResponse(data) {
if (!data) return data;
// If we have the expected structure with task and allTasks
if (typeof data === 'object' && data !== null && data.id && data.title) {
// If the data itself looks like the task object, return it
return data;
} else if (data.task) {
return data.task;
}
// If structure is unexpected, return as is
return data;
}
/**
* Register the get-task tool with the MCP server
* @param {Object} server - FastMCP server instance
*/
export function registerShowTaskTool(server) {
server.addTool({
name: 'get_task',
description: 'Get detailed information about a specific task',
parameters: z.object({
id: z.string().describe('Task ID to get'),
status: z
.string()
.optional()
.describe("Filter subtasks by status (e.g., 'pending', 'done')"),
file: z
.string()
.optional()
.describe('Path to the tasks file relative to project root'),
projectRoot: z
.string()
.optional()
.describe(
'Absolute path to the project root directory (Optional, usually from session)'
)
}),
execute: withNormalizedProjectRoot(async (args, { log }) => {
const { id, file, status, projectRoot } = args;
try {
log.info(
`Getting task details for ID: ${id}${status ? ` (filtering subtasks by status: ${status})` : ''} in root: ${projectRoot}`
);
// Resolve the path to tasks.json using the NORMALIZED projectRoot from args
let tasksJsonPath;
try {
tasksJsonPath = findTasksJsonPath(
{ projectRoot: projectRoot, file: file },
log
);
log.info(`Resolved tasks path: ${tasksJsonPath}`);
} catch (error) {
log.error(`Error finding tasks.json: ${error.message}`);
return createErrorResponse(
`Failed to find tasks.json: ${error.message}`
);
}
// Call the direct function, passing the normalized projectRoot
const result = await showTaskDirect(
{
tasksJsonPath: tasksJsonPath,
id: id,
status: status,
projectRoot: projectRoot
},
log
);
if (result.success) {
log.info(
`Successfully retrieved task details for ID: ${args.id}${result.fromCache ? ' (from cache)' : ''}`
);
} else {
log.error(`Failed to get task: ${result.error.message}`);
}
// Use our custom processor function
return handleApiResult(
result,
log,
'Error retrieving task details',
processTaskResponse
);
} catch (error) {
log.error(`Error in get-task tool: ${error.message}\n${error.stack}`);
return createErrorResponse(`Failed to get task: ${error.message}`);
}
})
});
}