Skip to main content
Glama

taskqueue-mcp

toolExecutors.ts15.4 kB
import { TaskManager } from "./TaskManager.js"; import { AppError, AppErrorCode } from "../types/errors.js"; /** * Interface defining the contract for tool executors. * Each tool executor is responsible for executing a specific tool's logic * and handling its input validation. */ interface ToolExecutor { /** The name of the tool this executor handles */ name: string; /** * Executes the tool's logic with the given arguments * @param taskManager The TaskManager instance to use for task-related operations * @param args The arguments passed to the tool as a key-value record * @returns A promise that resolves to the raw data from TaskManager */ execute: ( taskManager: TaskManager, args: Record<string, unknown> ) => Promise<unknown>; } // ---------------------- UTILITY FUNCTIONS ---------------------- /** * Throws an AppError if a required parameter is not present or not a string. */ function validateRequiredStringParam(param: unknown, paramName: string): string { if (typeof param !== "string" || !param) { throw new AppError( `Invalid or missing required parameter: ${paramName} (Expected string)`, AppErrorCode.MissingParameter ); } return param; } /** * Validates that a project ID parameter exists and is a string. */ function validateProjectId(projectId: unknown): string { return validateRequiredStringParam(projectId, "projectId"); } /** * Validates that a task ID parameter exists and is a string. */ function validateTaskId(taskId: unknown): string { return validateRequiredStringParam(taskId, "taskId"); } /** * Throws an AppError if tasks is not defined or not an array. */ function validateTaskList(tasks: unknown): void { if (!Array.isArray(tasks)) { throw new AppError( "Invalid or missing required parameter: tasks (Expected array)", AppErrorCode.InvalidArgument ); } } /** * Validates an optional "state" parameter against the allowed states. */ function validateOptionalStateParam( state: unknown, validStates: Array<string> ): string | undefined { if (state === undefined) return undefined; if (typeof state === "string" && validStates.includes(state)) return state; throw new AppError( `Invalid state parameter. Must be one of: ${validStates.join(", ")}`, AppErrorCode.InvalidState ); } /** * Validates an array of task objects, ensuring each has required fields. */ function validateTaskObjects( tasks: unknown, errorPrefix?: string ): Array<{ title: string; description: string; toolRecommendations?: string; ruleRecommendations?: string; }> { validateTaskList(tasks); const taskArray = tasks as Array<unknown>; return taskArray.map((task, index) => { if (!task || typeof task !== "object") { throw new AppError( `${errorPrefix || "Task"} at index ${index} must be an object`, AppErrorCode.InvalidArgument ); } const t = task as Record<string, unknown>; const title = validateRequiredStringParam(t.title, `title in task at index ${index}`); const description = validateRequiredStringParam(t.description, `description in task at index ${index}`); return { title, description, toolRecommendations: t.toolRecommendations ? String(t.toolRecommendations) : undefined, ruleRecommendations: t.ruleRecommendations ? String(t.ruleRecommendations) : undefined, }; }); } // ---------------------- TOOL EXECUTOR MAP ---------------------- export const toolExecutorMap: Map<string, ToolExecutor> = new Map(); // ---------------------- TOOL EXECUTORS ---------------------- /** * Tool executor for listing projects with optional state filtering */ const listProjectsToolExecutor: ToolExecutor = { name: "list_projects", async execute(taskManager, args) { // 1. Argument Validation const state = validateOptionalStateParam(args.state, [ "open", "pending_approval", "completed", "all", ]); // 2. Core Logic Execution const resultData = await taskManager.listProjects(state as any); // 3. Return raw success data return resultData; }, }; toolExecutorMap.set(listProjectsToolExecutor.name, listProjectsToolExecutor); /** * Tool executor for creating new projects with tasks */ const createProjectToolExecutor: ToolExecutor = { name: "create_project", async execute(taskManager, args) { const initialPrompt = validateRequiredStringParam(args.initialPrompt, "initialPrompt"); const validatedTasks = validateTaskObjects(args.tasks); const projectPlan = args.projectPlan !== undefined ? String(args.projectPlan) : undefined; const autoApprove = args.autoApprove as boolean | undefined; if (args.projectPlan !== undefined && typeof args.projectPlan !== 'string') { throw new AppError( "Invalid type for optional parameter 'projectPlan' (Expected string)", AppErrorCode.InvalidArgument ); } if (args.autoApprove !== undefined && typeof args.autoApprove !== 'boolean') { throw new AppError( "Invalid type for optional parameter 'autoApprove' (Expected boolean)", AppErrorCode.InvalidArgument ); } const resultData = await taskManager.createProject( initialPrompt, validatedTasks, projectPlan, autoApprove ); return resultData; }, }; toolExecutorMap.set(createProjectToolExecutor.name, createProjectToolExecutor); /** * Tool executor for generating project plans using an LLM */ const generateProjectPlanToolExecutor: ToolExecutor = { name: "generate_project_plan", async execute(taskManager, args) { // 1. Argument Validation const prompt = validateRequiredStringParam(args.prompt, "prompt"); const provider = validateRequiredStringParam(args.provider, "provider"); const model = validateRequiredStringParam(args.model, "model"); // Validate optional attachments let attachments: string[] = []; if (args.attachments !== undefined) { if (!Array.isArray(args.attachments)) { throw new AppError( "Invalid attachments: must be an array of strings", AppErrorCode.InvalidArgument ); } attachments = args.attachments.map((att, index) => { if (typeof att !== "string") { throw new AppError( `Invalid attachment at index ${index}: must be a string`, AppErrorCode.InvalidArgument ); } return att; }); } // 2. Core Logic Execution const resultData = await taskManager.generateProjectPlan({ prompt, provider, model, attachments, }); // 3. Return raw success data return resultData; }, }; toolExecutorMap.set(generateProjectPlanToolExecutor.name, generateProjectPlanToolExecutor); /** * Tool executor for getting the next task in a project */ const getNextTaskToolExecutor: ToolExecutor = { name: "get_next_task", async execute(taskManager, args) { // 1. Argument Validation const projectId = validateProjectId(args.projectId); // 2. Core Logic Execution const resultData = await taskManager.getNextTask(projectId); // 3. Return raw success data return resultData; }, }; toolExecutorMap.set(getNextTaskToolExecutor.name, getNextTaskToolExecutor); /** * Tool executor for updating a task */ const updateTaskToolExecutor: ToolExecutor = { name: "update_task", async execute(taskManager, args) { const projectId = validateProjectId(args.projectId); const taskId = validateTaskId(args.taskId); const updates: Record<string, string> = {}; if (args.title !== undefined) { updates.title = validateRequiredStringParam(args.title, "title"); } if (args.description !== undefined) { updates.description = validateRequiredStringParam(args.description, "description"); } if (args.toolRecommendations !== undefined) { if (typeof args.toolRecommendations !== "string") { throw new AppError( "Invalid toolRecommendations: must be a string", AppErrorCode.InvalidArgument ); } updates.toolRecommendations = args.toolRecommendations; } if (args.ruleRecommendations !== undefined) { if (typeof args.ruleRecommendations !== "string") { throw new AppError( "Invalid ruleRecommendations: must be a string", AppErrorCode.InvalidArgument ); } updates.ruleRecommendations = args.ruleRecommendations; } if (args.status !== undefined) { const status = args.status; if ( typeof status !== "string" || !["not started", "in progress", "done"].includes(status) ) { throw new AppError( "Invalid status: must be one of 'not started', 'in progress', 'done'", AppErrorCode.InvalidArgument ); } if (status === "done") { updates.completedDetails = validateRequiredStringParam( args.completedDetails, "completedDetails (required when status = 'done')" ); } updates.status = status; } const resultData = await taskManager.updateTask(projectId, taskId, updates); return resultData; }, }; toolExecutorMap.set(updateTaskToolExecutor.name, updateTaskToolExecutor); /** * Tool executor for reading project details */ const readProjectToolExecutor: ToolExecutor = { name: "read_project", async execute(taskManager, args) { // 1. Argument Validation const projectId = validateProjectId(args.projectId); // 2. Core Logic Execution const resultData = await taskManager.readProject(projectId); // 3. Return raw success data return resultData; }, }; toolExecutorMap.set(readProjectToolExecutor.name, readProjectToolExecutor); /** * Tool executor for deleting projects */ const deleteProjectToolExecutor: ToolExecutor = { name: "delete_project", async execute(taskManager, args) { const projectId = validateProjectId(args.projectId); const projectIndex = taskManager["data"].projects.findIndex( (p) => p.projectId === projectId ); if (projectIndex === -1) { throw new AppError( `Project not found: ${projectId}`, AppErrorCode.ProjectNotFound ); } taskManager["data"].projects.splice(projectIndex, 1); await taskManager["saveTasks"](); return { status: "project_deleted", message: `Project ${projectId} has been deleted.`, }; }, }; toolExecutorMap.set(deleteProjectToolExecutor.name, deleteProjectToolExecutor); /** * Tool executor for adding tasks to a project */ const addTasksToProjectToolExecutor: ToolExecutor = { name: "add_tasks_to_project", async execute(taskManager, args) { // 1. Argument Validation const projectId = validateProjectId(args.projectId); const tasks = validateTaskObjects(args.tasks); // 2. Core Logic Execution const resultData = await taskManager.addTasksToProject(projectId, tasks); // 3. Return raw success data return resultData; }, }; toolExecutorMap.set(addTasksToProjectToolExecutor.name, addTasksToProjectToolExecutor); /** * Tool executor for finalizing (completing) projects */ const finalizeProjectToolExecutor: ToolExecutor = { name: "finalize_project", async execute(taskManager, args) { // 1. Argument Validation const projectId = validateProjectId(args.projectId); // 2. Core Logic Execution const resultData = await taskManager.approveProjectCompletion(projectId); // 3. Return raw success data return resultData; }, }; toolExecutorMap.set(finalizeProjectToolExecutor.name, finalizeProjectToolExecutor); /** * Tool executor for listing tasks with optional projectId and state */ const listTasksToolExecutor: ToolExecutor = { name: "list_tasks", async execute(taskManager, args) { // 1. Argument Validation const projectId = args.projectId !== undefined ? validateProjectId(args.projectId) : undefined; const state = validateOptionalStateParam(args.state, [ "open", "pending_approval", "completed", "all", ]); // 2. Core Logic Execution const resultData = await taskManager.listTasks(projectId, state as any); // 3. Return raw success data return resultData; }, }; toolExecutorMap.set(listTasksToolExecutor.name, listTasksToolExecutor); /** * Tool executor for reading task details */ const readTaskToolExecutor: ToolExecutor = { name: "read_task", async execute(taskManager, args) { // 1. Argument Validation const projectId = validateProjectId(args.projectId); const taskId = validateTaskId(args.taskId); // 2. Core Logic Execution const resultData = await taskManager.openTaskDetails(projectId, taskId); // 3. Return raw success data return resultData; }, }; toolExecutorMap.set(readTaskToolExecutor.name, readTaskToolExecutor); /** * Tool executor for creating an individual task in a project */ const createTaskToolExecutor: ToolExecutor = { name: "create_task", async execute(taskManager, args) { const projectId = validateProjectId(args.projectId); const title = validateRequiredStringParam(args.title, "title"); const description = validateRequiredStringParam(args.description, "description"); if (args.toolRecommendations !== undefined && typeof args.toolRecommendations !== "string") { throw new AppError( "Invalid type for optional parameter 'toolRecommendations' (Expected string)", AppErrorCode.InvalidArgument ); } if (args.ruleRecommendations !== undefined && typeof args.ruleRecommendations !== "string") { throw new AppError( "Invalid type for optional parameter 'ruleRecommendations' (Expected string)", AppErrorCode.InvalidArgument ); } const singleTask = { title, description, toolRecommendations: args.toolRecommendations ? String(args.toolRecommendations) : undefined, ruleRecommendations: args.ruleRecommendations ? String(args.ruleRecommendations) : undefined, }; const resultData = await taskManager.addTasksToProject(projectId, [singleTask]); return resultData; }, }; toolExecutorMap.set(createTaskToolExecutor.name, createTaskToolExecutor); /** * Tool executor for deleting tasks */ const deleteTaskToolExecutor: ToolExecutor = { name: "delete_task", async execute(taskManager, args) { // 1. Argument Validation const projectId = validateProjectId(args.projectId); const taskId = validateTaskId(args.taskId); // 2. Core Logic Execution const resultData = await taskManager.deleteTask(projectId, taskId); // 3. Return raw success data return resultData; }, }; toolExecutorMap.set(deleteTaskToolExecutor.name, deleteTaskToolExecutor); /** * Tool executor for approving completed tasks */ const approveTaskToolExecutor: ToolExecutor = { name: "approve_task", async execute(taskManager, args) { // 1. Argument Validation const projectId = validateProjectId(args.projectId); const taskId = validateTaskId(args.taskId); // 2. Core Logic Execution const resultData = await taskManager.approveTaskCompletion(projectId, taskId); // 3. Return raw success data return resultData; }, }; toolExecutorMap.set(approveTaskToolExecutor.name, approveTaskToolExecutor);

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/chriscarrollsmith/taskqueue-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server