delete_directory
Remove a directory by specifying its path, with an option to delete contents recursively. Supports both relative and absolute paths for flexible file management.
Instructions
Removes a directory. Optionally removes recursively. Accepts relative or absolute paths.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | The path to the directory to delete. Can be relative or absolute. | |
| recursive | No | If true, delete the directory and all its contents. If false, only delete if the directory is empty. |
Implementation Reference
- Core handler function that executes the delete directory logic: resolves path, checks existence and type, deletes recursively or if empty using fs.promises APIs, handles various errors with McpError.export const deleteDirectoryLogic = async (input: DeleteDirectoryInput, context: RequestContext): Promise<DeleteDirectoryOutput> => { const { path: requestedPath, recursive } = input; const logicContext = { ...context, tool: 'deleteDirectoryLogic', recursive }; logger.debug(`deleteDirectoryLogic: Received request to delete directory "${requestedPath}"`, logicContext); // Resolve the path const absolutePath = serverState.resolvePath(requestedPath, context); logger.debug(`deleteDirectoryLogic: Resolved path to "${absolutePath}"`, { ...logicContext, requestedPath }); try { // Check if the path exists and is a directory before attempting deletion let stats; try { stats = await fs.stat(absolutePath); } catch (statError: any) { if (statError.code === 'ENOENT') { logger.warning(`deleteDirectoryLogic: Directory not found at "${absolutePath}"`, { ...logicContext, requestedPath }); throw new McpError(BaseErrorCode.NOT_FOUND, `Directory not found at path: ${absolutePath}`, { ...logicContext, requestedPath, resolvedPath: absolutePath, originalError: statError }); } throw statError; // Re-throw other stat errors } if (!stats.isDirectory()) { logger.warning(`deleteDirectoryLogic: Path is not a directory "${absolutePath}"`, { ...logicContext, requestedPath }); throw new McpError(BaseErrorCode.VALIDATION_ERROR, `Path is not a directory: ${absolutePath}`, { ...logicContext, requestedPath, resolvedPath: absolutePath }); } // Attempt to delete the directory if (recursive) { // Use fs.rm for recursive deletion (available in Node.js 14.14.0+) await fs.rm(absolutePath, { recursive: true, force: true }); // force helps with potential permission issues on subfiles sometimes logger.info(`deleteDirectoryLogic: Successfully deleted directory recursively "${absolutePath}"`, { ...logicContext, requestedPath }); } else { // Use fs.rmdir for non-recursive deletion (fails if not empty) await fs.rmdir(absolutePath); logger.info(`deleteDirectoryLogic: Successfully deleted empty directory "${absolutePath}"`, { ...logicContext, requestedPath }); } return { message: `Successfully deleted directory: ${absolutePath}${recursive ? ' (recursively)' : ' (empty)'}`, deletedPath: absolutePath, wasRecursive: recursive, }; } catch (error: any) { logger.error(`deleteDirectoryLogic: Error deleting directory "${absolutePath}"`, { ...logicContext, requestedPath, error: error.message, code: error.code }); if (error instanceof McpError) { throw error; // Re-throw known McpErrors } if (error.code === 'ENOENT') { // Should have been caught by stat, but handle defensively logger.warning(`deleteDirectoryLogic: Directory not found during delete operation "${absolutePath}"`, { ...logicContext, requestedPath }); throw new McpError(BaseErrorCode.NOT_FOUND, `Directory not found at path: ${absolutePath}`, { ...logicContext, requestedPath, resolvedPath: absolutePath, originalError: error }); } if (error.code === 'ENOTEMPTY' && !recursive) { logger.warning(`deleteDirectoryLogic: Directory not empty and recursive=false "${absolutePath}"`, { ...logicContext, requestedPath }); throw new McpError(BaseErrorCode.VALIDATION_ERROR, `Directory not empty: ${absolutePath}. Use recursive=true to delete non-empty directories.`, { ...logicContext, requestedPath, resolvedPath: absolutePath, originalError: error }); } // Handle other potential I/O errors (e.g., permissions) throw new McpError(BaseErrorCode.INTERNAL_ERROR, `Failed to delete directory: ${error.message || 'Unknown I/O error'}`, { ...logicContext, requestedPath, resolvedPath: absolutePath, originalError: error }); }
- Zod input schema for the delete_directory tool: requires 'path' string and optional 'recursive' boolean (default false).export const DeleteDirectoryInputSchema = z.object({ path: z.string().min(1, 'Path cannot be empty') .describe('The path to the directory to delete. Can be relative or absolute.'), recursive: z.boolean().default(false) .describe('If true, delete the directory and all its contents. If false, only delete if the directory is empty.'), });
- src/mcp-server/tools/deleteDirectory/registration.ts:25-61 (registration)MCP server.tool() registration for 'delete_directory': sets name, description, input shape, and handler that validates input, calls deleteDirectoryLogic, and formats response.server.tool( 'delete_directory', // Tool name 'Removes a directory. Optionally removes recursively. Accepts relative or absolute paths.', // Description DeleteDirectoryInputSchema.shape, // Pass the schema shape async (params, extra) => { // Validate input using the Zod schema const validationResult = DeleteDirectoryInputSchema.safeParse(params); if (!validationResult.success) { const errorContext = requestContextService.createRequestContext({ operation: 'DeleteDirectoryToolValidation' }); logger.error('Invalid input parameters for delete_directory tool', { ...errorContext, errors: validationResult.error.errors }); throw new McpError(BaseErrorCode.VALIDATION_ERROR, `Invalid parameters: ${validationResult.error.errors.map(e => `${e.path.join('.')} - ${e.message}`).join(', ')}`, errorContext); } const typedParams = validationResult.data; // Use validated data // Create context for this execution const callContext = requestContextService.createRequestContext({ operation: 'DeleteDirectoryToolExecution' }); logger.info(`Executing 'delete_directory' tool for path: ${typedParams.path}, recursive: ${typedParams.recursive}`, callContext); // ErrorHandler will catch McpErrors thrown by the logic const result = await ErrorHandler.tryCatch( () => deleteDirectoryLogic(typedParams, callContext), { operation: 'deleteDirectoryLogic', context: callContext, input: sanitization.sanitizeForLogging(typedParams), // Sanitize path errorCode: BaseErrorCode.INTERNAL_ERROR } ); logger.info(`Successfully executed 'delete_directory' for path: ${result.deletedPath}, recursive: ${result.wasRecursive}`, callContext); // Format the successful response return { content: [{ type: 'text', text: result.message }], }; } );
- src/mcp-server/server.ts:88-88 (registration)Invocation of registerDeleteDirectoryTool during server tool registration sequence.registerDeleteDirectoryTool(server),
- TypeScript interface for the output of the delete_directory tool.export interface DeleteDirectoryOutput { message: string; deletedPath: string; wasRecursive: boolean; }