add_tag
Create and organize tags for tasks in the Task Master MCP server, enabling efficient categorization, task copying, and project management in AI-driven workflows.
Instructions
Create a new tag for organizing tasks in different contexts
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| copyFromCurrent | No | Whether to copy tasks from the current tag (default: false) | |
| copyFromTag | No | Specific tag to copy tasks from | |
| description | No | Optional description for the tag | |
| file | No | Path to the tasks file (default: tasks/tasks.json) | |
| fromBranch | No | Create tag name from current git branch (ignores name parameter) | |
| name | Yes | Name of the new tag to create | |
| projectRoot | Yes | The directory of the project. Must be an absolute path. |
Implementation Reference
- mcp-server/src/tools/add-tag.js:19-98 (registration)Registers the 'add_tag' MCP tool including input schema, description, and execute handler that delegates to addTagDirect after path resolution.export function registerAddTagTool(server) { server.addTool({ name: 'add_tag', description: 'Create a new tag for organizing tasks in different contexts', parameters: z.object({ name: z.string().describe('Name of the new tag to create'), copyFromCurrent: z .boolean() .optional() .describe( 'Whether to copy tasks from the current tag (default: false)' ), copyFromTag: z .string() .optional() .describe('Specific tag to copy tasks from'), fromBranch: z .boolean() .optional() .describe( 'Create tag name from current git branch (ignores name parameter)' ), description: z .string() .optional() .describe('Optional description for the tag'), file: z .string() .optional() .describe('Path to the tasks file (default: tasks/tasks.json)'), projectRoot: z .string() .describe('The directory of the project. Must be an absolute path.') }), execute: withNormalizedProjectRoot(async (args, { log, session }) => { try { log.info(`Starting add-tag with args: ${JSON.stringify(args)}`); // Use args.projectRoot directly (guaranteed by withNormalizedProjectRoot) let tasksJsonPath; try { tasksJsonPath = findTasksPath( { projectRoot: args.projectRoot, file: args.file }, log ); } catch (error) { log.error(`Error finding tasks.json: ${error.message}`); return createErrorResponse( `Failed to find tasks.json: ${error.message}` ); } // Call the direct function const result = await addTagDirect( { tasksJsonPath: tasksJsonPath, name: args.name, copyFromCurrent: args.copyFromCurrent, copyFromTag: args.copyFromTag, fromBranch: args.fromBranch, description: args.description, projectRoot: args.projectRoot }, log, { session } ); return handleApiResult({ result, log: log, errorPrefix: 'Error creating tag', projectRoot: args.projectRoot }); } catch (error) { log.error(`Error in add-tag tool: ${error.message}`); return createErrorResponse(error.message); } }) }); }
- Core handler function addTagDirect that implements the add tag logic, supporting creation from branch or direct name, with git integration and error handling.export async function addTagDirect(args, log, context = {}) { // Destructure expected args const { tasksJsonPath, name, copyFromCurrent = false, copyFromTag, fromBranch = false, description, projectRoot } = args; const { session } = context; // Enable silent mode to prevent console logs from interfering with JSON response enableSilentMode(); // Create logger wrapper using the utility const mcpLog = createLogWrapper(log); try { // Check if tasksJsonPath was provided if (!tasksJsonPath) { log.error('addTagDirect called without tasksJsonPath'); disableSilentMode(); return { success: false, error: { code: 'MISSING_ARGUMENT', message: 'tasksJsonPath is required' } }; } // Handle --from-branch option if (fromBranch) { log.info('Creating tag from current git branch'); // Import git utilities const gitUtils = await import( '../../../../scripts/modules/utils/git-utils.js' ); // Check if we're in a git repository if (!(await gitUtils.isGitRepository(projectRoot))) { log.error('Not in a git repository'); disableSilentMode(); return { success: false, error: { code: 'NOT_GIT_REPO', message: 'Not in a git repository. Cannot use fromBranch option.' } }; } // Get current git branch const currentBranch = await gitUtils.getCurrentBranch(projectRoot); if (!currentBranch) { log.error('Could not determine current git branch'); disableSilentMode(); return { success: false, error: { code: 'NO_CURRENT_BRANCH', message: 'Could not determine current git branch.' } }; } // Prepare options for branch-based tag creation const branchOptions = { copyFromCurrent, copyFromTag, description: description || `Tag created from git branch "${currentBranch}"` }; // Call the createTagFromBranch function const result = await createTagFromBranch( tasksJsonPath, currentBranch, branchOptions, { session, mcpLog, projectRoot }, 'json' // outputFormat - use 'json' to suppress CLI UI ); // Restore normal logging disableSilentMode(); return { success: true, data: { branchName: result.branchName, tagName: result.tagName, created: result.created, mappingUpdated: result.mappingUpdated, message: `Successfully created tag "${result.tagName}" from git branch "${result.branchName}"` } }; } else { // Check required parameters for regular tag creation if (!name || typeof name !== 'string') { log.error('Missing required parameter: name'); disableSilentMode(); return { success: false, error: { code: 'MISSING_PARAMETER', message: 'Tag name is required and must be a string' } }; } log.info(`Creating new tag: ${name}`); // Prepare options const options = { copyFromCurrent, copyFromTag, description }; // Call the createTag function const result = await createTag( tasksJsonPath, name, options, { session, mcpLog, projectRoot }, 'json' // outputFormat - use 'json' to suppress CLI UI ); // Restore normal logging disableSilentMode(); return { success: true, data: { tagName: result.tagName, created: result.created, tasksCopied: result.tasksCopied, sourceTag: result.sourceTag, description: result.description, message: `Successfully created tag "${result.tagName}"` } }; } } catch (error) { // Make sure to restore normal logging even if there's an error disableSilentMode(); log.error(`Error in addTagDirect: ${error.message}`); return { success: false, error: { code: error.code || 'ADD_TAG_ERROR', message: error.message } }; } }
- mcp-server/src/tools/tool-registry.js:8-89 (registration)Tool registry entry mapping 'add_tag' to its registration function for dynamic tool setup.import { registerAddTagTool } from './add-tag.js'; import { registerAddTaskTool } from './add-task.js'; import { registerAnalyzeProjectComplexityTool } from './analyze.js'; import { registerClearSubtasksTool } from './clear-subtasks.js'; import { registerComplexityReportTool } from './complexity-report.js'; import { registerCopyTagTool } from './copy-tag.js'; import { registerDeleteTagTool } from './delete-tag.js'; import { registerExpandAllTool } from './expand-all.js'; import { registerExpandTaskTool } from './expand-task.js'; import { registerFixDependenciesTool } from './fix-dependencies.js'; import { registerInitializeProjectTool } from './initialize-project.js'; import { registerListTagsTool } from './list-tags.js'; import { registerModelsTool } from './models.js'; import { registerMoveTaskTool } from './move-task.js'; import { registerNextTaskTool } from './next-task.js'; import { registerParsePRDTool } from './parse-prd.js'; import { registerRemoveDependencyTool } from './remove-dependency.js'; import { registerRemoveSubtaskTool } from './remove-subtask.js'; import { registerRemoveTaskTool } from './remove-task.js'; import { registerRenameTagTool } from './rename-tag.js'; import { registerResearchTool } from './research.js'; import { registerResponseLanguageTool } from './response-language.js'; import { registerRulesTool } from './rules.js'; import { registerScopeDownTool } from './scope-down.js'; import { registerScopeUpTool } from './scope-up.js'; import { registerUpdateSubtaskTool } from './update-subtask.js'; import { registerUpdateTaskTool } from './update-task.js'; import { registerUpdateTool } from './update.js'; import { registerUseTagTool } from './use-tag.js'; import { registerValidateDependenciesTool } from './validate-dependencies.js'; // Import TypeScript tools from apps/mcp import { registerAutopilotAbortTool, registerAutopilotCommitTool, registerAutopilotCompleteTool, registerAutopilotFinalizeTool, registerAutopilotNextTool, registerAutopilotResumeTool, registerAutopilotStartTool, registerAutopilotStatusTool, registerGenerateTool, registerGetTaskTool, registerGetTasksTool, registerSetTaskStatusTool } from '@tm/mcp'; /** * Comprehensive tool registry mapping tool names to their registration functions * Used for dynamic tool registration and validation */ export const toolRegistry = { initialize_project: registerInitializeProjectTool, models: registerModelsTool, rules: registerRulesTool, parse_prd: registerParsePRDTool, 'response-language': registerResponseLanguageTool, analyze_project_complexity: registerAnalyzeProjectComplexityTool, expand_task: registerExpandTaskTool, expand_all: registerExpandAllTool, scope_up_task: registerScopeUpTool, scope_down_task: registerScopeDownTool, get_tasks: registerGetTasksTool, get_task: registerGetTaskTool, next_task: registerNextTaskTool, complexity_report: registerComplexityReportTool, set_task_status: registerSetTaskStatusTool, add_task: registerAddTaskTool, add_subtask: registerAddSubtaskTool, update: registerUpdateTool, update_task: registerUpdateTaskTool, update_subtask: registerUpdateSubtaskTool, remove_task: registerRemoveTaskTool, remove_subtask: registerRemoveSubtaskTool, clear_subtasks: registerClearSubtasksTool, move_task: registerMoveTaskTool, add_dependency: registerAddDependencyTool, remove_dependency: registerRemoveDependencyTool, validate_dependencies: registerValidateDependenciesTool, fix_dependencies: registerFixDependenciesTool, list_tags: registerListTagsTool, add_tag: registerAddTagTool,
- mcp-server/src/core/task-master-core.js:9-72 (registration)Re-exports and registers addTagDirect in the central direct functions map.import { addTagDirect } from './direct-functions/add-tag.js'; import { addTaskDirect } from './direct-functions/add-task.js'; import { analyzeTaskComplexityDirect } from './direct-functions/analyze-task-complexity.js'; // Import direct function implementations import { getCacheStatsDirect } from './direct-functions/cache-stats.js'; import { clearSubtasksDirect } from './direct-functions/clear-subtasks.js'; import { complexityReportDirect } from './direct-functions/complexity-report.js'; import { copyTagDirect } from './direct-functions/copy-tag.js'; import { deleteTagDirect } from './direct-functions/delete-tag.js'; import { expandAllTasksDirect } from './direct-functions/expand-all-tasks.js'; import { expandTaskDirect } from './direct-functions/expand-task.js'; import { fixDependenciesDirect } from './direct-functions/fix-dependencies.js'; import { initializeProjectDirect } from './direct-functions/initialize-project.js'; import { listTagsDirect } from './direct-functions/list-tags.js'; import { modelsDirect } from './direct-functions/models.js'; import { moveTaskCrossTagDirect } from './direct-functions/move-task-cross-tag.js'; import { moveTaskDirect } from './direct-functions/move-task.js'; import { nextTaskDirect } from './direct-functions/next-task.js'; import { parsePRDDirect } from './direct-functions/parse-prd.js'; import { removeDependencyDirect } from './direct-functions/remove-dependency.js'; import { removeSubtaskDirect } from './direct-functions/remove-subtask.js'; import { removeTaskDirect } from './direct-functions/remove-task.js'; import { renameTagDirect } from './direct-functions/rename-tag.js'; import { researchDirect } from './direct-functions/research.js'; import { scopeDownDirect } from './direct-functions/scope-down.js'; import { scopeUpDirect } from './direct-functions/scope-up.js'; import { setTaskStatusDirect } from './direct-functions/set-task-status.js'; import { updateSubtaskByIdDirect } from './direct-functions/update-subtask-by-id.js'; import { updateTaskByIdDirect } from './direct-functions/update-task-by-id.js'; import { updateTasksDirect } from './direct-functions/update-tasks.js'; import { useTagDirect } from './direct-functions/use-tag.js'; import { validateDependenciesDirect } from './direct-functions/validate-dependencies.js'; // Re-export utility functions export { findTasksPath } from './utils/path-utils.js'; // Use Map for potential future enhancements like introspection or dynamic dispatch export const directFunctions = new Map([ ['getCacheStatsDirect', getCacheStatsDirect], ['parsePRDDirect', parsePRDDirect], ['updateTasksDirect', updateTasksDirect], ['updateTaskByIdDirect', updateTaskByIdDirect], ['updateSubtaskByIdDirect', updateSubtaskByIdDirect], ['setTaskStatusDirect', setTaskStatusDirect], ['nextTaskDirect', nextTaskDirect], ['expandTaskDirect', expandTaskDirect], ['addTaskDirect', addTaskDirect], ['addSubtaskDirect', addSubtaskDirect], ['removeSubtaskDirect', removeSubtaskDirect], ['analyzeTaskComplexityDirect', analyzeTaskComplexityDirect], ['clearSubtasksDirect', clearSubtasksDirect], ['expandAllTasksDirect', expandAllTasksDirect], ['removeDependencyDirect', removeDependencyDirect], ['validateDependenciesDirect', validateDependenciesDirect], ['fixDependenciesDirect', fixDependenciesDirect], ['complexityReportDirect', complexityReportDirect], ['addDependencyDirect', addDependencyDirect], ['removeTaskDirect', removeTaskDirect], ['initializeProjectDirect', initializeProjectDirect], ['modelsDirect', modelsDirect], ['moveTaskDirect', moveTaskDirect], ['moveTaskCrossTagDirect', moveTaskCrossTagDirect], ['researchDirect', researchDirect], ['addTagDirect', addTagDirect],