feat: Implement MCP (#20)
This commit is contained in:
36
mcp-server/server.js
Executable file
36
mcp-server/server.js
Executable file
@@ -0,0 +1,36 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import TaskMasterMCPServer from "./src/index.js";
|
||||
import dotenv from "dotenv";
|
||||
import logger from "./src/logger.js";
|
||||
|
||||
// Load environment variables
|
||||
dotenv.config();
|
||||
|
||||
/**
|
||||
* Start the MCP server
|
||||
*/
|
||||
async function startServer() {
|
||||
const server = new TaskMasterMCPServer();
|
||||
|
||||
// Handle graceful shutdown
|
||||
process.on("SIGINT", async () => {
|
||||
await server.stop();
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
process.on("SIGTERM", async () => {
|
||||
await server.stop();
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
try {
|
||||
await server.start();
|
||||
} catch (error) {
|
||||
logger.error(`Failed to start MCP server: ${error.message}`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Start the server
|
||||
startServer();
|
||||
86
mcp-server/src/index.js
Normal file
86
mcp-server/src/index.js
Normal file
@@ -0,0 +1,86 @@
|
||||
import { FastMCP } from "fastmcp";
|
||||
import path from "path";
|
||||
import dotenv from "dotenv";
|
||||
import { fileURLToPath } from "url";
|
||||
import fs from "fs";
|
||||
import logger from "./logger.js";
|
||||
import { registerTaskMasterTools } from "./tools/index.js";
|
||||
|
||||
// Load environment variables
|
||||
dotenv.config();
|
||||
|
||||
// Constants
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
/**
|
||||
* Main MCP server class that integrates with Task Master
|
||||
*/
|
||||
class TaskMasterMCPServer {
|
||||
constructor() {
|
||||
// Get version from package.json using synchronous fs
|
||||
const packagePath = path.join(__dirname, "../../package.json");
|
||||
const packageJson = JSON.parse(fs.readFileSync(packagePath, "utf8"));
|
||||
|
||||
this.options = {
|
||||
name: "Task Master MCP Server",
|
||||
version: packageJson.version,
|
||||
};
|
||||
|
||||
this.server = new FastMCP(this.options);
|
||||
this.initialized = false;
|
||||
|
||||
// this.server.addResource({});
|
||||
|
||||
// this.server.addResourceTemplate({});
|
||||
|
||||
// Bind methods
|
||||
this.init = this.init.bind(this);
|
||||
this.start = this.start.bind(this);
|
||||
this.stop = this.stop.bind(this);
|
||||
|
||||
// Setup logging
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the MCP server with necessary tools and routes
|
||||
*/
|
||||
async init() {
|
||||
if (this.initialized) return;
|
||||
|
||||
// Register Task Master tools
|
||||
registerTaskMasterTools(this.server);
|
||||
|
||||
this.initialized = true;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the MCP server
|
||||
*/
|
||||
async start() {
|
||||
if (!this.initialized) {
|
||||
await this.init();
|
||||
}
|
||||
|
||||
// Start the FastMCP server
|
||||
await this.server.start({
|
||||
transportType: "stdio",
|
||||
});
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the MCP server
|
||||
*/
|
||||
async stop() {
|
||||
if (this.server) {
|
||||
await this.server.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default TaskMasterMCPServer;
|
||||
68
mcp-server/src/logger.js
Normal file
68
mcp-server/src/logger.js
Normal file
@@ -0,0 +1,68 @@
|
||||
import chalk from "chalk";
|
||||
|
||||
// Define log levels
|
||||
const LOG_LEVELS = {
|
||||
debug: 0,
|
||||
info: 1,
|
||||
warn: 2,
|
||||
error: 3,
|
||||
success: 4,
|
||||
};
|
||||
|
||||
// Get log level from environment or default to info
|
||||
const LOG_LEVEL = process.env.LOG_LEVEL
|
||||
? LOG_LEVELS[process.env.LOG_LEVEL.toLowerCase()]
|
||||
: LOG_LEVELS.info;
|
||||
|
||||
/**
|
||||
* Logs a message with the specified level
|
||||
* @param {string} level - The log level (debug, info, warn, error, success)
|
||||
* @param {...any} args - Arguments to log
|
||||
*/
|
||||
function log(level, ...args) {
|
||||
const icons = {
|
||||
debug: chalk.gray("🔍"),
|
||||
info: chalk.blue("ℹ️"),
|
||||
warn: chalk.yellow("⚠️"),
|
||||
error: chalk.red("❌"),
|
||||
success: chalk.green("✅"),
|
||||
};
|
||||
|
||||
if (LOG_LEVELS[level] >= LOG_LEVEL) {
|
||||
const icon = icons[level] || "";
|
||||
|
||||
if (level === "error") {
|
||||
console.error(icon, chalk.red(...args));
|
||||
} else if (level === "warn") {
|
||||
console.warn(icon, chalk.yellow(...args));
|
||||
} else if (level === "success") {
|
||||
console.log(icon, chalk.green(...args));
|
||||
} else if (level === "info") {
|
||||
console.log(icon, chalk.blue(...args));
|
||||
} else {
|
||||
console.log(icon, ...args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a logger object with methods for different log levels
|
||||
* Can be used as a drop-in replacement for existing logger initialization
|
||||
* @returns {Object} Logger object with info, error, debug, warn, and success methods
|
||||
*/
|
||||
export function createLogger() {
|
||||
return {
|
||||
debug: (message) => log("debug", message),
|
||||
info: (message) => log("info", message),
|
||||
warn: (message) => log("warn", message),
|
||||
error: (message) => log("error", message),
|
||||
success: (message) => log("success", message),
|
||||
log: log, // Also expose the raw log function
|
||||
};
|
||||
}
|
||||
|
||||
// Export a default logger instance
|
||||
const logger = createLogger();
|
||||
|
||||
export default logger;
|
||||
export { log, LOG_LEVELS };
|
||||
66
mcp-server/src/tools/addTask.js
Normal file
66
mcp-server/src/tools/addTask.js
Normal file
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* tools/addTask.js
|
||||
* Tool to add a new task using AI
|
||||
*/
|
||||
|
||||
import { z } from "zod";
|
||||
import {
|
||||
executeTaskMasterCommand,
|
||||
createContentResponse,
|
||||
createErrorResponse,
|
||||
} from "./utils.js";
|
||||
|
||||
/**
|
||||
* Register the addTask tool with the MCP server
|
||||
* @param {FastMCP} server - FastMCP server instance
|
||||
*/
|
||||
export function registerAddTaskTool(server) {
|
||||
server.addTool({
|
||||
name: "addTask",
|
||||
description: "Add a new task using AI",
|
||||
parameters: z.object({
|
||||
prompt: z.string().describe("Description of the task to add"),
|
||||
dependencies: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe("Comma-separated list of task IDs this task depends on"),
|
||||
priority: z
|
||||
.string()
|
||||
.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 {
|
||||
log.info(`Adding new task: ${args.prompt}`);
|
||||
|
||||
const cmdArgs = [`--prompt="${args.prompt}"`];
|
||||
if (args.dependencies)
|
||||
cmdArgs.push(`--dependencies=${args.dependencies}`);
|
||||
if (args.priority) cmdArgs.push(`--priority=${args.priority}`);
|
||||
if (args.file) cmdArgs.push(`--file=${args.file}`);
|
||||
|
||||
const result = executeTaskMasterCommand(
|
||||
"add-task",
|
||||
log,
|
||||
cmdArgs,
|
||||
projectRoot
|
||||
);
|
||||
|
||||
if (!result.success) {
|
||||
throw new Error(result.error);
|
||||
}
|
||||
|
||||
return createContentResponse(result.stdout);
|
||||
} catch (error) {
|
||||
log.error(`Error adding task: ${error.message}`);
|
||||
return createErrorResponse(`Error adding task: ${error.message}`);
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
78
mcp-server/src/tools/expandTask.js
Normal file
78
mcp-server/src/tools/expandTask.js
Normal file
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* tools/expandTask.js
|
||||
* Tool to break down a task into detailed subtasks
|
||||
*/
|
||||
|
||||
import { z } from "zod";
|
||||
import {
|
||||
executeTaskMasterCommand,
|
||||
createContentResponse,
|
||||
createErrorResponse,
|
||||
} from "./utils.js";
|
||||
|
||||
/**
|
||||
* Register the expandTask tool with the MCP server
|
||||
* @param {Object} server - FastMCP server instance
|
||||
*/
|
||||
export function registerExpandTaskTool(server) {
|
||||
server.addTool({
|
||||
name: "expandTask",
|
||||
description: "Break down a task into detailed subtasks",
|
||||
parameters: z.object({
|
||||
id: z.string().describe("Task ID to expand"),
|
||||
num: z.number().optional().describe("Number of subtasks to generate"),
|
||||
research: z
|
||||
.boolean()
|
||||
.optional()
|
||||
.describe(
|
||||
"Enable Perplexity AI for research-backed subtask generation"
|
||||
),
|
||||
prompt: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe("Additional context to guide subtask generation"),
|
||||
force: z
|
||||
.boolean()
|
||||
.optional()
|
||||
.describe(
|
||||
"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 {
|
||||
log.info(`Expanding task ${args.id}`);
|
||||
|
||||
const cmdArgs = [`--id=${args.id}`];
|
||||
if (args.num) cmdArgs.push(`--num=${args.num}`);
|
||||
if (args.research) cmdArgs.push("--research");
|
||||
if (args.prompt) cmdArgs.push(`--prompt="${args.prompt}"`);
|
||||
if (args.force) cmdArgs.push("--force");
|
||||
if (args.file) cmdArgs.push(`--file=${args.file}`);
|
||||
|
||||
const projectRoot = args.projectRoot;
|
||||
|
||||
const result = executeTaskMasterCommand(
|
||||
"expand",
|
||||
log,
|
||||
cmdArgs,
|
||||
projectRoot
|
||||
);
|
||||
|
||||
if (!result.success) {
|
||||
throw new Error(result.error);
|
||||
}
|
||||
|
||||
return createContentResponse(result.stdout);
|
||||
} catch (error) {
|
||||
log.error(`Error expanding task: ${error.message}`);
|
||||
return createErrorResponse(`Error expanding task: ${error.message}`);
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
29
mcp-server/src/tools/index.js
Normal file
29
mcp-server/src/tools/index.js
Normal file
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* tools/index.js
|
||||
* Export all Task Master CLI tools for MCP server
|
||||
*/
|
||||
|
||||
import logger from "../logger.js";
|
||||
import { registerListTasksTool } from "./listTasks.js";
|
||||
import { registerShowTaskTool } from "./showTask.js";
|
||||
import { registerSetTaskStatusTool } from "./setTaskStatus.js";
|
||||
import { registerExpandTaskTool } from "./expandTask.js";
|
||||
import { registerNextTaskTool } from "./nextTask.js";
|
||||
import { registerAddTaskTool } from "./addTask.js";
|
||||
|
||||
/**
|
||||
* Register all Task Master tools with the MCP server
|
||||
* @param {Object} server - FastMCP server instance
|
||||
*/
|
||||
export function registerTaskMasterTools(server) {
|
||||
registerListTasksTool(server);
|
||||
registerShowTaskTool(server);
|
||||
registerSetTaskStatusTool(server);
|
||||
registerExpandTaskTool(server);
|
||||
registerNextTaskTool(server);
|
||||
registerAddTaskTool(server);
|
||||
}
|
||||
|
||||
export default {
|
||||
registerTaskMasterTools,
|
||||
};
|
||||
65
mcp-server/src/tools/listTasks.js
Normal file
65
mcp-server/src/tools/listTasks.js
Normal file
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* tools/listTasks.js
|
||||
* Tool to list all tasks from Task Master
|
||||
*/
|
||||
|
||||
import { z } from "zod";
|
||||
import {
|
||||
executeTaskMasterCommand,
|
||||
createContentResponse,
|
||||
createErrorResponse,
|
||||
} from "./utils.js";
|
||||
|
||||
/**
|
||||
* Register the listTasks tool with the MCP server
|
||||
* @param {Object} server - FastMCP server instance
|
||||
*/
|
||||
export function registerListTasksTool(server) {
|
||||
server.addTool({
|
||||
name: "listTasks",
|
||||
description: "List all tasks from Task Master",
|
||||
parameters: z.object({
|
||||
status: z.string().optional().describe("Filter tasks by status"),
|
||||
withSubtasks: z
|
||||
.boolean()
|
||||
.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 {
|
||||
log.info(`Listing tasks with filters: ${JSON.stringify(args)}`);
|
||||
|
||||
const cmdArgs = [];
|
||||
if (args.status) cmdArgs.push(`--status=${args.status}`);
|
||||
if (args.withSubtasks) cmdArgs.push("--with-subtasks");
|
||||
if (args.file) cmdArgs.push(`--file=${args.file}`);
|
||||
|
||||
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}`);
|
||||
return createErrorResponse(`Error listing tasks: ${error.message}`);
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
57
mcp-server/src/tools/nextTask.js
Normal file
57
mcp-server/src/tools/nextTask.js
Normal file
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* tools/nextTask.js
|
||||
* Tool to show the next task to work on based on dependencies and status
|
||||
*/
|
||||
|
||||
import { z } from "zod";
|
||||
import {
|
||||
executeTaskMasterCommand,
|
||||
createContentResponse,
|
||||
createErrorResponse,
|
||||
} from "./utils.js";
|
||||
|
||||
/**
|
||||
* Register the nextTask tool with the MCP server
|
||||
* @param {Object} server - FastMCP server instance
|
||||
*/
|
||||
export function registerNextTaskTool(server) {
|
||||
server.addTool({
|
||||
name: "nextTask",
|
||||
description:
|
||||
"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 {
|
||||
log.info(`Finding next task to work on`);
|
||||
|
||||
const cmdArgs = [];
|
||||
if (args.file) cmdArgs.push(`--file=${args.file}`);
|
||||
|
||||
const projectRoot = args.projectRoot;
|
||||
|
||||
const result = executeTaskMasterCommand(
|
||||
"next",
|
||||
log,
|
||||
cmdArgs,
|
||||
projectRoot
|
||||
);
|
||||
|
||||
if (!result.success) {
|
||||
throw new Error(result.error);
|
||||
}
|
||||
|
||||
return createContentResponse(result.stdout);
|
||||
} catch (error) {
|
||||
log.error(`Error finding next task: ${error.message}`);
|
||||
return createErrorResponse(`Error finding next task: ${error.message}`);
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
64
mcp-server/src/tools/setTaskStatus.js
Normal file
64
mcp-server/src/tools/setTaskStatus.js
Normal file
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* tools/setTaskStatus.js
|
||||
* Tool to set the status of a task
|
||||
*/
|
||||
|
||||
import { z } from "zod";
|
||||
import {
|
||||
executeTaskMasterCommand,
|
||||
createContentResponse,
|
||||
createErrorResponse,
|
||||
} from "./utils.js";
|
||||
|
||||
/**
|
||||
* Register the setTaskStatus tool with the MCP server
|
||||
* @param {Object} server - FastMCP server instance
|
||||
*/
|
||||
export function registerSetTaskStatusTool(server) {
|
||||
server.addTool({
|
||||
name: "setTaskStatus",
|
||||
description: "Set the status of a task",
|
||||
parameters: z.object({
|
||||
id: z
|
||||
.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 {
|
||||
log.info(`Setting status of task(s) ${args.id} to: ${args.status}`);
|
||||
|
||||
const cmdArgs = [`--id=${args.id}`, `--status=${args.status}`];
|
||||
if (args.file) cmdArgs.push(`--file=${args.file}`);
|
||||
|
||||
const projectRoot = args.projectRoot;
|
||||
|
||||
const result = executeTaskMasterCommand(
|
||||
"set-status",
|
||||
log,
|
||||
cmdArgs,
|
||||
projectRoot
|
||||
);
|
||||
|
||||
if (!result.success) {
|
||||
throw new Error(result.error);
|
||||
}
|
||||
|
||||
return createContentResponse(result.stdout);
|
||||
} catch (error) {
|
||||
log.error(`Error setting task status: ${error.message}`);
|
||||
return createErrorResponse(
|
||||
`Error setting task status: ${error.message}`
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
57
mcp-server/src/tools/showTask.js
Normal file
57
mcp-server/src/tools/showTask.js
Normal file
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* tools/showTask.js
|
||||
* Tool to show detailed information about a specific task
|
||||
*/
|
||||
|
||||
import { z } from "zod";
|
||||
import {
|
||||
executeTaskMasterCommand,
|
||||
createContentResponse,
|
||||
createErrorResponse,
|
||||
} from "./utils.js";
|
||||
|
||||
/**
|
||||
* Register the showTask tool with the MCP server
|
||||
* @param {Object} server - FastMCP server instance
|
||||
*/
|
||||
export function registerShowTaskTool(server) {
|
||||
server.addTool({
|
||||
name: "showTask",
|
||||
description: "Show detailed information about a specific task",
|
||||
parameters: z.object({
|
||||
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 = [`--id=${args.id}`];
|
||||
if (args.file) cmdArgs.push(`--file=${args.file}`);
|
||||
|
||||
const projectRoot = args.projectRoot;
|
||||
|
||||
const result = executeTaskMasterCommand(
|
||||
"show",
|
||||
log,
|
||||
cmdArgs,
|
||||
projectRoot
|
||||
);
|
||||
|
||||
if (!result.success) {
|
||||
throw new Error(result.error);
|
||||
}
|
||||
|
||||
return createContentResponse(result.stdout);
|
||||
} catch (error) {
|
||||
log.error(`Error showing task: ${error.message}`);
|
||||
return createErrorResponse(`Error showing task: ${error.message}`);
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
108
mcp-server/src/tools/utils.js
Normal file
108
mcp-server/src/tools/utils.js
Normal file
@@ -0,0 +1,108 @@
|
||||
/**
|
||||
* tools/utils.js
|
||||
* Utility functions for Task Master CLI integration
|
||||
*/
|
||||
|
||||
import { spawnSync } from "child_process";
|
||||
|
||||
/**
|
||||
* Execute a Task Master CLI command using 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 = [],
|
||||
cwd = process.cwd()
|
||||
) {
|
||||
try {
|
||||
log.info(
|
||||
`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, 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], spawnOptions);
|
||||
}
|
||||
|
||||
if (result.error) {
|
||||
throw new Error(`Command execution error: ${result.error.message}`);
|
||||
}
|
||||
|
||||
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}: ${errorOutput}`
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
stdout: result.stdout,
|
||||
stderr: result.stderr,
|
||||
};
|
||||
} catch (error) {
|
||||
log.error(`Error executing task-master command: ${error.message}`);
|
||||
return {
|
||||
success: false,
|
||||
error: error.message,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates standard content response for tools
|
||||
* @param {string} text - Text content to include in response
|
||||
* @returns {Object} - Content response object
|
||||
*/
|
||||
export function createContentResponse(text) {
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
text,
|
||||
type: "text",
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates error response for tools
|
||||
* @param {string} errorMessage - Error message to include in response
|
||||
* @returns {Object} - Error content response object
|
||||
*/
|
||||
export function createErrorResponse(errorMessage) {
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
text: errorMessage,
|
||||
type: "text",
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user