feat: Adds initialize-project to the MCP tools to enable onboarding to Taskmaster directly from MCP only.
This commit is contained in:
@@ -16,7 +16,7 @@ This document provides a detailed reference for interacting with Taskmaster, cov
|
|||||||
|
|
||||||
### 1. Initialize Project (`init`)
|
### 1. Initialize Project (`init`)
|
||||||
|
|
||||||
* **MCP Tool:** N/A (Note: MCP equivalent is not currently practical, this is a CLI only action)
|
* **MCP Tool:** `initialize_project`
|
||||||
* **CLI Command:** `task-master init [options]`
|
* **CLI Command:** `task-master init [options]`
|
||||||
* **Description:** `Set up the basic Taskmaster file structure and configuration in the current directory for a new project.`
|
* **Description:** `Set up the basic Taskmaster file structure and configuration in the current directory for a new project.`
|
||||||
* **Key CLI Options:**
|
* **Key CLI Options:**
|
||||||
@@ -25,6 +25,17 @@ This document provides a detailed reference for interacting with Taskmaster, cov
|
|||||||
* `--version <version>`: `Set the initial version for your project (e.g., '0.1.0').`
|
* `--version <version>`: `Set the initial version for your project (e.g., '0.1.0').`
|
||||||
* `-y, --yes`: `Initialize Taskmaster quickly using default settings without interactive prompts.`
|
* `-y, --yes`: `Initialize Taskmaster quickly using default settings without interactive prompts.`
|
||||||
* **Usage:** Run this once at the beginning of a new project.
|
* **Usage:** Run this once at the beginning of a new project.
|
||||||
|
* **MCP Variant Description:** `Set up the basic Taskmaster file structure and configuration in the current directory for a new project by running the 'task-master init' command.`
|
||||||
|
* **Key MCP Parameters/Options:**
|
||||||
|
* `projectName`: `Set the name for your project.` (CLI: `--name <name>`)
|
||||||
|
* `projectDescription`: `Provide a brief description for your project.` (CLI: `--description <text>`)
|
||||||
|
* `projectVersion`: `Set the initial version for your project (e.g., '0.1.0').` (CLI: `--version <version>`)
|
||||||
|
* `authorName`: `Author name.` (CLI: `--author <author>`)
|
||||||
|
* `skipInstall`: `Skip installing dependencies (default: false).` (CLI: `--skip-install`)
|
||||||
|
* `addAliases`: `Add shell aliases (tm, taskmaster) (default: false).` (CLI: `--aliases`)
|
||||||
|
* `yes`: `Skip prompts and use defaults/provided arguments (default: false).` (CLI: `-y, --yes`)
|
||||||
|
* **Usage:** Run this once at the beginning of a new project, typically via an integrated tool like Cursor. Operates on the current working directory of the MCP server.
|
||||||
|
|
||||||
|
|
||||||
### 2. Parse PRD (`parse_prd`)
|
### 2. Parse PRD (`parse_prd`)
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import { registerFixDependenciesTool } from "./fix-dependencies.js";
|
|||||||
import { registerComplexityReportTool } from "./complexity-report.js";
|
import { registerComplexityReportTool } from "./complexity-report.js";
|
||||||
import { registerAddDependencyTool } from "./add-dependency.js";
|
import { registerAddDependencyTool } from "./add-dependency.js";
|
||||||
import { registerRemoveTaskTool } from './remove-task.js';
|
import { registerRemoveTaskTool } from './remove-task.js';
|
||||||
|
import { registerInitializeProjectTool } from './initialize-project.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register all Task Master tools with the MCP server
|
* Register all Task Master tools with the MCP server
|
||||||
@@ -56,6 +57,7 @@ export function registerTaskMasterTools(server) {
|
|||||||
registerComplexityReportTool(server);
|
registerComplexityReportTool(server);
|
||||||
registerAddDependencyTool(server);
|
registerAddDependencyTool(server);
|
||||||
registerRemoveTaskTool(server);
|
registerRemoveTaskTool(server);
|
||||||
|
registerInitializeProjectTool(server);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error(`Error registering Task Master tools: ${error.message}`);
|
logger.error(`Error registering Task Master tools: ${error.message}`);
|
||||||
throw error;
|
throw error;
|
||||||
|
|||||||
62
mcp-server/src/tools/initialize-project.js
Normal file
62
mcp-server/src/tools/initialize-project.js
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
import { z } from "zod";
|
||||||
|
import { execSync } from 'child_process';
|
||||||
|
import { createContentResponse, createErrorResponse } from "./utils.js"; // Only need response creators
|
||||||
|
|
||||||
|
export function registerInitializeProjectTool(server) {
|
||||||
|
server.addTool({
|
||||||
|
name: "initialize_project", // snake_case for tool name
|
||||||
|
description: "Initializes a new Task Master project structure in the current working directory by running 'task-master init'.",
|
||||||
|
parameters: z.object({
|
||||||
|
projectName: z.string().optional().describe("The name for the new project."),
|
||||||
|
projectDescription: z.string().optional().describe("A brief description for the project."),
|
||||||
|
projectVersion: z.string().optional().describe("The initial version for the project (e.g., '0.1.0')."),
|
||||||
|
authorName: z.string().optional().describe("The author's name."),
|
||||||
|
skipInstall: z.boolean().optional().default(false).describe("Skip installing dependencies automatically."),
|
||||||
|
addAliases: z.boolean().optional().default(false).describe("Add shell aliases (tm, taskmaster) to shell config file."),
|
||||||
|
yes: z.boolean().optional().default(false).describe("Skip prompts and use default values or provided arguments."),
|
||||||
|
// projectRoot is not needed here as 'init' works on the current directory
|
||||||
|
}),
|
||||||
|
execute: async (args, { log }) => { // Destructure context to get log
|
||||||
|
try {
|
||||||
|
log.info(`Executing initialize_project with args: ${JSON.stringify(args)}`);
|
||||||
|
|
||||||
|
// Construct the command arguments carefully
|
||||||
|
// Using npx ensures it uses the locally installed version if available, or fetches it
|
||||||
|
let command = 'npx task-master init';
|
||||||
|
const cliArgs = [];
|
||||||
|
if (args.projectName) cliArgs.push(`--name "${args.projectName.replace(/"/g, '\\"')}"`); // Escape quotes
|
||||||
|
if (args.projectDescription) cliArgs.push(`--description "${args.projectDescription.replace(/"/g, '\\"')}"`);
|
||||||
|
if (args.projectVersion) cliArgs.push(`--version "${args.projectVersion.replace(/"/g, '\\"')}"`);
|
||||||
|
if (args.authorName) cliArgs.push(`--author "${args.authorName.replace(/"/g, '\\"')}"`);
|
||||||
|
if (args.skipInstall) cliArgs.push('--skip-install');
|
||||||
|
if (args.addAliases) cliArgs.push('--aliases');
|
||||||
|
if (args.yes) cliArgs.push('--yes');
|
||||||
|
|
||||||
|
command += ' ' + cliArgs.join(' ');
|
||||||
|
|
||||||
|
log.info(`Constructed command: ${command}`);
|
||||||
|
|
||||||
|
// Execute the command in the current working directory of the server process
|
||||||
|
// Capture stdout/stderr. Use a reasonable timeout (e.g., 5 minutes)
|
||||||
|
const output = execSync(command, { encoding: 'utf8', stdio: 'pipe', timeout: 300000 });
|
||||||
|
|
||||||
|
log.info(`Initialization output:\n${output}`);
|
||||||
|
|
||||||
|
// Return a standard success response manually
|
||||||
|
return createContentResponse(
|
||||||
|
"Project initialized successfully.",
|
||||||
|
{ output: output } // Include output in the data payload
|
||||||
|
);
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
// Catch errors from execSync or timeouts
|
||||||
|
const errorMessage = `Project initialization failed: ${error.message}`;
|
||||||
|
const errorDetails = error.stderr?.toString() || error.stdout?.toString() || error.message; // Provide stderr/stdout if available
|
||||||
|
log.error(`${errorMessage}\nDetails: ${errorDetails}`);
|
||||||
|
|
||||||
|
// Return a standard error response manually
|
||||||
|
return createErrorResponse(errorMessage, { details: errorDetails });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user