MCPcopy
hub / github.com/codeaashu/claude-code / extractMcpbContents

Function extractMcpbContents

src/utils/plugins/mcpbHandler.ts:550–617  ·  view source on GitHub ↗

* Extract MCPB file and write contents to extraction directory. * * @param modes - name→mode map from `parseZipModes`. MCPB bundles can ship * native MCP server binaries, so preserving the exec bit matters here.

(
  unzipped: Record<string, Uint8Array>,
  extractPath: string,
  modes: Record<string, number>,
  onProgress?: ProgressCallback,
)

Source from the content-addressed store, hash-verified

548 * native MCP server binaries, so preserving the exec bit matters here.
549 */
550async function extractMcpbContents(
551 unzipped: Record<string, Uint8Array>,
552 extractPath: string,
553 modes: Record<string, number>,
554 onProgress?: ProgressCallback,
555): Promise<void> {
556 if (onProgress) {
557 onProgress('Extracting files...')
558 }
559
560 // Create extraction directory
561 await getFsImplementation().mkdir(extractPath)
562
563 // Write all files. Filter directory entries from the count so progress
564 // messages use the same denominator as filesWritten (which skips them).
565 let filesWritten = 0
566 const entries = Object.entries(unzipped).filter(([k]) => !k.endsWith('/'))
567 const totalFiles = entries.length
568
569 for (const [filePath, fileData] of entries) {
570 // Directory entries (common in zip -r, Python zipfile, Java ZipOutputStream)
571 // are filtered above — writeFile would create `bin/` as an empty regular
572 // file, then mkdir for `bin/server` would fail with ENOTDIR. The
573 // mkdir(dirname(fullPath)) below creates parent dirs implicitly.
574
575 const fullPath = join(extractPath, filePath)
576 const dir = dirname(fullPath)
577
578 // Ensure directory exists (recursive handles already-existing)
579 if (dir !== extractPath) {
580 await getFsImplementation().mkdir(dir)
581 }
582
583 // Determine if text or binary
584 const isTextFile =
585 filePath.endsWith('.json') ||
586 filePath.endsWith('.js') ||
587 filePath.endsWith('.ts') ||
588 filePath.endsWith('.txt') ||
589 filePath.endsWith('.md') ||
590 filePath.endsWith('.yml') ||
591 filePath.endsWith('.yaml')
592
593 if (isTextFile) {
594 const content = new TextDecoder().decode(fileData)
595 await writeFile(fullPath, content, 'utf-8')
596 } else {
597 await writeFile(fullPath, Buffer.from(fileData))
598 }
599
600 const mode = modes[filePath]
601 if (mode && mode & 0o111) {
602 // Swallow EPERM/ENOTSUP (NFS root_squash, some FUSE mounts) — losing +x
603 // is the pre-PR behavior and better than aborting mid-extraction.
604 await chmod(fullPath, mode & 0o777).catch(() => {})
605 }
606
607 filesWritten++

Callers 1

loadMcpbFileFunction · 0.85

Calls 5

getFsImplementationFunction · 0.85
logForDebuggingFunction · 0.85
entriesMethod · 0.80
decodeMethod · 0.80
onProgressFunction · 0.50

Tested by

no test coverage detected