decompress
Extract contents from a local ZIP file to a specified directory, with options to include password protection, overwrite files, and create directories.
Instructions
Decompress local ZIP file to specified directory
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| input | Yes | ||
| options | No | ||
| output | Yes |
Input Schema (JSON Schema)
{
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false,
"properties": {
"input": {
"type": "string"
},
"options": {
"additionalProperties": false,
"properties": {
"createDirectories": {
"type": "boolean"
},
"overwrite": {
"type": "boolean"
},
"password": {
"type": "string"
}
},
"type": "object"
},
"output": {
"type": "string"
}
},
"required": [
"input",
"output"
],
"type": "object"
}
Implementation Reference
- src/index.ts:184-255 (handler)Handler function that executes the decompress tool logic: reads ZIP file, decompresses using helper, writes files to output directory with overwrite and directory creation options.execute: async (args) => { try { const inputPath = args.input; const outputPath = args.output; const options: DecompressionOptions & { overwrite?: boolean; createDirectories?: boolean; } = args.options || {}; const overwrite = options.overwrite ?? false; const createDirectories = options.createDirectories ?? true; // Check if input file exists if (!(await exists(inputPath))) { throw new Error(`Input file not found: ${inputPath}`); } // Check output directory if (await exists(outputPath)) { const stats = await fs.stat(outputPath); if (!stats.isDirectory()) { throw new Error(`Output path is not a directory: ${outputPath}`); } } else { if (createDirectories) { await fs.mkdir(outputPath, { recursive: true }); } else { throw new Error(`Output directory does not exist: ${outputPath}`); } } // Read ZIP file const zipData = await fs.readFile(inputPath); // Decompress file const result = await decompressData(new Uint8Array(zipData), options); // Extract files to output directory const extractedFiles: string[] = []; for (const file of result) { const outputFilePath = path.join(outputPath, file.name); const outputFileDir = path.dirname(outputFilePath); // Create directory (if needed) if (!(await exists(outputFileDir))) { await fs.mkdir(outputFileDir, { recursive: true }); } // Check if file already exists if ((await exists(outputFilePath)) && !overwrite) { console.warn(`Skipping existing file: ${outputFilePath}`); continue; } // Write file await fs.writeFile(outputFilePath, file.data); extractedFiles.push(file.name); } return { content: [ { type: "text", text: `Decompression completed. Extracted ${extractedFiles.length} files to ${outputPath}`, }, ], }; } catch (error) { return { content: [{ type: "text", text: `Decompression failed: ${formatError(error)}` }], }; } },
- src/index.ts:173-183 (schema)Zod schema defining input parameters for the decompress tool: input ZIP path, output directory, and optional options (password, overwrite, createDirectories).parameters: z.object({ input: z.string(), // ZIP file path output: z.string(), // Output directory path options: z .object({ password: z.string().optional(), overwrite: z.boolean().optional(), createDirectories: z.boolean().optional(), }) .optional(), }),
- src/index.ts:169-256 (registration)Registration of the 'decompress' tool with FastMCP server.addTool, specifying name, description, input schema, and handler function.// Decompression tool - Decompress local ZIP file server.addTool({ name: "decompress", description: "Decompress local ZIP file to specified directory", parameters: z.object({ input: z.string(), // ZIP file path output: z.string(), // Output directory path options: z .object({ password: z.string().optional(), overwrite: z.boolean().optional(), createDirectories: z.boolean().optional(), }) .optional(), }), execute: async (args) => { try { const inputPath = args.input; const outputPath = args.output; const options: DecompressionOptions & { overwrite?: boolean; createDirectories?: boolean; } = args.options || {}; const overwrite = options.overwrite ?? false; const createDirectories = options.createDirectories ?? true; // Check if input file exists if (!(await exists(inputPath))) { throw new Error(`Input file not found: ${inputPath}`); } // Check output directory if (await exists(outputPath)) { const stats = await fs.stat(outputPath); if (!stats.isDirectory()) { throw new Error(`Output path is not a directory: ${outputPath}`); } } else { if (createDirectories) { await fs.mkdir(outputPath, { recursive: true }); } else { throw new Error(`Output directory does not exist: ${outputPath}`); } } // Read ZIP file const zipData = await fs.readFile(inputPath); // Decompress file const result = await decompressData(new Uint8Array(zipData), options); // Extract files to output directory const extractedFiles: string[] = []; for (const file of result) { const outputFilePath = path.join(outputPath, file.name); const outputFileDir = path.dirname(outputFilePath); // Create directory (if needed) if (!(await exists(outputFileDir))) { await fs.mkdir(outputFileDir, { recursive: true }); } // Check if file already exists if ((await exists(outputFilePath)) && !overwrite) { console.warn(`Skipping existing file: ${outputFilePath}`); continue; } // Write file await fs.writeFile(outputFilePath, file.data); extractedFiles.push(file.name); } return { content: [ { type: "text", text: `Decompression completed. Extracted ${extractedFiles.length} files to ${outputPath}`, }, ], }; } catch (error) { return { content: [{ type: "text", text: `Decompression failed: ${formatError(error)}` }], }; } }, });
- src/utils/compression.ts:87-117 (helper)Core helper function decompressData that uses @zip.js/zip.js to read ZIP entries and extract file data as Uint8Array./** * Decompress data */ export async function decompressData( data: Uint8Array | Blob, options: DecompressionOptions = {} ): Promise<{ name: string, data: Uint8Array }[]> { try { const reader = data instanceof Blob ? new zip.BlobReader(data) : new zip.Uint8ArrayReader(data); const zipReader = new zip.ZipReader(reader, { password: options.password }); const entries = await zipReader.getEntries(); const results: { name: string, data: Uint8Array }[] = []; for (const entry of entries) { if (!entry.directory && typeof entry.getData === 'function') { const writer = new zip.Uint8ArrayWriter(); const data = await entry.getData(writer); results.push({ name: entry.filename, data }); } } await zipReader.close(); return results; } catch (error: any) { throw new Error(`Decompression failed: ${error.message}`); } }
- src/utils/compression.ts:9-11 (schema)TypeScript interface defining options for decompression, primarily password.export interface DecompressionOptions { password?: string; // Decompression password }