process_and_upload_image
Optimize, resize, and convert local image files to WebP format, then upload them to Vercel Blob storage for efficient cloud integration.
Instructions
Process a local image file (optimize, resize, convert to WebP) and upload to Vercel Blob
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| height | No | Height to resize the image to (default: 300) | |
| imagePath | Yes | Path to the image file to process | |
| newName | Yes | New name for the processed image (without extension) | |
| width | No | Width to resize the image to (default: 550) |
Implementation Reference
- src/index.ts:325-353 (handler)Specific handler logic for 'process_and_upload_image' tool: validates inputs, reads local image file into buffer, and invokes the core processing function.
if (toolName === "process_and_upload_image") { // Process local image file const { imagePath, newName, width = 550, height = 300 } = args as { imagePath: string; newName: string; width?: number; height?: number; }; if (!imagePath || !newName) { throw new McpError( ErrorCode.InvalidParams, "imagePath and newName are required" ); } if (!fs.existsSync(imagePath)) { throw new McpError( ErrorCode.InvalidParams, `Image file not found: ${imagePath}` ); } // Read the image file const imageBuffer = await fs.readFile(imagePath); // Process and upload the image result = await processAndUploadImageBuffer(imageBuffer, newName, width, height); } - src/index.ts:194-298 (helper)Core helper function that takes an image buffer, resizes and optimizes PNG version, optimizes WebP version, saves to temp files, and uploads both to Vercel Blob (checking for existence first). Returns URLs.
async function processAndUploadImageBuffer( imageBuffer: Buffer, newName: string, width: number = 550, height: number = 300 ): Promise<any> { // Process results const results = { png: { localPath: "", blobUrl: "" }, webp: { localPath: "", blobUrl: "" } }; // Create temporary directory for processed images const tempDir = await createTempDir(); // Process PNG version const optimizedBuffer = await sharp(imageBuffer) .resize(width, height) .png({ quality: 80, effort: 6 }) .toBuffer(); const smallFileName = `${newName}_small.png`; const smallFilePath = path.join(tempDir, smallFileName); await fs.writeFile(smallFilePath, optimizedBuffer); results.png.localPath = smallFilePath; // Check if PNG already exists in Vercel Blob storage let pngUrl = ""; try { const existingUrl = await list({ prefix: smallFileName }); if (existingUrl.blobs.length > 0) { pngUrl = existingUrl.blobs[0].url; } else { // Upload if not found const { url } = await put(smallFileName, optimizedBuffer, { access: "public", contentType: "image/png" }); pngUrl = url; } } catch (error) { console.error(`Failed to check/upload PNG blob: ${error}`); throw new McpError( ErrorCode.InternalError, `Failed to upload PNG to Vercel Blob: ${error}` ); } results.png.blobUrl = pngUrl; // Process WebP version const optimizedBufferWebp = await sharp(imageBuffer) .webp({ quality: 80, effort: 6 }) .toBuffer(); const webpFileName = `${newName}.webp`; const webpFilePath = path.join(tempDir, webpFileName); await fs.writeFile(webpFilePath, optimizedBufferWebp); results.webp.localPath = webpFilePath; // Check if WebP already exists in Vercel Blob storage let webpUrl = ""; try { const existingUrlWebp = await list({ prefix: webpFileName }); if (existingUrlWebp.blobs.length > 0) { webpUrl = existingUrlWebp.blobs[0].url; } else { // Upload if not found const { url } = await put(webpFileName, optimizedBufferWebp, { access: "public", contentType: "image/webp" }); webpUrl = url; } } catch (error) { console.error(`Failed to check/upload WebP blob: ${error}`); throw new McpError( ErrorCode.InternalError, `Failed to upload WebP to Vercel Blob: ${error}` ); } results.webp.blobUrl = webpUrl; return { success: true, message: `Successfully processed and uploaded image: ${newName}`, results: { png: { fileName: smallFileName, localPath: results.png.localPath, blobUrl: results.png.blobUrl }, webp: { fileName: webpFileName, localPath: results.webp.localPath, blobUrl: results.webp.blobUrl } } }; } - src/index.ts:91-116 (schema)Input schema definition for the 'process_and_upload_image' tool, including properties and requirements.
{ name: "process_and_upload_image", description: "Process a local image file (optimize, resize, convert to WebP) and upload to Vercel Blob", inputSchema: { type: "object", properties: { imagePath: { type: "string", description: "Path to the image file to process" }, newName: { type: "string", description: "New name for the processed image (without extension)" }, width: { type: "number", description: "Width to resize the image to (default: 550)" }, height: { type: "number", description: "Height to resize the image to (default: 300)" } }, required: ["imagePath", "newName"] } }, - src/index.ts:88-145 (registration)Registration of the tool via the ListToolsRequestSchema handler, which returns the tool list including 'process_and_upload_image'.
server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: "process_and_upload_image", description: "Process a local image file (optimize, resize, convert to WebP) and upload to Vercel Blob", inputSchema: { type: "object", properties: { imagePath: { type: "string", description: "Path to the image file to process" }, newName: { type: "string", description: "New name for the processed image (without extension)" }, width: { type: "number", description: "Width to resize the image to (default: 550)" }, height: { type: "number", description: "Height to resize the image to (default: 300)" } }, required: ["imagePath", "newName"] } }, { name: "process_and_upload_image_from_url", description: "Process an image from a URL (optimize, resize, convert to WebP) and upload to Vercel Blob", inputSchema: { type: "object", properties: { imageUrl: { type: "string", description: "URL of the image to process" }, newName: { type: "string", description: "New name for the processed image (without extension)" }, width: { type: "number", description: "Width to resize the image to (default: 550)" }, height: { type: "number", description: "Height to resize the image to (default: 300)" } }, required: ["imageUrl", "newName"] } } ] }; });