convert_to_webp
Convert multiple PNG, JPG, and JPEG images to WebP format in batches with customizable quality, lossless encoding, and directory scanning.
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 |
|---|---|---|---|
| src | No | Source directory to scan for images (default: current directory) | . |
| quality | No | WebP quality (0-100, default: 75) | |
| lossless | No | Use lossless encoding (recommended for PNG images) | |
| overwrite | No | Replace original files with WebP versions | |
| threads | No | Number of concurrent conversions (default: 2) | |
| preserveMeta | No | Preserve EXIF and ICC metadata | |
| flat | No | Output all WebP files to specified directory (optional) |
Implementation Reference
- src/lib/convert.ts:139-179 (handler)Core batch conversion implementation: finds images recursively, converts them to WebP concurrently using cwebp or sharp fallback, computes statistics including space savings.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 for 'convert_to_webp': parameter validation, defaults, calls WebPConverter.batchConvert, formats success/error 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:39-81 (schema)JSON input schema for the convert_to_webp tool, defining parameters with descriptions, defaults, and constraints.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/server.ts:33-84 (registration)Tool registration via ListToolsRequestSchema handler, listing 'convert_to_webp' with description and schema.this.server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { 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-26 (schema)TypeScript interfaces defining ConvertOptions input and ConvertResult output for the converter class.export interface ConvertOptions { src: string; quality: number; lossless: boolean; overwrite: boolean; threads: number; preserveMeta: boolean; flat?: string; } export interface ConvertResult { converted: string[]; skipped: string[]; errors: Array<{ file: string; error: string }>; originalKB: number; webpKB: number; savings: number; }