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
  5c9096db_a74b_41f3_ba88_9738d6d799b5["addFilesRecursively()"]
  1fd46af5_c3e2_8998_1eb2_098430ff3629["zipRepository()"]
  1fd46af5_c3e2_8998_1eb2_098430ff3629 -->|calls| 5c9096db_a74b_41f3_ba88_9738d6d799b5
  e5352615_c5fb_64a2_cc5c_a248578cbc8a["warn()"]
  5c9096db_a74b_41f3_ba88_9738d6d799b5 -->|calls| e5352615_c5fb_64a2_cc5c_a248578cbc8a
  9a818de6_4969_c29c_0dd7_dab4f6d4fbdb["error()"]
  5c9096db_a74b_41f3_ba88_9738d6d799b5 -->|calls| 9a818de6_4969_c29c_0dd7_dab4f6d4fbdb
  69fc7a46_28f6_6b72_2725_66c381e53322["debug()"]
  5c9096db_a74b_41f3_ba88_9738d6d799b5 -->|calls| 69fc7a46_28f6_6b72_2725_66c381e53322
  acd13495_08c9_df51_1b17_173570f3e5ea["formatBytes()"]
  5c9096db_a74b_41f3_ba88_9738d6d799b5 -->|calls| acd13495_08c9_df51_1b17_173570f3e5ea
  style 5c9096db_a74b_41f3_ba88_9738d6d799b5 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,
    });
  }
}

Domain

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