Home / Function/ addFilesRecursively() — mcp Function Reference

addFilesRecursively() — mcp Function Reference

Architecture documentation for the addFilesRecursively() function in zip-repository.ts from the mcp codebase.

Entity Profile

Dependency Diagram

graph TD
  3a4a51ae_b292_2750_c894_60a641d584b1["addFilesRecursively()"]
  52a097f2_598d_df67_e422_55b20a202d95["zipRepository()"]
  52a097f2_598d_df67_e422_55b20a202d95 -->|calls| 3a4a51ae_b292_2750_c894_60a641d584b1
  dfe11f52_4dd3_db89_9717_941d05bae091["warn()"]
  3a4a51ae_b292_2750_c894_60a641d584b1 -->|calls| dfe11f52_4dd3_db89_9717_941d05bae091
  7676d97e_3407_e9fb_36e4_f3398b574ec2["error()"]
  3a4a51ae_b292_2750_c894_60a641d584b1 -->|calls| 7676d97e_3407_e9fb_36e4_f3398b574ec2
  b8971bfc_ba3c_23a9_1f17_5d613ac67105["debug()"]
  3a4a51ae_b292_2750_c894_60a641d584b1 -->|calls| b8971bfc_ba3c_23a9_1f17_5d613ac67105
  e2a45e09_2506_abe8_d09f_d033416cdd84["formatBytes()"]
  3a4a51ae_b292_2750_c894_60a641d584b1 -->|calls| e2a45e09_2506_abe8_d09f_d033416cdd84
  style 3a4a51ae_b292_2750_c894_60a641d584b1 fill:#6366f1,stroke:#818cf8,color:#fff

Relationship Graph

Source Code

src/utils/zip-repository.ts lines 588–702

async function addFilesRecursively(
  archive: archiver.Archiver,
  rootDir: string,
  currentDir: string,
  ignoreFilter: Ignore,
  options?: ZipOptions,
  progressState?: ProgressState
): Promise<void> {
  let entries: string[];

  try {
    entries = await fs.readdir(currentDir);
  } catch (error: any) {
    if (error.code === 'EACCES') {
      logger.warn('Permission denied:', currentDir);
      return;
    }
    logger.error('Failed to read directory:', currentDir);
    logger.error('Error:', error.message);
    throw error;
  }

  for (const entry of entries) {
    const fullPath = join(currentDir, entry);
    const relativePath = relative(rootDir, fullPath);

    // Normalize path for ignore matching (use forward slashes)
    const normalizedRelativePath = relativePath.split(sep).join('/');

    // Check if ignored
    if (ignoreFilter.ignores(normalizedRelativePath)) {
      continue;
    }

    let stats;
    try {
      stats = await fs.lstat(fullPath);
    } catch (error: any) {
      if (error.code === 'ENOENT') {
        // File disappeared, skip
        continue;
      }
      console.error('[WARN] Failed to stat:', fullPath, error.message);
      continue;
    }

    // Skip symlinks to prevent following links outside the repository
    if (stats.isSymbolicLink()) {
      logger.warn('Skipping symlink:', fullPath);
      continue;
    }

    if (stats.isDirectory()) {
      // Check if directory itself should be ignored
      const dirPath = normalizedRelativePath + '/';
      if (ignoreFilter.ignores(dirPath)) {
        continue;
      }

      // Recurse into directory
      await addFilesRecursively(archive, rootDir, fullPath, ignoreFilter, options, progressState);
    } else if (stats.isFile()) {
      // Add file to archive
      try {
        archive.file(fullPath, { name: normalizedRelativePath });

        // Track progress if callback is provided
        if (progressState && options?.onProgress) {
          progressState.filesProcessed++;
          progressState.bytesProcessed += stats.size;
          progressState.lastFile = normalizedRelativePath;

          const progressInterval = options.progressInterval || 100;

          // Report progress every N files
          if (progressState.filesProcessed - progressState.lastReportedCount >= progressInterval) {
            logger.debug(
              `Progress: ${progressState.filesProcessed} files, ${formatBytes(progressState.bytesProcessed)}`
            );

            options.onProgress({
              filesProcessed: progressState.filesProcessed,
              currentFile: normalizedRelativePath,
              bytesProcessed: progressState.bytesProcessed,
            });

            progressState.lastReportedCount = progressState.filesProcessed;
          }
        }
      } catch (error: any) {
        logger.warn('Failed to add file:', fullPath, error.message);
      }
    }
    // Skip other special files (sockets, FIFOs, etc.)
  }

  // Report final progress if we have a callback and there are unreported files
  // Only report at the root level (when currentDir === rootDir)
  if (
    currentDir === rootDir &&
    progressState &&
    options?.onProgress &&
    progressState.filesProcessed > progressState.lastReportedCount
  ) {
    logger.debug(
      `Final progress: ${progressState.filesProcessed} files, ${formatBytes(progressState.bytesProcessed)}`
    );

    options.onProgress({
      filesProcessed: progressState.filesProcessed,
      currentFile: progressState.lastFile,
      bytesProcessed: progressState.bytesProcessed,
    });
  }
}

Subdomains

Called By

Frequently Asked Questions

What does addFilesRecursively() do?
addFilesRecursively() is a function in the mcp codebase.
What does addFilesRecursively() call?
addFilesRecursively() calls 4 function(s): debug, error, formatBytes, warn.
What calls addFilesRecursively()?
addFilesRecursively() is called by 1 function(s): zipRepository.

Analyze Your Own Codebase

Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.

Try Supermodel Free