Skip to main content
Glama

update_product

Modifies product details on Printify by updating the title, description, variants, and print areas using the provided product ID. Enables precise product management and customization within the Print-on-Demand platform.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
descriptionNoProduct description
printAreasNoPrint areas for the product
productIdYesProduct ID
titleNoProduct title
variantsNoProduct variants

Implementation Reference

  • src/index.ts:303-349 (registration)
    MCP tool registration for 'update_product', including inline Zod input schema validation and handler function that delegates to the printify-products service.
    server.tool( "update_product", { productId: z.string().describe("Product ID"), title: z.string().optional().describe("Product title"), description: z.string().optional().describe("Product description"), variants: z.array(z.object({ variantId: z.number().describe("Variant ID"), price: z.number().describe("Price in cents (e.g., 1999 for $19.99)"), isEnabled: z.boolean().optional().describe("Whether the variant is enabled") })).optional().describe("Product variants"), printAreas: z.record(z.string(), z.object({ position: z.string().describe("Print position (e.g., 'front', 'back')"), imageId: z.string().describe("Image ID from Printify uploads") })).optional().describe("Print areas for the product") }, async ({ productId, title, description, variants, printAreas }): Promise<{ content: any[], isError?: boolean }> => { // Import the printify products service const { updateProduct } = await import('./services/printify-products.js'); // Check if client is initialized if (!printifyClient) { return { content: [{ type: "text", text: "Printify API client is not initialized. The PRINTIFY_API_KEY environment variable may not be set." }], isError: true }; } // Call the service const result = await updateProduct(printifyClient, productId, { title, description, variants, printAreas }); // Return the result if (result.success) { return result.response as { content: any[], isError?: boolean }; } else { return result.errorResponse as { content: any[], isError: boolean }; } } );
  • MCP handler function for update_product tool. Validates client initialization and calls the service layer updateProduct function.
    async ({ productId, title, description, variants, printAreas }): Promise<{ content: any[], isError?: boolean }> => { // Import the printify products service const { updateProduct } = await import('./services/printify-products.js'); // Check if client is initialized if (!printifyClient) { return { content: [{ type: "text", text: "Printify API client is not initialized. The PRINTIFY_API_KEY environment variable may not be set." }], isError: true }; } // Call the service const result = await updateProduct(printifyClient, productId, { title, description, variants, printAreas }); // Return the result if (result.success) { return result.response as { content: any[], isError?: boolean }; } else { return result.errorResponse as { content: any[], isError: boolean }; } }
  • Zod schema for input parameters of the update_product tool: required productId, optional title, description, variants array, and printAreas record.
    productId: z.string().describe("Product ID"), title: z.string().optional().describe("Product title"), description: z.string().optional().describe("Product description"), variants: z.array(z.object({ variantId: z.number().describe("Variant ID"), price: z.number().describe("Price in cents (e.g., 1999 for $19.99)"), isEnabled: z.boolean().optional().describe("Whether the variant is enabled") })).optional().describe("Product variants"), printAreas: z.record(z.string(), z.object({ position: z.string().describe("Print position (e.g., 'front', 'back')"), imageId: z.string().describe("Image ID from Printify uploads") })).optional().describe("Print areas for the product") },
  • Service helper function updateProduct that performs shop validation, calls PrintifyAPI.updateProduct, and returns formatted success/error responses.
    export async function updateProduct( printifyClient: PrintifyAPI, productId: string, updateData: { title?: string; description?: string; variants?: Array<{ variantId: number; price: number; isEnabled?: boolean; }>; printAreas?: Record<string, { position: string; imageId: string; }>; } ) { try { // Validate shop is selected const currentShop = printifyClient.getCurrentShop(); if (!currentShop) { throw new Error('No shop is currently selected. Use the list-shops and switch-shop tools to select a shop.'); } // Update product const product = await printifyClient.updateProduct(productId, updateData); return { success: true, product, response: formatSuccessResponse( 'Product Updated Successfully', { ProductId: productId, Title: updateData.title || 'Not updated', Shop: currentShop }, `You may need to publish the changes using the publish-product tool.` ) }; } catch (error: any) { console.error('Error updating product:', error); return { success: false, error, errorResponse: formatErrorResponse( error, 'Update Product', { ProductId: productId, UpdateData: updateData, Shop: printifyClient.getCurrentShop() }, [ 'Check that the product ID is valid', 'Check that the variant IDs are valid', 'Ensure your Printify account is properly connected', 'Make sure you have selected a shop' ] ) }; } }
  • Low-level PrintifyAPI class method that formats the update data (handling print_areas conversion to Printify SDK format) and calls client.products.updateOne.
    async updateProduct(productId: string, productData: any) { if (!this.shopId) { throw new Error('Shop ID is not set. Call setShopId() first.'); } try { // Format the product data if it contains print_areas if (productData.print_areas || productData.printAreas) { const formattedData = { ...productData }; const printAreasData = formattedData.print_areas || formattedData.printAreas; // If print_areas is provided, format it correctly if (printAreasData) { // Get the current product to get variant IDs if not provided let variantIds: number[] = []; if (formattedData.variants && Array.isArray(formattedData.variants)) { // Use the variants from the update data variantIds = formattedData.variants.map((v: any) => parseInt(v.id || v.variantId)); } else { // Get the current product to get its variant IDs try { const currentProduct = await this.client.products.getOne(productId); variantIds = currentProduct.variants .filter((v: any) => v.is_enabled) .map((v: any) => v.id); } catch (error) { console.error(`Error fetching current product ${productId}:`, error); // Continue with empty variant IDs } } // Create a print area entry with all variants const printAreaEntry: any = { variant_ids: variantIds, placeholders: [] }; // Add placeholders for each position (front, back, etc.) for (const key in printAreasData) { const area = printAreasData[key]; printAreaEntry.placeholders.push({ position: area.position, images: [ { id: area.image_id || area.imageId, x: 0.5, y: 0.5, scale: 1, angle: 0 } ] }); } // Replace the print_areas with the correctly formatted version formattedData.print_areas = [printAreaEntry]; // Remove the printAreas property if it exists if (formattedData.printAreas) { delete formattedData.printAreas; } } console.log(`Updating product ${productId} with formatted data:`, JSON.stringify(formattedData, null, 2)); return await this.client.products.updateOne(productId, formattedData); } else { // If no print_areas, just pass the data as is return await this.client.products.updateOne(productId, productData); } } catch (error) { console.error(`Error updating product ${productId}:`, error); throw this.enhanceError(error, productData); } }

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/TSavo/printify-mcp'

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