diff --git a/.cursor/mcp.json b/.cursor/mcp.json index 3b7160ae..e69de29b 100644 --- a/.cursor/mcp.json +++ b/.cursor/mcp.json @@ -1,8 +0,0 @@ -{ - "mcpServers": { - "taskMaster": { - "command": "node", - "args": ["mcp-server/server.js"] - } - } -} diff --git a/README-task-master.md b/README-task-master.md index cf46772c..26cce92b 100644 --- a/README-task-master.md +++ b/README-task-master.md @@ -1,4 +1,5 @@ # Task Master + ### by [@eyaltoledano](https://x.com/eyaltoledano) A task management system for AI-driven development with Claude, designed to work seamlessly with Cursor AI. @@ -15,9 +16,11 @@ A task management system for AI-driven development with Claude, designed to work The script can be configured through environment variables in a `.env` file at the root of the project: ### Required Configuration + - `ANTHROPIC_API_KEY`: Your Anthropic API key for Claude ### Optional Configuration + - `MODEL`: Specify which Claude model to use (default: "claude-3-7-sonnet-20250219") - `MAX_TOKENS`: Maximum tokens for model responses (default: 4000) - `TEMPERATURE`: Temperature for model responses (default: 0.7) @@ -123,6 +126,21 @@ Claude Task Master is designed to work seamlessly with [Cursor AI](https://www.c 3. Place your PRD document in the `scripts/` directory (e.g., `scripts/prd.txt`) 4. Open Cursor's AI chat and switch to Agent mode +### Setting up MCP in Cursor + +To enable enhanced task management capabilities directly within Cursor using the Model Control Protocol (MCP): + +1. Go to Cursor settings +2. Navigate to the MCP section +3. Click on "Add New MCP Server" +4. Configure with the following details: + - Name: "Task Master" + - Type: "Command" + - Command: "npx -y task-master-mcp" +5. Save the settings + +Once configured, you can interact with Task Master's task management commands directly through Cursor's interface, providing a more integrated experience. + ### Initial Task Generation In Cursor's AI chat, instruct the agent to generate tasks from your PRD: @@ -132,11 +150,13 @@ Please use the task-master parse-prd command to generate tasks from my PRD. The ``` The agent will execute: + ```bash task-master parse-prd scripts/prd.txt ``` This will: + - Parse your PRD document - Generate a structured `tasks.json` file with tasks, dependencies, priorities, and test strategies - The agent will understand this process due to the Cursor rules @@ -150,6 +170,7 @@ Please generate individual task files from tasks.json ``` The agent will execute: + ```bash task-master generate ``` @@ -169,6 +190,7 @@ What tasks are available to work on next? ``` The agent will: + - Run `task-master list` to see all tasks - Run `task-master next` to determine the next task to work on - Analyze dependencies to determine which tasks are ready to be worked on @@ -178,12 +200,14 @@ The agent will: ### 2. Task Implementation When implementing a task, the agent will: + - Reference the task's details section for implementation specifics - Consider dependencies on previous tasks - Follow the project's coding standards - Create appropriate tests based on the task's testStrategy You can ask: + ``` Let's implement task 3. What does it involve? ``` @@ -191,6 +215,7 @@ Let's implement task 3. What does it involve? ### 3. Task Verification Before marking a task as complete, verify it according to: + - The task's specified testStrategy - Any automated tests in the codebase - Manual verification if required @@ -204,6 +229,7 @@ Task 3 is now complete. Please update its status. ``` The agent will execute: + ```bash task-master set-status --id=3 --status=done ``` @@ -211,16 +237,19 @@ task-master set-status --id=3 --status=done ### 5. Handling Implementation Drift If during implementation, you discover that: + - The current approach differs significantly from what was planned - Future tasks need to be modified due to current implementation choices - New dependencies or requirements have emerged Tell the agent: + ``` We've changed our approach. We're now using Express instead of Fastify. Please update all future tasks to reflect this change. ``` The agent will execute: + ```bash task-master update --from=4 --prompt="Now we are using Express instead of Fastify." ``` @@ -236,36 +265,43 @@ Task 5 seems complex. Can you break it down into subtasks? ``` The agent will execute: + ```bash task-master expand --id=5 --num=3 ``` You can provide additional context: + ``` Please break down task 5 with a focus on security considerations. ``` The agent will execute: + ```bash task-master expand --id=5 --prompt="Focus on security aspects" ``` You can also expand all pending tasks: + ``` Please break down all pending tasks into subtasks. ``` The agent will execute: + ```bash task-master expand --all ``` For research-backed subtask generation using Perplexity AI: + ``` Please break down task 5 using research-backed generation. ``` The agent will execute: + ```bash task-master expand --id=5 --research ``` @@ -275,6 +311,7 @@ task-master expand --id=5 --research Here's a comprehensive reference of all available commands: ### Parse PRD + ```bash # Parse a PRD file and generate tasks task-master parse-prd @@ -284,6 +321,7 @@ task-master parse-prd --num-tasks=10 ``` ### List Tasks + ```bash # List all tasks task-master list @@ -299,12 +337,14 @@ task-master list --status= --with-subtasks ``` ### Show Next Task + ```bash # Show the next task to work on based on dependencies and status task-master next ``` ### Show Specific Task + ```bash # Show details of a specific task task-master show @@ -316,18 +356,21 @@ task-master show 1.2 ``` ### Update Tasks + ```bash # Update tasks from a specific ID and provide context task-master update --from= --prompt="" ``` ### Generate Task Files + ```bash # Generate individual task files from tasks.json task-master generate ``` ### Set Task Status + ```bash # Set status of a single task task-master set-status --id= --status= @@ -342,6 +385,7 @@ task-master set-status --id=1.1,1.2 --status= When marking a task as "done", all of its subtasks will automatically be marked as "done" as well. ### Expand Tasks + ```bash # Expand a specific task with subtasks task-master expand --id= --num= @@ -363,6 +407,7 @@ task-master expand --all --research ``` ### Clear Subtasks + ```bash # Clear subtasks from a specific task task-master clear-subtasks --id= @@ -375,6 +420,7 @@ task-master clear-subtasks --all ``` ### Analyze Task Complexity + ```bash # Analyze complexity of all tasks task-master analyze-complexity @@ -396,6 +442,7 @@ task-master analyze-complexity --research ``` ### View Complexity Report + ```bash # Display the task complexity analysis report task-master complexity-report @@ -405,6 +452,7 @@ task-master complexity-report --file=my-report.json ``` ### Managing Task Dependencies + ```bash # Add a dependency to a task task-master add-dependency --id= --depends-on= @@ -420,6 +468,7 @@ task-master fix-dependencies ``` ### Add a New Task + ```bash # Add a new task using AI task-master add-task --prompt="Description of the new task" @@ -436,6 +485,7 @@ task-master add-task --prompt="Description" --priority=high ### Analyzing Task Complexity The `analyze-complexity` command: + - Analyzes each task using AI to assess its complexity on a scale of 1-10 - Recommends optimal number of subtasks based on configured DEFAULT_SUBTASKS - Generates tailored prompts for expanding each task @@ -443,6 +493,7 @@ The `analyze-complexity` command: - Saves the report to scripts/task-complexity-report.json by default The generated report contains: + - Complexity analysis for each task (scored 1-10) - Recommended number of subtasks based on complexity - AI-generated expansion prompts customized for each task @@ -451,6 +502,7 @@ The generated report contains: ### Viewing Complexity Report The `complexity-report` command: + - Displays a formatted, easy-to-read version of the complexity analysis report - Shows tasks organized by complexity score (highest to lowest) - Provides complexity distribution statistics (low, medium, high) @@ -463,12 +515,14 @@ The `complexity-report` command: The `expand` command automatically checks for and uses the complexity report: When a complexity report exists: + - Tasks are automatically expanded using the recommended subtask count and prompts - When expanding all tasks, they're processed in order of complexity (highest first) - Research-backed generation is preserved from the complexity analysis - You can still override recommendations with explicit command-line options Example workflow: + ```bash # Generate the complexity analysis report with research capabilities task-master analyze-complexity --research @@ -485,6 +539,7 @@ task-master expand --all ### Finding the Next Task The `next` command: + - Identifies tasks that are pending/in-progress and have all dependencies satisfied - Prioritizes tasks by priority level, dependency count, and task ID - Displays comprehensive information about the selected task: @@ -499,6 +554,7 @@ The `next` command: ### Viewing Specific Task Details The `show` command: + - Displays comprehensive details about a specific task or subtask - Shows task status, priority, dependencies, and detailed implementation notes - For parent tasks, displays all subtasks and their status @@ -529,43 +585,51 @@ The `show` command: ## Example Cursor AI Interactions ### Starting a new project + ``` -I've just initialized a new project with Claude Task Master. I have a PRD at scripts/prd.txt. +I've just initialized a new project with Claude Task Master. I have a PRD at scripts/prd.txt. Can you help me parse it and set up the initial tasks? ``` ### Working on tasks + ``` What's the next task I should work on? Please consider dependencies and priorities. ``` ### Implementing a specific task + ``` I'd like to implement task 4. Can you help me understand what needs to be done and how to approach it? ``` ### Managing subtasks + ``` I need to regenerate the subtasks for task 3 with a different approach. Can you help me clear and regenerate them? ``` ### Handling changes + ``` We've decided to use MongoDB instead of PostgreSQL. Can you update all future tasks to reflect this change? ``` ### Completing work + ``` -I've finished implementing the authentication system described in task 2. All tests are passing. +I've finished implementing the authentication system described in task 2. All tests are passing. Please mark it as complete and tell me what I should work on next. ``` ### Analyzing complexity + ``` Can you analyze the complexity of our tasks to help me understand which ones need to be broken down further? ``` ### Viewing complexity report + ``` Can you show me the complexity report in a more readable format? -``` \ No newline at end of file +``` diff --git a/README.md b/README.md index 6e24c651..b0803a99 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # Task Master + ### by [@eyaltoledano](https://x.com/eyaltoledano) A task management system for AI-driven development with Claude, designed to work seamlessly with Cursor AI. @@ -15,9 +16,11 @@ A task management system for AI-driven development with Claude, designed to work The script can be configured through environment variables in a `.env` file at the root of the project: ### Required Configuration + - `ANTHROPIC_API_KEY`: Your Anthropic API key for Claude ### Optional Configuration + - `MODEL`: Specify which Claude model to use (default: "claude-3-7-sonnet-20250219") - `MAX_TOKENS`: Maximum tokens for model responses (default: 4000) - `TEMPERATURE`: Temperature for model responses (default: 0.7) @@ -123,6 +126,21 @@ Claude Task Master is designed to work seamlessly with [Cursor AI](https://www.c 3. Place your PRD document in the `scripts/` directory (e.g., `scripts/prd.txt`) 4. Open Cursor's AI chat and switch to Agent mode +### Setting up MCP in Cursor + +To enable enhanced task management capabilities directly within Cursor using the Model Control Protocol (MCP): + +1. Go to Cursor settings +2. Navigate to the MCP section +3. Click on "Add New MCP Server" +4. Configure with the following details: + - Name: "Task Master" + - Type: "Command" + - Command: "npx -y task-master-mcp" +5. Save the settings + +Once configured, you can interact with Task Master's task management commands directly through Cursor's interface, providing a more integrated experience. + ### Initial Task Generation In Cursor's AI chat, instruct the agent to generate tasks from your PRD: @@ -132,11 +150,13 @@ Please use the task-master parse-prd command to generate tasks from my PRD. The ``` The agent will execute: + ```bash task-master parse-prd scripts/prd.txt ``` This will: + - Parse your PRD document - Generate a structured `tasks.json` file with tasks, dependencies, priorities, and test strategies - The agent will understand this process due to the Cursor rules @@ -150,6 +170,7 @@ Please generate individual task files from tasks.json ``` The agent will execute: + ```bash task-master generate ``` @@ -169,6 +190,7 @@ What tasks are available to work on next? ``` The agent will: + - Run `task-master list` to see all tasks - Run `task-master next` to determine the next task to work on - Analyze dependencies to determine which tasks are ready to be worked on @@ -178,12 +200,14 @@ The agent will: ### 2. Task Implementation When implementing a task, the agent will: + - Reference the task's details section for implementation specifics - Consider dependencies on previous tasks - Follow the project's coding standards - Create appropriate tests based on the task's testStrategy You can ask: + ``` Let's implement task 3. What does it involve? ``` @@ -191,6 +215,7 @@ Let's implement task 3. What does it involve? ### 3. Task Verification Before marking a task as complete, verify it according to: + - The task's specified testStrategy - Any automated tests in the codebase - Manual verification if required @@ -204,6 +229,7 @@ Task 3 is now complete. Please update its status. ``` The agent will execute: + ```bash task-master set-status --id=3 --status=done ``` @@ -211,16 +237,19 @@ task-master set-status --id=3 --status=done ### 5. Handling Implementation Drift If during implementation, you discover that: + - The current approach differs significantly from what was planned - Future tasks need to be modified due to current implementation choices - New dependencies or requirements have emerged Tell the agent: + ``` We've changed our approach. We're now using Express instead of Fastify. Please update all future tasks to reflect this change. ``` The agent will execute: + ```bash task-master update --from=4 --prompt="Now we are using Express instead of Fastify." ``` @@ -236,36 +265,43 @@ Task 5 seems complex. Can you break it down into subtasks? ``` The agent will execute: + ```bash task-master expand --id=5 --num=3 ``` You can provide additional context: + ``` Please break down task 5 with a focus on security considerations. ``` The agent will execute: + ```bash task-master expand --id=5 --prompt="Focus on security aspects" ``` You can also expand all pending tasks: + ``` Please break down all pending tasks into subtasks. ``` The agent will execute: + ```bash task-master expand --all ``` For research-backed subtask generation using Perplexity AI: + ``` Please break down task 5 using research-backed generation. ``` The agent will execute: + ```bash task-master expand --id=5 --research ``` @@ -275,6 +311,7 @@ task-master expand --id=5 --research Here's a comprehensive reference of all available commands: ### Parse PRD + ```bash # Parse a PRD file and generate tasks task-master parse-prd @@ -284,6 +321,7 @@ task-master parse-prd --num-tasks=10 ``` ### List Tasks + ```bash # List all tasks task-master list @@ -299,12 +337,14 @@ task-master list --status= --with-subtasks ``` ### Show Next Task + ```bash # Show the next task to work on based on dependencies and status task-master next ``` ### Show Specific Task + ```bash # Show details of a specific task task-master show @@ -316,18 +356,21 @@ task-master show 1.2 ``` ### Update Tasks + ```bash # Update tasks from a specific ID and provide context task-master update --from= --prompt="" ``` ### Generate Task Files + ```bash # Generate individual task files from tasks.json task-master generate ``` ### Set Task Status + ```bash # Set status of a single task task-master set-status --id= --status= @@ -342,6 +385,7 @@ task-master set-status --id=1.1,1.2 --status= When marking a task as "done", all of its subtasks will automatically be marked as "done" as well. ### Expand Tasks + ```bash # Expand a specific task with subtasks task-master expand --id= --num= @@ -363,6 +407,7 @@ task-master expand --all --research ``` ### Clear Subtasks + ```bash # Clear subtasks from a specific task task-master clear-subtasks --id= @@ -375,6 +420,7 @@ task-master clear-subtasks --all ``` ### Analyze Task Complexity + ```bash # Analyze complexity of all tasks task-master analyze-complexity @@ -396,6 +442,7 @@ task-master analyze-complexity --research ``` ### View Complexity Report + ```bash # Display the task complexity analysis report task-master complexity-report @@ -405,6 +452,7 @@ task-master complexity-report --file=my-report.json ``` ### Managing Task Dependencies + ```bash # Add a dependency to a task task-master add-dependency --id= --depends-on= @@ -420,6 +468,7 @@ task-master fix-dependencies ``` ### Add a New Task + ```bash # Add a new task using AI task-master add-task --prompt="Description of the new task" @@ -866,6 +915,7 @@ task-master add-task --prompt="Description" --priority=high ### Analyzing Task Complexity The `analyze-complexity` command: + - Analyzes each task using AI to assess its complexity on a scale of 1-10 - Recommends optimal number of subtasks based on configured DEFAULT_SUBTASKS - Generates tailored prompts for expanding each task @@ -873,6 +923,7 @@ The `analyze-complexity` command: - Saves the report to scripts/task-complexity-report.json by default The generated report contains: + - Complexity analysis for each task (scored 1-10) - Recommended number of subtasks based on complexity - AI-generated expansion prompts customized for each task @@ -881,6 +932,7 @@ The generated report contains: ### Viewing Complexity Report The `complexity-report` command: + - Displays a formatted, easy-to-read version of the complexity analysis report - Shows tasks organized by complexity score (highest to lowest) - Provides complexity distribution statistics (low, medium, high) @@ -893,12 +945,14 @@ The `complexity-report` command: The `expand` command automatically checks for and uses the complexity report: When a complexity report exists: + - Tasks are automatically expanded using the recommended subtask count and prompts - When expanding all tasks, they're processed in order of complexity (highest first) - Research-backed generation is preserved from the complexity analysis - You can still override recommendations with explicit command-line options Example workflow: + ```bash # Generate the complexity analysis report with research capabilities task-master analyze-complexity --research @@ -915,6 +969,7 @@ task-master expand --all ### Finding the Next Task The `next` command: + - Identifies tasks that are pending/in-progress and have all dependencies satisfied - Prioritizes tasks by priority level, dependency count, and task ID - Displays comprehensive information about the selected task: @@ -929,6 +984,7 @@ The `next` command: ### Viewing Specific Task Details The `show` command: + - Displays comprehensive details about a specific task or subtask - Shows task status, priority, dependencies, and detailed implementation notes - For parent tasks, displays all subtasks and their status @@ -959,43 +1015,51 @@ The `show` command: ## Example Cursor AI Interactions ### Starting a new project + ``` -I've just initialized a new project with Claude Task Master. I have a PRD at scripts/prd.txt. +I've just initialized a new project with Claude Task Master. I have a PRD at scripts/prd.txt. Can you help me parse it and set up the initial tasks? ``` ### Working on tasks + ``` What's the next task I should work on? Please consider dependencies and priorities. ``` ### Implementing a specific task + ``` I'd like to implement task 4. Can you help me understand what needs to be done and how to approach it? ``` ### Managing subtasks + ``` I need to regenerate the subtasks for task 3 with a different approach. Can you help me clear and regenerate them? ``` ### Handling changes + ``` We've decided to use MongoDB instead of PostgreSQL. Can you update all future tasks to reflect this change? ``` ### Completing work + ``` -I've finished implementing the authentication system described in task 2. All tests are passing. +I've finished implementing the authentication system described in task 2. All tests are passing. Please mark it as complete and tell me what I should work on next. ``` ### Analyzing complexity + ``` Can you analyze the complexity of our tasks to help me understand which ones need to be broken down further? ``` ### Viewing complexity report + ``` Can you show me the complexity report in a more readable format? -``` \ No newline at end of file +``` diff --git a/mcp-server/README.md b/mcp-server/README.md deleted file mode 100644 index 9c8b1300..00000000 --- a/mcp-server/README.md +++ /dev/null @@ -1,170 +0,0 @@ -# Task Master MCP Server - -This module implements a [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) server for Task Master, allowing external applications to access Task Master functionality and context through a standardized API. - -## Features - -- MCP-compliant server implementation using FastMCP -- RESTful API for context management -- Authentication and authorization for secure access -- Context storage and retrieval with metadata and tagging -- Context windowing and truncation for handling size limits -- Integration with Task Master for task management operations - -## Installation - -The MCP server is included with Task Master. Install Task Master globally to use the MCP server: - -```bash -npm install -g task-master-ai -``` - -Or use it locally: - -```bash -npm install task-master-ai -``` - -## Environment Configuration - -The MCP server can be configured using environment variables or a `.env` file: - -| Variable | Description | Default | -| -------------------- | ---------------------------------------- | ----------------------------- | -| `MCP_SERVER_PORT` | Port for the MCP server | 3000 | -| `MCP_SERVER_HOST` | Host for the MCP server | localhost | -| `MCP_CONTEXT_DIR` | Directory for context storage | ./mcp-server/contexts | -| `MCP_API_KEYS_FILE` | File for API key storage | ./mcp-server/api-keys.json | -| `MCP_JWT_SECRET` | Secret for JWT token generation | task-master-mcp-server-secret | -| `MCP_JWT_EXPIRATION` | JWT token expiration time | 24h | -| `LOG_LEVEL` | Logging level (debug, info, warn, error) | info | - -## Getting Started - -### Starting the Server - -Start the MCP server as a standalone process: - -```bash -npx task-master-mcp-server -``` - -Or start it programmatically: - -```javascript -import { TaskMasterMCPServer } from "task-master-ai/mcp-server"; - -const server = new TaskMasterMCPServer(); -await server.start({ port: 3000, host: "localhost" }); -``` - -### Authentication - -The MCP server uses API key authentication with JWT tokens for secure access. A default admin API key is generated on first startup and can be found in the `api-keys.json` file. - -To get a JWT token: - -```bash -curl -X POST http://localhost:3000/auth/token \ - -H "x-api-key: YOUR_API_KEY" -``` - -Use the token for subsequent requests: - -```bash -curl http://localhost:3000/mcp/tools \ - -H "Authorization: Bearer YOUR_JWT_TOKEN" -``` - -### Creating a New API Key - -Admin users can create new API keys: - -```bash -curl -X POST http://localhost:3000/auth/api-keys \ - -H "Authorization: Bearer ADMIN_JWT_TOKEN" \ - -H "Content-Type: application/json" \ - -d '{"clientId": "user1", "role": "user"}' -``` - -## Available MCP Endpoints - -The MCP server implements the following MCP-compliant endpoints: - -### Context Management - -- `GET /mcp/context` - List all contexts -- `POST /mcp/context` - Create a new context -- `GET /mcp/context/{id}` - Get a specific context -- `PUT /mcp/context/{id}` - Update a context -- `DELETE /mcp/context/{id}` - Delete a context - -### Models - -- `GET /mcp/models` - List available models -- `GET /mcp/models/{id}` - Get model details - -### Execution - -- `POST /mcp/execute` - Execute an operation with context - -## Available MCP Tools - -The MCP server provides the following tools: - -### Context Tools - -- `createContext` - Create a new context -- `getContext` - Retrieve a context by ID -- `updateContext` - Update an existing context -- `deleteContext` - Delete a context -- `listContexts` - List available contexts -- `addTags` - Add tags to a context -- `truncateContext` - Truncate a context to a maximum size - -### Task Master Tools - -- `listTasks` - List tasks from Task Master -- `getTaskDetails` - Get detailed task information -- `executeWithContext` - Execute operations using context - -## Examples - -### Creating a Context - -```javascript -// Using the MCP client -const client = new MCPClient("http://localhost:3000"); -await client.authenticate("YOUR_API_KEY"); - -const context = await client.createContext("my-context", { - title: "My Project", - tasks: ["Implement feature X", "Fix bug Y"], -}); -``` - -### Executing an Operation with Context - -```javascript -// Using the MCP client -const result = await client.execute("generateTask", "my-context", { - title: "New Task", - description: "Create a new task based on context", -}); -``` - -## Integration with Other Tools - -The Task Master MCP server can be integrated with other MCP-compatible tools and clients: - -- LLM applications that support the MCP protocol -- Task management systems that support context-aware operations -- Development environments with MCP integration - -## Contributing - -Contributions are welcome! Please feel free to submit a Pull Request. - -## License - -This project is licensed under the MIT License - see the LICENSE file for details. diff --git a/mcp-server/src/tools/addTask.js b/mcp-server/src/tools/addTask.js index 0622d0e8..0b12d9fc 100644 --- a/mcp-server/src/tools/addTask.js +++ b/mcp-server/src/tools/addTask.js @@ -29,6 +29,11 @@ export function registerAddTaskTool(server) { .optional() .describe("Task priority (high, medium, low)"), file: z.string().optional().describe("Path to the tasks file"), + projectRoot: z + .string() + .describe( + "Root directory of the project (default: current working directory)" + ), }), execute: async (args, { log }) => { try { @@ -40,7 +45,12 @@ export function registerAddTaskTool(server) { if (args.priority) cmdArgs.push(`--priority=${args.priority}`); if (args.file) cmdArgs.push(`--file=${args.file}`); - const result = executeTaskMasterCommand("add-task", log, cmdArgs); + const result = executeTaskMasterCommand( + "add-task", + log, + cmdArgs, + projectRoot + ); if (!result.success) { throw new Error(result.error); diff --git a/mcp-server/src/tools/expandTask.js b/mcp-server/src/tools/expandTask.js index b94d00d4..ae0b4550 100644 --- a/mcp-server/src/tools/expandTask.js +++ b/mcp-server/src/tools/expandTask.js @@ -19,7 +19,7 @@ export function registerExpandTaskTool(server) { name: "expandTask", description: "Break down a task into detailed subtasks", parameters: z.object({ - id: z.union([z.string(), z.number()]).describe("Task ID to expand"), + id: z.string().describe("Task ID to expand"), num: z.number().optional().describe("Number of subtasks to generate"), research: z .boolean() @@ -38,6 +38,11 @@ export function registerExpandTaskTool(server) { "Force regeneration of subtasks for tasks that already have them" ), file: z.string().optional().describe("Path to the tasks file"), + projectRoot: z + .string() + .describe( + "Root directory of the project (default: current working directory)" + ), }), execute: async (args, { log }) => { try { @@ -50,7 +55,14 @@ export function registerExpandTaskTool(server) { if (args.force) cmdArgs.push("--force"); if (args.file) cmdArgs.push(`--file=${args.file}`); - const result = executeTaskMasterCommand("expand", log, cmdArgs); + const projectRoot = args.projectRoot; + + const result = executeTaskMasterCommand( + "expand", + log, + cmdArgs, + projectRoot + ); if (!result.success) { throw new Error(result.error); diff --git a/mcp-server/src/tools/listTasks.js b/mcp-server/src/tools/listTasks.js index 7da65692..af6f4844 100644 --- a/mcp-server/src/tools/listTasks.js +++ b/mcp-server/src/tools/listTasks.js @@ -25,6 +25,11 @@ export function registerListTasksTool(server) { .optional() .describe("Include subtasks in the response"), file: z.string().optional().describe("Path to the tasks file"), + projectRoot: z + .string() + .describe( + "Root directory of the project (default: current working directory)" + ), }), execute: async (args, { log }) => { try { @@ -35,12 +40,21 @@ export function registerListTasksTool(server) { if (args.withSubtasks) cmdArgs.push("--with-subtasks"); if (args.file) cmdArgs.push(`--file=${args.file}`); - const result = executeTaskMasterCommand("list", log, cmdArgs); + const projectRoot = args.projectRoot; + + const result = executeTaskMasterCommand( + "list", + log, + cmdArgs, + projectRoot + ); if (!result.success) { throw new Error(result.error); } + log.info(`Listing tasks result: ${result.stdout}`, result.stdout); + return createContentResponse(result.stdout); } catch (error) { log.error(`Error listing tasks: ${error.message}`); diff --git a/mcp-server/src/tools/nextTask.js b/mcp-server/src/tools/nextTask.js index 4003ce04..729c5fec 100644 --- a/mcp-server/src/tools/nextTask.js +++ b/mcp-server/src/tools/nextTask.js @@ -21,6 +21,11 @@ export function registerNextTaskTool(server) { "Show the next task to work on based on dependencies and status", parameters: z.object({ file: z.string().optional().describe("Path to the tasks file"), + projectRoot: z + .string() + .describe( + "Root directory of the project (default: current working directory)" + ), }), execute: async (args, { log }) => { try { @@ -29,7 +34,14 @@ export function registerNextTaskTool(server) { const cmdArgs = []; if (args.file) cmdArgs.push(`--file=${args.file}`); - const result = executeTaskMasterCommand("next", log, cmdArgs); + const projectRoot = args.projectRoot; + + const result = executeTaskMasterCommand( + "next", + log, + cmdArgs, + projectRoot + ); if (!result.success) { throw new Error(result.error); diff --git a/mcp-server/src/tools/setTaskStatus.js b/mcp-server/src/tools/setTaskStatus.js index 5681dd7b..d2c0b2c1 100644 --- a/mcp-server/src/tools/setTaskStatus.js +++ b/mcp-server/src/tools/setTaskStatus.js @@ -20,12 +20,17 @@ export function registerSetTaskStatusTool(server) { description: "Set the status of a task", parameters: z.object({ id: z - .union([z.string(), z.number()]) + .string() .describe("Task ID (can be comma-separated for multiple tasks)"), status: z .string() .describe("New status (todo, in-progress, review, done)"), file: z.string().optional().describe("Path to the tasks file"), + projectRoot: z + .string() + .describe( + "Root directory of the project (default: current working directory)" + ), }), execute: async (args, { log }) => { try { @@ -34,7 +39,14 @@ export function registerSetTaskStatusTool(server) { const cmdArgs = [`--id=${args.id}`, `--status=${args.status}`]; if (args.file) cmdArgs.push(`--file=${args.file}`); - const result = executeTaskMasterCommand("set-status", log, cmdArgs); + const projectRoot = args.projectRoot; + + const result = executeTaskMasterCommand( + "set-status", + log, + cmdArgs, + projectRoot + ); if (!result.success) { throw new Error(result.error); diff --git a/mcp-server/src/tools/showTask.js b/mcp-server/src/tools/showTask.js index c44d9463..86130570 100644 --- a/mcp-server/src/tools/showTask.js +++ b/mcp-server/src/tools/showTask.js @@ -19,17 +19,29 @@ export function registerShowTaskTool(server) { name: "showTask", description: "Show detailed information about a specific task", parameters: z.object({ - id: z.union([z.string(), z.number()]).describe("Task ID to show"), + id: z.string().describe("Task ID to show"), file: z.string().optional().describe("Path to the tasks file"), + projectRoot: z + .string() + .describe( + "Root directory of the project (default: current working directory)" + ), }), execute: async (args, { log }) => { try { log.info(`Showing task details for ID: ${args.id}`); - const cmdArgs = [args.id]; + const cmdArgs = [`--id=${args.id}`]; if (args.file) cmdArgs.push(`--file=${args.file}`); - const result = executeTaskMasterCommand("show", log, cmdArgs); + const projectRoot = args.projectRoot; + + const result = executeTaskMasterCommand( + "show", + log, + cmdArgs, + projectRoot + ); if (!result.success) { throw new Error(result.error); diff --git a/mcp-server/src/tools/utils.js b/mcp-server/src/tools/utils.js index 24745d2e..872363e0 100644 --- a/mcp-server/src/tools/utils.js +++ b/mcp-server/src/tools/utils.js @@ -10,27 +10,39 @@ import { spawnSync } from "child_process"; * @param {string} command - The command to execute * @param {Object} log - The logger object from FastMCP * @param {Array} args - Arguments for the command + * @param {string} cwd - Working directory for command execution (defaults to current project root) * @returns {Object} - The result of the command execution */ -export function executeTaskMasterCommand(command, log, args = []) { +export function executeTaskMasterCommand( + command, + log, + args = [], + cwd = process.cwd() +) { try { log.info( - `Executing task-master ${command} with args: ${JSON.stringify(args)}` + `Executing task-master ${command} with args: ${JSON.stringify( + args + )} in directory: ${cwd}` ); // Prepare full arguments array const fullArgs = [command, ...args]; + // Common options for spawn + const spawnOptions = { + encoding: "utf8", + cwd: cwd, + }; + // Execute the command using the global task-master CLI or local script // Try the global CLI first - let result = spawnSync("task-master", fullArgs, { encoding: "utf8" }); + let result = spawnSync("task-master", fullArgs, spawnOptions); // If global CLI is not available, try fallback to the local script if (result.error && result.error.code === "ENOENT") { log.info("Global task-master not found, falling back to local script"); - result = spawnSync("node", ["scripts/dev.js", ...fullArgs], { - encoding: "utf8", - }); + result = spawnSync("node", ["scripts/dev.js", ...fullArgs], spawnOptions); } if (result.error) { @@ -38,8 +50,14 @@ export function executeTaskMasterCommand(command, log, args = []) { } if (result.status !== 0) { + // Improve error handling by combining stderr and stdout if stderr is empty + const errorOutput = result.stderr + ? result.stderr.trim() + : result.stdout + ? result.stdout.trim() + : "Unknown error"; throw new Error( - `Command failed with exit code ${result.status}: ${result.stderr}` + `Command failed with exit code ${result.status}: ${errorOutput}` ); }