Skip to main content
Glama

rm

Remove files or directories permanently from the filesystem. Specify a path to delete items, with options for recursive deletion of folders and ignoring missing files.

Instructions

Permanently delete a file or directory. This action is irreversible.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
pathYesAbsolute path to file or directory.
recursiveNoDelete non-empty directories
ignoreIfNotExistsNoNo error if missing

Implementation Reference

  • The `handleDeleteFile` function contains the actual logic for deleting files or directories, including handling recursive options and checking for existence.
    async function handleDeleteFile(
      args: z.infer<typeof DeleteFileInputSchema>,
      signal?: AbortSignal
    ): Promise<ToolResponse<z.infer<typeof DeleteFileOutputSchema>>> {
      const validPath = await validatePathForWrite(args.path, signal);
    
      if (isAllowedDirectoryRoot(validPath)) {
        throw new McpError(
          ErrorCode.E_ACCESS_DENIED,
          `Deleting a workspace root directory is not allowed: ${args.path}`
        );
      }
    
      let stats: Awaited<ReturnType<typeof fs.lstat>> | undefined;
      try {
        stats = await withAbort(fs.lstat(validPath), signal);
      } catch (error) {
        if (
          isNodeError(error) &&
          error.code === 'ENOENT' &&
          args.ignoreIfNotExists
        ) {
          return buildToolResponse(`Successfully deleted: ${args.path}`, {
            ok: true,
            path: validPath,
          });
        }
        throw error;
      }
    
      if (stats.isDirectory() && !args.recursive) {
        // Use rmdir for non-recursive directory deletes so non-empty directories
        // consistently return ENOTEMPTY-style errors with actionable guidance.
        await withAbort(fs.rmdir(validPath), signal);
      } else {
        await withAbort(
          fs.rm(validPath, {
            recursive: args.recursive,
            force: args.ignoreIfNotExists,
          }),
          signal
        );
      }
    
      return buildToolResponse(`Successfully deleted: ${args.path}`, {
        ok: true,
        path: validPath,
      });
    }
  • The `registerDeleteFileTool` function registers the 'rm' tool with the MCP server, including the handler, schemas, and icons.
    export function registerDeleteFileTool(
      server: McpServer,
      options: ToolRegistrationOptions = {}
    ): void {
      const handler = (
        args: z.infer<typeof DeleteFileInputSchema>,
        extra: ToolExtra
      ): Promise<ToolResult<z.infer<typeof DeleteFileOutputSchema>>> =>
        executeToolWithDiagnostics({
          toolName: 'rm',
          extra,
          outputSchema: DeleteFileOutputSchema,
          timedSignal: {},
          context: { path: args.path },
          run: (signal) => handleDeleteFile(args, signal),
          onError: (error) => {
            if (isNodeError(error)) {
              if (error.code === 'ENOENT') {
                return buildToolErrorResponse(
                  error,
                  ErrorCode.E_NOT_FOUND,
                  args.path
                );
              }
              if (error.code === 'ENOTEMPTY') {
                return buildToolErrorResponse(
                  new Error(
                    `Directory is not empty: ${args.path}. Use recursive: true to delete non-empty directories.`
                  ),
                  ErrorCode.E_INVALID_INPUT,
                  args.path
                );
              }
              if (error.code === 'EISDIR') {
                return buildToolErrorResponse(
                  new Error(
                    `Path is a directory: ${args.path}. Use recursive: true to delete directories.`
                  ),
                  ErrorCode.E_INVALID_INPUT,
                  args.path
                );
              }
              if (error.code === 'EEXIST') {
                return buildToolErrorResponse(
                  new Error(
                    `Directory is not empty: ${args.path}. Use recursive: true to delete non-empty directories.`
                  ),
                  ErrorCode.E_INVALID_INPUT,
                  args.path
                );
              }
              if (error.code === 'EPERM' || error.code === 'EACCES') {
                return buildToolErrorResponse(
                  error,
                  ErrorCode.E_PERMISSION_DENIED,
                  args.path
                );
              }
            }
            return buildToolErrorResponse(error, ErrorCode.E_UNKNOWN, args.path);
          },
        });
    
      const wrappedHandler = wrapToolHandler(handler, {
        guard: options.isInitialized,
        progressMessage: (args) => `🛠 rm: ${path.basename(args.path)}`,
        completionMessage: (args, result) => {
          const name = path.basename(args.path);
          if (result.isError) return `🛠 rm: ${name} • failed`;
          return `🛠 rm: ${name}`;
        },
      });
    
      const validatedHandler = withValidatedArgs(
        DeleteFileInputSchema,
        wrappedHandler
      );
    
      if (
        registerToolTaskIfAvailable(
          server,
          'rm',
          DELETE_FILE_TOOL,
          validatedHandler,
          options.iconInfo,
          options.isInitialized
        )
      )
        return;
      server.registerTool(
        'rm',
        withDefaultIcons({ ...DELETE_FILE_TOOL }, options.iconInfo),
        validatedHandler
      );
    }
  • The `DELETE_FILE_TOOL` object defines the metadata for the 'rm' tool, including its name, description, and schema references.
    export const DELETE_FILE_TOOL: ToolContract = {
      name: 'rm',
      title: 'Delete File',
      description:
        'Permanently delete a file or directory. This action is irreversible.',
      inputSchema: DeleteFileInputSchema,
      outputSchema: DeleteFileOutputSchema,
      annotations: DESTRUCTIVE_WRITE_TOOL_ANNOTATIONS,
      gotchas: ['Non-empty directories require `recursive=true`.'],
      taskSupport: 'forbidden',
    } as const;

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/j0hanz/filesystem-mcp'

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