Skip to main content
Glama

add_tasks

Add multiple tasks to a goal with hierarchical structure in a single transactional operation, ensuring all tasks succeed or none are added.

Instructions

Add multiple tasks to a goal. Tasks can be provided in a hierarchical structure. For tasks that are children of existing tasks, use the parentId field. The operation is transactional: either all tasks in the batch succeed, or the entire operation fails.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
goalIdYesID of the goal to add tasks to (number)
tasksYesAn array of task objects to be added. Each task can define nested subtasks.

Implementation Reference

  • Main handler for the 'add_tasks' tool. Parses AddTasksInput, recursively processes hierarchical task inputs (validating existing parentIds, creating new tasks via storage.addTask), builds HierarchicalTaskResponse tree, and returns JSON-formatted content.
    case 'add_tasks': { const { goalId, tasks: taskInputs } = request.params.arguments as AddTasksInput; const createdTasks: HierarchicalTaskResponse[] = []; // Helper function to recursively process tasks const processTaskInputRecursively = async ( taskInput: TaskInput, currentGoalId: number, parentTaskId: string | null ): Promise<HierarchicalTaskResponse> => { // Validate parentId if it refers to an existing task if (taskInput.parentId !== undefined && taskInput.parentId !== null) { // Use getTasks to check for existing parent, passing the parentId as an array const existingTasks = await storage.getTasks(currentGoalId, [taskInput.parentId]); if (!existingTasks || existingTasks.length === 0) { throw new McpError(ErrorCode.InvalidParams, `Parent task with ID "${taskInput.parentId}" not found for goal ${currentGoalId}.`); } } // Add the current task const newTask = await storage.addTask(currentGoalId, { title: taskInput.title, description: taskInput.description, parentId: parentTaskId, // Use the parentTaskId from recursion, not taskInput.parentId deleted: false, }); const hierarchicalTaskResponse: HierarchicalTaskResponse = { id: newTask.id, goalId: newTask.goalId, title: newTask.title, description: newTask.description, isComplete: newTask.isComplete, deleted: newTask.deleted, }; // Recursively add subtasks if (taskInput.subtasks && taskInput.subtasks.length > 0) { hierarchicalTaskResponse.subtasks = []; for (const subtaskInput of taskInput.subtasks) { const subtaskResult = await processTaskInputRecursively( subtaskInput, currentGoalId, newTask.id // New task's ID becomes the parent for its subtasks ); hierarchicalTaskResponse.subtasks.push(subtaskResult); } } return hierarchicalTaskResponse; }; // Process top-level tasks for (const taskInput of taskInputs) { const createdTask = await processTaskInputRecursively(taskInput, goalId, taskInput.parentId || null); createdTasks.push(createdTask); } return { content: [ { type: 'text', text: JSON.stringify(createdTasks, null, 2), }, ], }; }
  • Core helper function that adds a single task to a goal's plan in LokiDB. Generates dot-notation task ID (e.g., '1.2'), validates parent task exists, tracks next sequence numbers per parent, inserts task record, updates plan timestamp.
    async addTask( goalId: number, { title, description, parentId }: Omit<Task, 'id' | 'goalId' | 'isComplete' | 'createdAt' | 'updatedAt'> ): Promise<TaskResponse> { const plan = await this.getPlan(goalId); if (!plan) { throw new Error(`No plan found for goal ${goalId}`); } const metadataCollection = this.db.getCollection('metadata'); const metadata = metadataCollection.findOne({}); if (!metadata) { throw new Error('Metadata collection not found or empty.'); } // Ensure nextTaskId for this goal exists if (!metadata.nextTaskId[goalId]) { metadata.nextTaskId[goalId] = { root: 0 }; // Initialize if not present } let effectiveParentId: string | null = parentId; if (parentId !== null) { const existingParent = this.tasks.findOne({ goalId, id: parentId }); if (!existingParent) { throw new McpError(ErrorCode.InvalidParams, `Parent task with ID "${parentId}" not found for goal ${goalId}.`); } } const parentKey = effectiveParentId === null ? 'root' : effectiveParentId; const nextSequence = (metadata.nextTaskId[goalId][parentKey] || 0) + 1; const newTaskId = effectiveParentId === null ? String(nextSequence) : `${effectiveParentId}.${nextSequence}`; metadata.nextTaskId[goalId][parentKey] = nextSequence; metadataCollection.update(metadata); const task: Task = { id: newTaskId, goalId, parentId: effectiveParentId, // Use effectiveParentId here title, description, isComplete: false, createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), deleted: false, // Initialize as not deleted }; this.tasks.insert(task as LokiTask); plan.updatedAt = new Date().toISOString(); await this.save(); const { createdAt, updatedAt, parentId: _, $loki, meta, ...taskResponse } = task as LokiTask; return taskResponse; }
  • src/index.ts:58-104 (registration)
    Tool registration in ListToolsRequestHandler, defining 'add_tasks' name, description, and JSON inputSchema with TaskInput definition for hierarchical inputs.
    { name: 'add_tasks', description: 'Add multiple tasks to a goal. Tasks can be provided in a hierarchical structure. For tasks that are children of *existing* tasks, use the `parentId` field. The operation is transactional: either all tasks in the batch succeed, or the entire operation fails.', inputSchema: { type: 'object', properties: { goalId: { type: 'number', description: 'ID of the goal to add tasks to (number)', }, tasks: { type: 'array', description: 'An array of task objects to be added. Each task can define nested subtasks.', items: { $ref: '#/definitions/TaskInput' } } }, required: ['goalId', 'tasks'], definitions: { TaskInput: { type: 'object', properties: { title: { type: 'string', description: 'Title of the task (string)' }, description: { type: 'string', description: 'Detailed description of the task (string)' }, parentId: { type: ['string', 'null'], description: 'Optional parent task ID for tasks that are children of *existing* tasks. Do not use for new subtasks defined hierarchically within this batch.' }, subtasks: { type: 'array', description: 'An array of nested subtask objects to be created under this task.', items: { $ref: '#/definitions/TaskInput' } } }, required: ['title', 'description'] } } }
  • TypeScript type definitions supporting add_tasks: TaskInput for inputs, AddTasksInput wrapper, HierarchicalTaskResponse for recursive output structures.
    // New interfaces for add_tasks input and output export interface TaskInput { title: string; description: string; parentId?: string | null; // For linking to existing tasks subtasks?: TaskInput[]; // For hierarchical new tasks } export interface AddTasksInput { goalId: number; tasks: TaskInput[]; } // For recursive output export interface HierarchicalTaskResponse extends TaskResponse { subtasks?: HierarchicalTaskResponse[]; }

Other Tools

Related Tools

Latest Blog Posts

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/hrishirc/task-orchestrator'

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