From 535fb5be71542ba3a052ca77fb1808f305bea044 Mon Sep 17 00:00:00 2001 From: Eyal Toledano Date: Mon, 31 Mar 2025 13:55:07 -0400 Subject: [PATCH] Implement validate-dependencies MCP command for checking dependency validity --- .changeset/two-bats-smoke.md | 5 +- .../direct-functions/validate-dependencies.js | 55 +++++++++++++++++++ mcp-server/src/core/task-master-core.js | 7 ++- mcp-server/src/tools/index.js | 46 ++++++++++------ mcp-server/src/tools/validate-dependencies.js | 34 ++++++++++++ tasks/task_023.txt | 2 +- tasks/tasks.json | 2 +- 7 files changed, 127 insertions(+), 24 deletions(-) create mode 100644 mcp-server/src/core/direct-functions/validate-dependencies.js create mode 100644 mcp-server/src/tools/validate-dependencies.js diff --git a/.changeset/two-bats-smoke.md b/.changeset/two-bats-smoke.md index 0524cd15..62679538 100644 --- a/.changeset/two-bats-smoke.md +++ b/.changeset/two-bats-smoke.md @@ -13,9 +13,10 @@ - Implement add-task MCP command for creating new tasks using AI assistance - Implement add-subtask MCP command for adding subtasks to existing tasks - Implement remove-subtask MCP command for removing subtasks from parent tasks -- Implement analyze-complexity MCP command for analyzing task complexity and generating recommendations +- Implement expand-all MCP command for expanding all tasks into subtasks +- Implement analyze-complexity MCP command for analyzing task complexity - Implement clear-subtasks MCP command for clearing subtasks from parent tasks -- Implement expand-all MCP command for expanding all pending tasks with subtasks - Implement remove-dependency MCP command for removing dependencies from tasks +- Implement validate-dependencies MCP command for checking validity of task dependencies - 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) - Enhance task show view with a color-coded progress bar for visualizing subtask completion percentage diff --git a/mcp-server/src/core/direct-functions/validate-dependencies.js b/mcp-server/src/core/direct-functions/validate-dependencies.js new file mode 100644 index 00000000..27fbf7dd --- /dev/null +++ b/mcp-server/src/core/direct-functions/validate-dependencies.js @@ -0,0 +1,55 @@ +/** + * Direct function wrapper for validateDependenciesCommand + */ + +import { validateDependenciesCommand } from '../../../../scripts/modules/dependency-manager.js'; +import { findTasksJsonPath } from '../utils/path-utils.js'; +import fs from 'fs'; + +/** + * Validate dependencies in tasks.json + * @param {Object} args - Function arguments + * @param {string} [args.file] - Path to the tasks file + * @param {string} [args.projectRoot] - Project root directory + * @param {Object} log - Logger object + * @returns {Promise<{success: boolean, data?: Object, error?: {code: string, message: string}}>} + */ +export async function validateDependenciesDirect(args, log) { + try { + log.info(`Validating dependencies in tasks...`); + + // Determine the tasks file path + const tasksPath = args.file || await findTasksJsonPath(args.projectRoot); + + // Verify the file exists + if (!fs.existsSync(tasksPath)) { + return { + success: false, + error: { + code: 'FILE_NOT_FOUND', + message: `Tasks file not found at ${tasksPath}` + } + }; + } + + // Call the original command function + await validateDependenciesCommand(tasksPath); + + return { + success: true, + data: { + message: 'Dependencies validated successfully', + tasksPath + } + }; + } catch (error) { + log.error(`Error validating dependencies: ${error.message}`); + return { + success: false, + error: { + code: 'VALIDATION_ERROR', + message: error.message + } + }; + } +} \ No newline at end of file diff --git a/mcp-server/src/core/task-master-core.js b/mcp-server/src/core/task-master-core.js index 1e505714..c7067ecb 100644 --- a/mcp-server/src/core/task-master-core.js +++ b/mcp-server/src/core/task-master-core.js @@ -23,6 +23,7 @@ import { analyzeTaskComplexityDirect } from './direct-functions/analyze-task-com import { clearSubtasksDirect } from './direct-functions/clear-subtasks.js'; import { expandAllTasksDirect } from './direct-functions/expand-all-tasks.js'; import { removeDependencyDirect } from './direct-functions/remove-dependency.js'; +import { validateDependenciesDirect } from './direct-functions/validate-dependencies.js'; // Re-export utility functions export { findTasksJsonPath } from './utils/path-utils.js'; @@ -46,7 +47,8 @@ export const directFunctions = new Map([ ['analyzeTaskComplexityDirect', analyzeTaskComplexityDirect], ['clearSubtasksDirect', clearSubtasksDirect], ['expandAllTasksDirect', expandAllTasksDirect], - ['removeDependencyDirect', removeDependencyDirect] + ['removeDependencyDirect', removeDependencyDirect], + ['validateDependenciesDirect', validateDependenciesDirect] ]); // Re-export all direct function implementations @@ -68,5 +70,6 @@ export { analyzeTaskComplexityDirect, clearSubtasksDirect, expandAllTasksDirect, - removeDependencyDirect + removeDependencyDirect, + validateDependenciesDirect }; \ No newline at end of file diff --git a/mcp-server/src/tools/index.js b/mcp-server/src/tools/index.js index 5b95bc6c..4c7fd7df 100644 --- a/mcp-server/src/tools/index.js +++ b/mcp-server/src/tools/index.js @@ -21,31 +21,41 @@ import { registerAnalyzeTool } from "./analyze.js"; import { registerClearSubtasksTool } from "./clear-subtasks.js"; import { registerExpandAllTool } from "./expand-all.js"; import { registerRemoveDependencyTool } from "./remove-dependency.js"; +import { registerValidateDependenciesTool } from "./validate-dependencies.js"; /** * Register all Task Master tools with the MCP server * @param {Object} server - FastMCP server instance */ export function registerTaskMasterTools(server) { - registerListTasksTool(server); - registerSetTaskStatusTool(server); - registerParsePRDTool(server); - registerUpdateTool(server); - registerUpdateTaskTool(server); - registerUpdateSubtaskTool(server); - registerGenerateTool(server); - registerShowTaskTool(server); - registerNextTaskTool(server); - registerExpandTaskTool(server); - registerAddTaskTool(server); - registerAddSubtaskTool(server); - registerRemoveSubtaskTool(server); - registerAnalyzeTool(server); - registerClearSubtasksTool(server); - registerExpandAllTool(server); - registerRemoveDependencyTool(server); + logger.info("Registering Task Master tools with MCP server"); - logger.info("Registered all Task Master tools with MCP server"); + try { + // Register each tool + registerListTasksTool(server); + registerSetTaskStatusTool(server); + registerParsePRDTool(server); + registerUpdateTool(server); + registerUpdateTaskTool(server); + registerUpdateSubtaskTool(server); + registerGenerateTool(server); + registerShowTaskTool(server); + registerNextTaskTool(server); + registerExpandTaskTool(server); + registerAddTaskTool(server); + registerAddSubtaskTool(server); + registerRemoveSubtaskTool(server); + registerAnalyzeTool(server); + registerClearSubtasksTool(server); + registerExpandAllTool(server); + registerRemoveDependencyTool(server); + registerValidateDependenciesTool(server); + + logger.info("Successfully registered all Task Master tools"); + } catch (error) { + logger.error(`Error registering Task Master tools: ${error.message}`); + throw error; + } } export default { diff --git a/mcp-server/src/tools/validate-dependencies.js b/mcp-server/src/tools/validate-dependencies.js new file mode 100644 index 00000000..ded8bd5a --- /dev/null +++ b/mcp-server/src/tools/validate-dependencies.js @@ -0,0 +1,34 @@ +/** + * tools/validate-dependencies.js + * Tool for validating task dependencies + */ + +import { z } from "zod"; +import { + handleApiResult, + createErrorResponse +} from "./utils.js"; +import { validateDependenciesDirect } from "../core/task-master-core.js"; + +/** + * Register the validateDependencies tool with the MCP server + * @param {Object} server - FastMCP server instance + */ +export function registerValidateDependenciesTool(server) { + server.addTool({ + name: "validate_dependencies", + description: "Identify invalid dependencies in tasks without fixing them", + parameters: z.object({ + file: z.string().optional().describe("Path to the tasks file"), + projectRoot: z.string().optional().describe("Root directory of the project (default: current working directory)") + }), + handler: async ({ file, projectRoot }, { logger }) => { + try { + const result = await validateDependenciesDirect({ file, projectRoot }, logger); + return handleApiResult(result); + } catch (error) { + return createErrorResponse(error); + } + } + }); +} \ No newline at end of file diff --git a/tasks/task_023.txt b/tasks/task_023.txt index 3894a777..40a2d0cd 100644 --- a/tasks/task_023.txt +++ b/tasks/task_023.txt @@ -884,7 +884,7 @@ Analyze and refactor the project root handling mechanism to ensure consistent fi ### Details: -## 41. Implement validate-dependencies MCP command [pending] +## 41. Implement validate-dependencies MCP command [done] ### Dependencies: 23.31, 23.39, 23.40 ### Description: Create MCP tool implementation for the validate-dependencies command ### Details: diff --git a/tasks/tasks.json b/tasks/tasks.json index 2e04cc06..93054c62 100644 --- a/tasks/tasks.json +++ b/tasks/tasks.json @@ -1723,7 +1723,7 @@ "title": "Implement validate-dependencies MCP command", "description": "Create MCP tool implementation for the validate-dependencies command", "details": "", - "status": "pending", + "status": "done", "dependencies": [ "23.31", "23.39",