Skip to main content
Glama

scope_down_task

Simplify complex tasks efficiently with AI by adjusting their scope. Input task IDs, define strength levels, and apply custom prompts for precise task management in AI-driven development workflows.

Instructions

Decrease the complexity of one or more tasks using AI

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
fileNoPath to the tasks file (default: tasks/tasks.json)
idYesComma-separated list of task IDs to scope down (e.g., "1,3,5")
projectRootYesThe directory of the project. Must be an absolute path.
promptNoCustom prompt for specific scoping adjustments
researchNoWhether to use research capabilities for scoping
strengthNoStrength level: light, regular, or heavy (default: regular)
tagNoTag context to operate on

Implementation Reference

  • Core handler function implementing the logic to scope down task complexity: validates inputs, adjusts task descriptions, regenerates subtasks preserving completed ones, optionally reanalyzes complexity, and updates the tasks.json file.
    export async function scopeDownTask( tasksPath, taskIds, strength = 'regular', customPrompt = null, context = {}, outputFormat = 'text' ) { // Validate inputs if (!validateStrength(strength)) { throw new Error( `Invalid strength level: ${strength}. Must be one of: ${VALID_STRENGTHS.join(', ')}` ); } const { projectRoot = '.', tag = 'master' } = context; // Read tasks data const data = readJSON(tasksPath, projectRoot, tag); const tasks = data?.tasks || []; // Validate all task IDs exist for (const taskId of taskIds) { if (!taskExists(tasks, taskId)) { throw new Error(`Task with ID ${taskId} not found`); } } const updatedTasks = []; let combinedTelemetryData = null; // Process each task for (const taskId of taskIds) { const taskResult = findTaskById(tasks, taskId); const task = taskResult.task; if (!task) { throw new Error(`Task with ID ${taskId} not found`); } if (outputFormat === 'text') { log('info', `Scoping down task ${taskId}: ${task.title}`); } // Get original complexity score (if available) const originalComplexity = getCurrentComplexityScore(taskId, context); if (originalComplexity && outputFormat === 'text') { log('info', `Original complexity: ${originalComplexity}/10`); } const adjustResult = await adjustTaskComplexity( task, 'down', strength, customPrompt, context ); // Regenerate subtasks based on new complexity while preserving completed work const subtaskResult = await regenerateSubtasksForComplexity( adjustResult.updatedTask, tasksPath, context, 'down', strength, originalComplexity ); // Log subtask regeneration info if in text mode if (outputFormat === 'text' && subtaskResult.regenerated) { log( 'info', `Regenerated ${subtaskResult.generated} pending subtasks (preserved ${subtaskResult.preserved} completed)` ); } // Update task in data const taskIndex = data.tasks.findIndex((t) => t.id === taskId); if (taskIndex !== -1) { data.tasks[taskIndex] = subtaskResult.updatedTask; updatedTasks.push(subtaskResult.updatedTask); } // Re-analyze complexity after scoping (if we have a session for AI calls) if (context.session && originalComplexity) { try { // Write the updated task first so complexity analysis can read it writeJSON(tasksPath, data, projectRoot, tag); // Re-analyze complexity const newComplexity = await reanalyzeTaskComplexity( subtaskResult.updatedTask, tasksPath, context ); if (newComplexity && outputFormat === 'text') { const complexityChange = newComplexity - originalComplexity; const arrow = complexityChange > 0 ? '↗️' : complexityChange < 0 ? '↘️' : '➡️'; log( 'info', `New complexity: ${originalComplexity}/10 ${arrow} ${newComplexity}/10 (${complexityChange > 0 ? '+' : ''}${complexityChange})` ); } } catch (error) { if (outputFormat === 'text') { log('warn', `Could not re-analyze complexity: ${error.message}`); } } } // Combine telemetry data if (adjustResult.telemetryData) { if (!combinedTelemetryData) { combinedTelemetryData = { ...adjustResult.telemetryData }; } else { // Sum up costs and tokens combinedTelemetryData.inputTokens += adjustResult.telemetryData.inputTokens || 0; combinedTelemetryData.outputTokens += adjustResult.telemetryData.outputTokens || 0; combinedTelemetryData.totalTokens += adjustResult.telemetryData.totalTokens || 0; combinedTelemetryData.totalCost += adjustResult.telemetryData.totalCost || 0; } } } // Write updated data writeJSON(tasksPath, data, projectRoot, tag); if (outputFormat === 'text') { log('info', `Successfully scoped down ${updatedTasks.length} task(s)`); } return { updatedTasks, telemetryData: combinedTelemetryData }; }
  • Direct function wrapper for scopeDownTask, handles MCP-specific logging, silent mode, argument parsing, and error formatting.
    export async function scopeDownDirect(args, log, context = {}) { // Destructure expected args const { tasksJsonPath, id, strength = 'regular', prompt: customPrompt, research = false, projectRoot, tag } = args; const { session } = context; // Destructure session from 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('scopeDownDirect called without tasksJsonPath'); disableSilentMode(); // Disable before returning return { success: false, error: { code: 'MISSING_ARGUMENT', message: 'tasksJsonPath is required' } }; } // Check required parameters if (!id) { log.error('Missing required parameter: id'); disableSilentMode(); return { success: false, error: { code: 'MISSING_PARAMETER', message: 'The id parameter is required for scoping down tasks' } }; } // Parse task IDs - convert to numbers as expected by scopeDownTask const taskIds = id.split(',').map((taskId) => parseInt(taskId.trim(), 10)); log.info( `Scoping down tasks: ${taskIds.join(', ')}, strength: ${strength}, research: ${research}` ); // Call the scopeDownTask function const result = await scopeDownTask( tasksJsonPath, taskIds, strength, customPrompt, { session, mcpLog, projectRoot, commandName: 'scope-down', outputType: 'mcp', tag, research }, 'json' // outputFormat ); // Restore normal logging disableSilentMode(); return { success: true, data: { updatedTasks: result.updatedTasks, tasksUpdated: result.updatedTasks.length, message: `Successfully scoped down ${result.updatedTasks.length} task(s)`, telemetryData: result.telemetryData } }; } catch (error) { // Make sure to restore normal logging even if there's an error disableSilentMode(); log.error(`Error in scopeDownDirect: ${error.message}`); return { success: false, error: { code: error.code || 'SCOPE_DOWN_ERROR', message: error.message } }; } }
  • Zod schema defining input parameters for the scope_down_task tool.
    parameters: z.object({ id: z .string() .describe( 'Comma-separated list of task IDs to scope down (e.g., "1,3,5")' ), strength: z .string() .optional() .describe( 'Strength level: light, regular, or heavy (default: regular)' ), prompt: z .string() .optional() .describe('Custom prompt for specific scoping adjustments'), 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.'), tag: z.string().optional().describe('Tag context to operate on'), research: z .boolean() .optional() .describe('Whether to use research capabilities for scoping') }),
  • Registration function that adds the 'scope_down_task' tool to the MCP server, including name, description, schema, and execute handler.
    export function registerScopeDownTool(server) { server.addTool({ name: 'scope_down_task', description: 'Decrease the complexity of one or more tasks using AI', parameters: z.object({ id: z .string() .describe( 'Comma-separated list of task IDs to scope down (e.g., "1,3,5")' ), strength: z .string() .optional() .describe( 'Strength level: light, regular, or heavy (default: regular)' ), prompt: z .string() .optional() .describe('Custom prompt for specific scoping adjustments'), 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.'), tag: z.string().optional().describe('Tag context to operate on'), research: z .boolean() .optional() .describe('Whether to use research capabilities for scoping') }), execute: withNormalizedProjectRoot(async (args, { log, session }) => { try { log.info(`Starting scope-down with args: ${JSON.stringify(args)}`); const resolvedTag = resolveTag({ projectRoot: args.projectRoot, tag: args.tag }); // 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 scopeDownDirect( { tasksJsonPath: tasksJsonPath, id: args.id, strength: args.strength, prompt: args.prompt, research: args.research, projectRoot: args.projectRoot, tag: resolvedTag }, log, { session } ); return handleApiResult({ result, log: log, errorPrefix: 'Error scoping down task', projectRoot: args.projectRoot }); } catch (error) { log.error(`Error in scope-down tool: ${error.message}`); return createErrorResponse(error.message); } }) }); }
  • Central tool registry entry mapping 'scope_down_task' to its registration function registerScopeDownTool.
    scope_down_task: registerScopeDownTool,

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/eyaltoledano/claude-task-master'

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