Skip to main content
Glama

fix_dependencies

Automatically resolve invalid dependencies in task files to ensure project consistency. Specify the project root and task file path to streamline task management workflows.

Instructions

Fix invalid dependencies in tasks automatically

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
fileNoAbsolute path to the tasks file
projectRootYesThe directory of the project. Must be an absolute path.
tagNoTag context to operate on

Implementation Reference

  • Registration function that adds the 'fix_dependencies' tool to the MCP server, including schema (parameters) and handler (execute). This is the primary definition of the MCP tool.
    export function registerFixDependenciesTool(server) {
    	server.addTool({
    		name: 'fix_dependencies',
    		description: 'Fix invalid dependencies in tasks automatically',
    		parameters: z.object({
    			file: z.string().optional().describe('Absolute path to the tasks file'),
    			projectRoot: z
    				.string()
    				.describe('The directory of the project. Must be an absolute path.'),
    			tag: z.string().optional().describe('Tag context to operate on')
    		}),
    		execute: withToolContext('fix-dependencies', async (args, context) => {
    			try {
    				context.log.info(
    					`Fixing dependencies 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 },
    						context.log
    					);
    				} catch (error) {
    					context.log.error(`Error finding tasks.json: ${error.message}`);
    					return createErrorResponse(
    						`Failed to find tasks.json: ${error.message}`
    					);
    				}
    
    				const result = await fixDependenciesDirect(
    					{
    						tasksJsonPath: tasksJsonPath,
    						projectRoot: args.projectRoot,
    						tag: resolvedTag
    					},
    					context.log
    				);
    
    				if (result.success) {
    					context.log.info(
    						`Successfully fixed dependencies: ${result.data.message}`
    					);
    				} else {
    					context.log.error(
    						`Failed to fix dependencies: ${result.error.message}`
    					);
    				}
    
    				return handleApiResult({
    					result,
    					log: context.log,
    					errorPrefix: 'Error fixing dependencies',
    					projectRoot: args.projectRoot
    				});
    			} catch (error) {
    				context.log.error(`Error in fixDependencies tool: ${error.message}`);
    				return createErrorResponse(error.message);
    			}
    		})
    	});
    }
  • The core execution handler for the fix_dependencies tool. Handles input parameters, resolves paths and tags, locates tasks.json, calls the direct fix function, and returns structured results.
    execute: withToolContext('fix-dependencies', async (args, context) => {
    	try {
    		context.log.info(
    			`Fixing dependencies 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 },
    				context.log
    			);
    		} catch (error) {
    			context.log.error(`Error finding tasks.json: ${error.message}`);
    			return createErrorResponse(
    				`Failed to find tasks.json: ${error.message}`
    			);
    		}
    
    		const result = await fixDependenciesDirect(
    			{
    				tasksJsonPath: tasksJsonPath,
    				projectRoot: args.projectRoot,
    				tag: resolvedTag
    			},
    			context.log
    		);
    
    		if (result.success) {
    			context.log.info(
    				`Successfully fixed dependencies: ${result.data.message}`
    			);
    		} else {
    			context.log.error(
    				`Failed to fix dependencies: ${result.error.message}`
    			);
    		}
    
    		return handleApiResult({
    			result,
    			log: context.log,
    			errorPrefix: 'Error fixing dependencies',
    			projectRoot: args.projectRoot
    		});
    	} catch (error) {
    		context.log.error(`Error in fixDependencies tool: ${error.message}`);
    		return createErrorResponse(error.message);
    	}
    })
  • Direct function wrapper that calls the underlying fixDependenciesCommand from scripts/modules/dependency-manager.js, handles file existence checks, silent mode, and returns structured success/error responses.
    export async function fixDependenciesDirect(args, log) {
    	// Destructure expected args
    	const { tasksJsonPath, projectRoot, tag } = args;
    	try {
    		log.info(`Fixing invalid dependencies in tasks: ${tasksJsonPath}`);
    
    		// Check if tasksJsonPath was provided
    		if (!tasksJsonPath) {
    			log.error('fixDependenciesDirect called without tasksJsonPath');
    			return {
    				success: false,
    				error: {
    					code: 'MISSING_ARGUMENT',
    					message: 'tasksJsonPath is required'
    				}
    			};
    		}
    
    		// Use provided path
    		const tasksPath = tasksJsonPath;
    
    		// Verify the file exists
    		if (!fs.existsSync(tasksPath)) {
    			return {
    				success: false,
    				error: {
    					code: 'FILE_NOT_FOUND',
    					message: `Tasks file not found at ${tasksPath}`
    				}
    			};
    		}
    
    		// Enable silent mode to prevent console logs from interfering with JSON response
    		enableSilentMode();
    
    		const options = { projectRoot, tag };
    		// Call the original command function using the provided path and proper context
    		await fixDependenciesCommand(tasksPath, options);
    
    		// Restore normal logging
    		disableSilentMode();
    
    		return {
    			success: true,
    			data: {
    				message: 'Dependencies fixed successfully',
    				tasksPath,
    				tag: tag || 'master'
    			}
    		};
    	} catch (error) {
    		// Make sure to restore normal logging even if there's an error
    		disableSilentMode();
    
    		log.error(`Error fixing dependencies: ${error.message}`);
    		return {
    			success: false,
    			error: {
    				code: 'FIX_DEPENDENCIES_ERROR',
    				message: error.message
    			}
    		};
    	}
    }
  • Central tool registry that maps the 'fix_dependencies' tool name to its registration function, allowing dynamic tool registration.
    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,
  • The core command function implementing the dependency fixing logic: removes duplicates, invalid/missing dependencies, self-dependencies, and breaks circular dependencies in tasks.json. Called by the direct function.
    async function fixDependenciesCommand(tasksPath, options = {}) {
    	const { context = {} } = options;
    	log('info', 'Checking for and fixing invalid dependencies in tasks.json...');
    
    	try {
    		// Read tasks data
    		const data = readJSON(tasksPath, context.projectRoot, context.tag);
    		if (!data || !data.tasks) {
    			log('error', 'No valid tasks found in tasks.json');
    			process.exit(1);
    		}
    
    		// Create a deep copy of the original data for comparison
    		const originalData = JSON.parse(JSON.stringify(data));
    
    		// Track fixes for reporting
    		const stats = {
    			nonExistentDependenciesRemoved: 0,
    			selfDependenciesRemoved: 0,
    			duplicateDependenciesRemoved: 0,
    			circularDependenciesFixed: 0,
    			tasksFixed: 0,
    			subtasksFixed: 0
    		};
    
    		// First phase: Remove duplicate dependencies in tasks
    		data.tasks.forEach((task) => {
    			if (task.dependencies && Array.isArray(task.dependencies)) {
    				const uniqueDeps = new Set();
    				const originalLength = task.dependencies.length;
    				task.dependencies = task.dependencies.filter((depId) => {
    					const depIdStr = String(depId);
    					if (uniqueDeps.has(depIdStr)) {
    						log(
    							'info',
    							`Removing duplicate dependency from task ${task.id}: ${depId}`
    						);
    						stats.duplicateDependenciesRemoved++;
    						return false;
    					}
    					uniqueDeps.add(depIdStr);
    					return true;
    				});
    				if (task.dependencies.length < originalLength) {
    					stats.tasksFixed++;
    				}
    			}
    
    			// Check for duplicates in subtasks
    			if (task.subtasks && Array.isArray(task.subtasks)) {
    				task.subtasks.forEach((subtask) => {
    					if (subtask.dependencies && Array.isArray(subtask.dependencies)) {
    						const uniqueDeps = new Set();
    						const originalLength = subtask.dependencies.length;
    						subtask.dependencies = subtask.dependencies.filter((depId) => {
    							let depIdStr = String(depId);
    							if (typeof depId === 'number' && depId < 100) {
    								depIdStr = `${task.id}.${depId}`;
    							}
    							if (uniqueDeps.has(depIdStr)) {
    								log(
    									'info',
    									`Removing duplicate dependency from subtask ${task.id}.${subtask.id}: ${depId}`
    								);
    								stats.duplicateDependenciesRemoved++;
    								return false;
    							}
    							uniqueDeps.add(depIdStr);
    							return true;
    						});
    						if (subtask.dependencies.length < originalLength) {
    							stats.subtasksFixed++;
    						}
    					}
    				});
    			}
    		});
    
    		// Create validity maps for tasks and subtasks
    		const validTaskIds = new Set(data.tasks.map((t) => t.id));
    		const validSubtaskIds = new Set();
    		data.tasks.forEach((task) => {
    			if (task.subtasks && Array.isArray(task.subtasks)) {
    				task.subtasks.forEach((subtask) => {
    					validSubtaskIds.add(`${task.id}.${subtask.id}`);
    				});
    			}
    		});
    
    		// Second phase: Remove invalid task dependencies (non-existent tasks)
    		data.tasks.forEach((task) => {
    			if (task.dependencies && Array.isArray(task.dependencies)) {
    				const originalLength = task.dependencies.length;
    				task.dependencies = task.dependencies.filter((depId) => {
    					const isSubtask = typeof depId === 'string' && depId.includes('.');
    
    					if (isSubtask) {
    						// Check if the subtask exists
    						if (!validSubtaskIds.has(depId)) {
    							log(
    								'info',
    								`Removing invalid subtask dependency from task ${task.id}: ${depId} (subtask does not exist)`
    							);
    							stats.nonExistentDependenciesRemoved++;
    							return false;
    						}
    						return true;
    					} else {
    						// Check if the task exists
    						const numericId =
    							typeof depId === 'string' ? parseInt(depId, 10) : depId;
    						if (!validTaskIds.has(numericId)) {
    							log(
    								'info',
    								`Removing invalid task dependency from task ${task.id}: ${depId} (task does not exist)`
    							);
    							stats.nonExistentDependenciesRemoved++;
    							return false;
    						}
    						return true;
    					}
    				});
    
    				if (task.dependencies.length < originalLength) {
    					stats.tasksFixed++;
    				}
    			}
    
    			// Check subtask dependencies for invalid references
    			if (task.subtasks && Array.isArray(task.subtasks)) {
    				task.subtasks.forEach((subtask) => {
    					if (subtask.dependencies && Array.isArray(subtask.dependencies)) {
    						const originalLength = subtask.dependencies.length;
    						const subtaskId = `${task.id}.${subtask.id}`;
    
    						// First check for self-dependencies
    						const hasSelfDependency = subtask.dependencies.some((depId) => {
    							if (typeof depId === 'string' && depId.includes('.')) {
    								return depId === subtaskId;
    							} else if (typeof depId === 'number' && depId < 100) {
    								return depId === subtask.id;
    							}
    							return false;
    						});
    
    						if (hasSelfDependency) {
    							subtask.dependencies = subtask.dependencies.filter((depId) => {
    								const normalizedDepId =
    									typeof depId === 'number' && depId < 100
    										? `${task.id}.${depId}`
    										: String(depId);
    
    								if (normalizedDepId === subtaskId) {
    									log(
    										'info',
    										`Removing self-dependency from subtask ${subtaskId}`
    									);
    									stats.selfDependenciesRemoved++;
    									return false;
    								}
    								return true;
    							});
    						}
    
    						// Then check for non-existent dependencies
    						subtask.dependencies = subtask.dependencies.filter((depId) => {
    							if (typeof depId === 'string' && depId.includes('.')) {
    								if (!validSubtaskIds.has(depId)) {
    									log(
    										'info',
    										`Removing invalid subtask dependency from subtask ${subtaskId}: ${depId} (subtask does not exist)`
    									);
    									stats.nonExistentDependenciesRemoved++;
    									return false;
    								}
    								return true;
    							}
    
    							// Handle numeric dependencies
    							const numericId =
    								typeof depId === 'number' ? depId : parseInt(depId, 10);
    
    							// Small numbers likely refer to subtasks in the same task
    							if (numericId < 100) {
    								const fullSubtaskId = `${task.id}.${numericId}`;
    
    								if (!validSubtaskIds.has(fullSubtaskId)) {
    									log(
    										'info',
    										`Removing invalid subtask dependency from subtask ${subtaskId}: ${numericId}`
    									);
    									stats.nonExistentDependenciesRemoved++;
    									return false;
    								}
    
    								return true;
    							}
    
    							// Otherwise it's a task reference
    							if (!validTaskIds.has(numericId)) {
    								log(
    									'info',
    									`Removing invalid task dependency from subtask ${subtaskId}: ${numericId}`
    								);
    								stats.nonExistentDependenciesRemoved++;
    								return false;
    							}
    
    							return true;
    						});
    
    						if (subtask.dependencies.length < originalLength) {
    							stats.subtasksFixed++;
    						}
    					}
    				});
    			}
    		});
    
    		// Third phase: Check for circular dependencies
    		log('info', 'Checking for circular dependencies...');
    
    		// Build the dependency map for subtasks
    		const subtaskDependencyMap = new Map();
    		data.tasks.forEach((task) => {
    			if (task.subtasks && Array.isArray(task.subtasks)) {
    				task.subtasks.forEach((subtask) => {
    					const subtaskId = `${task.id}.${subtask.id}`;
    
    					if (subtask.dependencies && Array.isArray(subtask.dependencies)) {
    						const normalizedDeps = subtask.dependencies.map((depId) => {
    							if (typeof depId === 'string' && depId.includes('.')) {
    								return depId;
    							} else if (typeof depId === 'number' && depId < 100) {
    								return `${task.id}.${depId}`;
    							}
    							return String(depId);
    						});
    						subtaskDependencyMap.set(subtaskId, normalizedDeps);
    					} else {
    						subtaskDependencyMap.set(subtaskId, []);
    					}
    				});
    			}
    		});
    
    		// Check for and fix circular dependencies
    		for (const [subtaskId, dependencies] of subtaskDependencyMap.entries()) {
    			const visited = new Set();
    			const recursionStack = new Set();
    
    			// Detect cycles
    			const cycleEdges = findCycles(
    				subtaskId,
    				subtaskDependencyMap,
    				visited,
    				recursionStack
    			);
    
    			if (cycleEdges.length > 0) {
    				const [taskId, subtaskNum] = subtaskId
    					.split('.')
    					.map((part) => Number(part));
    				const task = data.tasks.find((t) => t.id === taskId);
    
    				if (task && task.subtasks) {
    					const subtask = task.subtasks.find((st) => st.id === subtaskNum);
    
    					if (subtask && subtask.dependencies) {
    						const originalLength = subtask.dependencies.length;
    
    						const edgesToRemove = cycleEdges.map((edge) => {
    							if (edge.includes('.')) {
    								const [depTaskId, depSubtaskId] = edge
    									.split('.')
    									.map((part) => Number(part));
    
    								if (depTaskId === taskId) {
    									return depSubtaskId;
    								}
    
    								return edge;
    							}
    
    							return Number(edge);
    						});
    
    						subtask.dependencies = subtask.dependencies.filter((depId) => {
    							const normalizedDepId =
    								typeof depId === 'number' && depId < 100
    									? `${taskId}.${depId}`
    									: String(depId);
    
    							if (
    								edgesToRemove.includes(depId) ||
    								edgesToRemove.includes(normalizedDepId)
    							) {
    								log(
    									'info',
    									`Breaking circular dependency: Removing ${normalizedDepId} from subtask ${subtaskId}`
    								);
    								stats.circularDependenciesFixed++;
    								return false;
    							}
    							return true;
    						});
    
    						if (subtask.dependencies.length < originalLength) {
    							stats.subtasksFixed++;
    						}
    					}
    				}
    			}
    		}
    
    		// Check if any changes were made by comparing with original data
    		const dataChanged = JSON.stringify(data) !== JSON.stringify(originalData);
    
    		if (dataChanged) {
    			// Save the changes
    			writeJSON(tasksPath, data, context.projectRoot, context.tag);
    			log('success', 'Fixed dependency issues in tasks.json');
    
    			// Regenerate task files
    			log('info', 'Regenerating task files to reflect dependency changes...');
    			// await generateTaskFiles(tasksPath, path.dirname(tasksPath));
    		} else {
    			log('info', 'No changes needed to fix dependencies');
    		}
    
    		// Show detailed statistics report
    		const totalFixedAll =
    			stats.nonExistentDependenciesRemoved +
    			stats.selfDependenciesRemoved +
    			stats.duplicateDependenciesRemoved +
    			stats.circularDependenciesFixed;
    
    		if (!isSilentMode()) {
    			if (totalFixedAll > 0) {
    				log('success', `Fixed ${totalFixedAll} dependency issues in total!`);
    
    				console.log(
    					boxen(
    						chalk.green(`Dependency Fixes Summary:\n\n`) +
    							`${chalk.cyan('Invalid dependencies removed:')} ${stats.nonExistentDependenciesRemoved}\n` +
    							`${chalk.cyan('Self-dependencies removed:')} ${stats.selfDependenciesRemoved}\n` +
    							`${chalk.cyan('Duplicate dependencies removed:')} ${stats.duplicateDependenciesRemoved}\n` +
    							`${chalk.cyan('Circular dependencies fixed:')} ${stats.circularDependenciesFixed}\n\n` +
    							`${chalk.cyan('Tasks fixed:')} ${stats.tasksFixed}\n` +
    							`${chalk.cyan('Subtasks fixed:')} ${stats.subtasksFixed}\n`,
    						{
    							padding: 1,
    							borderColor: 'green',
    							borderStyle: 'round',
    							margin: { top: 1, bottom: 1 }
    						}
    					)
    				);
    			} else {
    				log(
    					'success',
    					'No dependency issues found - all dependencies are valid'
    				);
    
    				console.log(
    					boxen(
    						chalk.green(`All Dependencies Are Valid\n\n`) +
    							`${chalk.cyan('Tasks checked:')} ${data.tasks.length}\n` +
    							`${chalk.cyan('Total dependencies verified:')} ${countAllDependencies(data.tasks)}`,
    						{
    							padding: 1,
    							borderColor: 'green',
    							borderStyle: 'round',
    							margin: { top: 1, bottom: 1 }
    						}
    					)
    				);
    			}
    		}
    	} catch (error) {
    		log('error', 'Error in fix-dependencies command:', error);
    		process.exit(1);
    	}
Behavior2/5

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

With no annotations provided, the description carries full burden but offers minimal behavioral insight. It mentions 'automatically', hinting at automation, but doesn't disclose critical traits like whether it's destructive (modifies files), requires specific permissions, has side effects, or how it handles errors. For a tool that likely modifies task dependencies, this is a significant gap in transparency.

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 with zero waste. It's front-loaded with the core purpose ('Fix invalid dependencies'), and 'automatically' adds useful context without verbosity. Every word earns its place, making it highly concise and well-structured.

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?

Given no annotations, no output schema, and a tool that likely performs mutations (fixing dependencies), the description is incomplete. It lacks details on behavior, outcomes, error handling, or how it interacts with sibling tools. For a 3-parameter tool with potential side effects, this minimal description is inadequate.

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 the schema fully documents parameters (file, projectRoot, tag). The description adds no meaning beyond the schema—it doesn't explain how parameters relate to fixing dependencies (e.g., if 'tag' limits scope). Baseline is 3 as the schema does the heavy lifting, but no extra value is provided.

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 'Fix invalid dependencies in tasks automatically' clearly states the action (fix), target (invalid dependencies), and scope (in tasks). It distinguishes from siblings like 'add_dependency' or 'remove_dependency' by focusing on fixing rather than adding/removing. However, it doesn't specify what makes dependencies 'invalid' or the exact mechanism, keeping it from a perfect score.

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?

The description provides no guidance on when to use this tool versus alternatives like 'validate_dependencies' or 'add_dependency'. It doesn't mention prerequisites (e.g., after validation fails) or exclusions (e.g., for manual fixes). Usage is implied only by the verb 'fix', but no explicit context is given.

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