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,
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It mentions 'using AI' which hints at automation, but doesn't explain what 'decrease complexity' means operationally, whether changes are reversible, what permissions are needed, or how the tool interacts with the task system. Significant behavioral aspects remain undocumented.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, efficient sentence that communicates the core purpose without unnecessary elaboration. It's appropriately sized and front-loaded with the essential information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with 7 parameters, no annotations, and no output schema, the description is insufficient. It doesn't explain what 'decrease complexity' means in practice, what the expected outcome looks like, or how this tool differs from related task modification tools. The agent would need to guess about the tool's behavior and results.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so parameters are well-documented in the schema itself. The description doesn't add any parameter-specific information beyond what's already in the schema descriptions. The baseline of 3 is appropriate when the schema does the heavy lifting for parameter documentation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('decrease complexity') and resource ('one or more tasks'), with the method ('using AI') providing additional context. However, it doesn't differentiate from sibling tools like 'scope_up_task' (which presumably increases complexity) or 'analyze_project_complexity' (which analyzes rather than modifies).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No explicit guidance on when to use this tool versus alternatives is provided. The description doesn't mention sibling tools like 'scope_up_task' for increasing complexity or 'add_subtask' for breaking down tasks differently. Usage context is implied but not specified.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

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

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