convert_to_webp
Batch convert PNG, JPG, and JPEG images to WebP format with customizable quality, lossless encoding, and multi-threading. Recursively scans directories, preserves metadata, and generates detailed conversion reports.
Instructions
Batch convert images (PNG, JPG, JPEG) to WebP format with customizable options. Recursively scans directories and provides detailed conversion reports.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| flat | No | Output all WebP files to specified directory (optional) | |
| lossless | No | Use lossless encoding (recommended for PNG images) | |
| overwrite | No | Replace original files with WebP versions | |
| preserveMeta | No | Preserve EXIF and ICC metadata | |
| quality | No | WebP quality (0-100, default: 75) | |
| src | No | Source directory to scan for images (default: current directory) | . |
| threads | No | Number of concurrent conversions (default: 4) |
Implementation Reference
- src/lib/convert.ts:139-179 (handler)The core batchConvert method that implements the WebP conversion logic: scans for images, processes them concurrently using cwebp or sharp, tracks stats and errors.async batchConvert(options: ConvertOptions): Promise<ConvertResult> { console.log(chalk.blue(`๐ Scanning ${options.src} for images...`)); const images = await this.findImages(options.src); const limit = pLimit(options.threads); console.log(chalk.blue(`๐ Found ${images.length} images`)); console.log(chalk.blue(`๐ Converting with ${options.threads} threads...`)); const result: ConvertResult = { converted: [], skipped: [], errors: [], originalKB: 0, webpKB: 0, savings: 0 }; const tasks = images.map(imagePath => limit(async () => { const convertResult = await this.convertSingle(imagePath, options); if (convertResult.success) { result.converted.push(imagePath); result.originalKB += convertResult.originalSize / 1024; result.webpKB += convertResult.webpSize / 1024; console.log(chalk.green(`โ ${basename(imagePath)}`)); } else { result.errors.push({ file: imagePath, error: convertResult.error || 'Unknown error' }); console.log(chalk.red(`โ ${basename(imagePath)}: ${convertResult.error}`)); } }) ); await Promise.all(tasks); result.savings = result.originalKB > 0 ? Math.round(((result.originalKB - result.webpKB) / result.originalKB) * 100) : 0; return result; }
- src/server.ts:88-146 (handler)MCP CallToolRequestSchema handler that dispatches to convert_to_webp, validates parameters, calls batchConvert, and formats the response.this.server.setRequestHandler(CallToolRequestSchema, async (request) => { if (request.params.name !== 'convert_to_webp') { throw new Error(`Unknown tool: ${request.params.name}`); } const args = request.params.arguments as any; try { // Validate and set defaults const options = { src: args.src || '.', quality: args.quality || 75, lossless: args.lossless || false, overwrite: args.overwrite || false, threads: args.threads || cpus().length, preserveMeta: args.preserveMeta || false, flat: args.flat }; // Validate quality range if (options.quality < 0 || options.quality > 100) { throw new Error('Quality must be between 0-100'); } // Validate threads if (options.threads < 1) { throw new Error('Threads must be a positive number'); } const result = await this.converter.batchConvert(options); return { content: [ { type: 'text', text: `WebP Batch Conversion Complete!\n\n` + `๐ Results:\n` + `โ Converted: ${result.converted.length} files\n` + `โญ๏ธ Skipped: ${result.skipped.length} files\n` + `โ Errors: ${result.errors.length} files\n` + `๐พ Original size: ${Math.round(result.originalKB)} KB\n` + `๐๏ธ WebP size: ${Math.round(result.webpKB)} KB\n` + `๐ฐ Space saved: ${result.savings}%\n\n` + `๐ Detailed Report:\n${JSON.stringify(result, null, 2)}` } ] }; } catch (error) { return { content: [ { type: 'text', text: `โ Conversion failed: ${error instanceof Error ? error.message : String(error)}` } ], isError: true }; } });
- src/server.ts:36-82 (registration)Tool registration in ListToolsRequestSchema, including name, description, and input schema.{ name: 'convert_to_webp', description: 'Batch convert images (PNG, JPG, JPEG) to WebP format with customizable options. Recursively scans directories and provides detailed conversion reports.', inputSchema: { type: 'object', properties: { src: { type: 'string', description: 'Source directory to scan for images (default: current directory)', default: '.' }, quality: { type: 'number', description: 'WebP quality (0-100, default: 75)', minimum: 0, maximum: 100, default: 75 }, lossless: { type: 'boolean', description: 'Use lossless encoding (recommended for PNG images)', default: false }, overwrite: { type: 'boolean', description: 'Replace original files with WebP versions', default: false }, threads: { type: 'number', description: `Number of concurrent conversions (default: ${cpus().length})`, minimum: 1, default: cpus().length }, preserveMeta: { type: 'boolean', description: 'Preserve EXIF and ICC metadata', default: false }, flat: { type: 'string', description: 'Output all WebP files to specified directory (optional)' } }, required: [] } }
- src/lib/convert.ts:9-16 (schema)TypeScript interface defining the input options for the conversion, matching the tool schema.export interface ConvertOptions { src: string; quality: number; lossless: boolean; overwrite: boolean; threads: number; preserveMeta: boolean; flat?: string;
- src/lib/convert.ts:19-26 (schema)TypeScript interface for the conversion result structure used in the response.export interface ConvertResult { converted: string[]; skipped: string[]; errors: Array<{ file: string; error: string }>; originalKB: number; webpKB: number; savings: number; }