Skip to main content
Glama
image-tools.js8.01 kB
const imageTools = [ { name: "upload_vehicle_images", description: `RECOMMENDED: Upload from file paths or URLs (2-5s per image) When to use: Pre-existing files on disk or web URLs Prerequisites: Vehicle must exist, valid file paths/URLs Batch support: 1-50 images per call (optimal: 10-20) Accepts: Local paths (/path/to/image.jpg), URLs (https://...) Auto-main image: First image automatically set as main if vehicle has no images Pro tip: For bulk uploads, prepare file list first`, inputSchema: { type: "object", properties: { vehicleId: { type: "number", description: "Vehicle ID to upload images to" }, images: { type: "array", items: { oneOf: [ { type: "string" }, { type: "object", properties: { type: { type: "string", enum: ["resource"] }, uri: { type: "string" }, mimeType: { type: "string" }, data: { type: "string" } }, required: ["type", "uri", "data"] } ] }, description: "Array of file paths, image URLs, or MCP resources (base64 data) to upload", minItems: 1, maxItems: 50 }, mainImageIndex: { type: "number", default: 0, description: "Index of the main image (0-based)" } }, required: ["vehicleId", "images"] } }, { name: "get_vehicle_images", description: `Get all images for a vehicle When to use: View current images before upload/delete operations Prerequisites: Vehicle must exist Returns: Array of image objects with IDs, URLs, and metadata Next steps: set_main_image, delete_vehicle_image, or upload more`, inputSchema: { type: "object", properties: { vehicleId: { type: "number", description: "Vehicle ID to get images from" } }, required: ["vehicleId"] } }, { name: "delete_vehicle_image", description: `Delete a specific image from a vehicle When to use: Remove unwanted or duplicate images Prerequisites: Image ID from get_vehicle_images Warning: Cannot delete the last image if vehicle is published Next steps: upload_vehicle_images or set_main_image`, inputSchema: { type: "object", properties: { vehicleId: { type: "number", description: "Vehicle ID" }, imageId: { type: "string", description: "Image ID to delete" } }, required: ["vehicleId", "imageId"] } }, { name: "set_vehicle_main_image", description: `Set a specific image as the main/primary image for a vehicle When to use: Change which image shows first in listings Prerequisites: Image ID from get_vehicle_images Effect: Main image appears in search results and thumbnails Pro tip: Choose the most attractive exterior front angle`, inputSchema: { type: "object", properties: { vehicleId: { type: "number", description: "Vehicle ID" }, imageId: { type: "string", description: "Image ID to set as main" } }, required: ["vehicleId", "imageId"] } } ]; const imageHandlers = { upload_vehicle_images: async (args, { imageAPI, logger }) => { const { validateVehicleId, validateRequired } = require('../utils/errors'); validateVehicleId(args.vehicleId); validateRequired(args.images, 'images'); const images = args.images || []; const filePaths = []; const urls = []; // Separate file paths from URLs images.forEach(image => { if (typeof image === 'string') { if (image.startsWith('http://') || image.startsWith('https://')) { urls.push(image); } else { filePaths.push(image); } } else { // Handle MCP resource objects filePaths.push(image); } }); let totalUploaded = 0; let allErrors = []; let message = ''; // Upload file paths if (filePaths.length > 0) { const fileResult = await imageAPI.uploadImages( args.vehicleId, filePaths, args.mainImageIndex || 0 ); totalUploaded += fileResult.uploadedCount; allErrors = allErrors.concat(fileResult.errors); message += `📁 Files: Uploaded ${fileResult.uploadedCount}/${filePaths.length}\n`; } // Upload URLs for (const url of urls) { const urlResult = await imageAPI.uploadImageFromUrl( args.vehicleId, url, urls.indexOf(url) === (args.mainImageIndex || 0) - filePaths.length ); if (urlResult.success) { totalUploaded++; message += `🌐 URL uploaded: ${url}\n`; } else { allErrors.push({ path: url, error: urlResult.error }); message += `❌ URL failed: ${url} - ${urlResult.error}\n`; } } message = `✅ Total uploaded: ${totalUploaded}/${images.length} images to vehicle ${args.vehicleId}\n\n` + message; if (allErrors.length > 0) { message += `\n❌ Errors (${allErrors.length}):\n`; allErrors.forEach(err => { message += `- ${err.path}: ${err.error}\n`; }); } // Check if vehicle needs a main image if (totalUploaded > 0) { const mainImageStatus = await imageAPI.checkMainImageStatus(args.vehicleId); if (!mainImageStatus.hasMainImage && mainImageStatus.firstImageId) { message += `\n💡 SUGGESTION: This vehicle has no main image set. Consider running:\n`; message += ` set_main_image(vehicleId=${args.vehicleId}, imageId="${mainImageStatus.firstImageId}")\n`; message += ` This will make the first image appear in listings and search results.`; } } return { content: [ { type: 'text', text: message, }, ], }; }, get_vehicle_images: async (args, { imageAPI }) => { const { validateVehicleId } = require('../utils/errors'); validateVehicleId(args.vehicleId); const result = await imageAPI.getVehicleImages(args.vehicleId); return { content: [ { type: 'text', text: JSON.stringify(result, null, 2), }, ], }; }, delete_vehicle_image: async (args, { imageAPI }) => { const { validateVehicleId, validateRequired } = require('../utils/errors'); validateVehicleId(args.vehicleId); validateRequired(args.imageId, 'imageId'); try { const result = await imageAPI.deleteImage(args.vehicleId, args.imageId); return { content: [ { type: 'text', text: `✅ Image ${args.imageId} deleted. Remaining images: ${result.remainingImages}`, }, ], }; } catch (error) { return { content: [ { type: 'text', text: `❌ Failed to delete image: ${error.message}`, }, ], isError: true, }; } }, set_vehicle_main_image: async (args, { imageAPI }) => { const { validateVehicleId, validateRequired } = require('../utils/errors'); validateVehicleId(args.vehicleId); validateRequired(args.imageId, 'imageId'); try { await imageAPI.setMainImage(args.vehicleId, args.imageId); return { content: [ { type: 'text', text: `✅ Image ${args.imageId} set as main image for vehicle ${args.vehicleId}`, }, ], }; } catch (error) { return { content: [ { type: 'text', text: `❌ Failed to set main image: ${error.message}`, }, ], isError: true, }; } } }; module.exports = { imageTools, imageHandlers };

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/loukach/stockspark-mcp-poc'

If you have feedback or need assistance with the MCP directory API, please join our Discord server