Skip to main content
Glama

update-product

Modify product details in Shopify stores by updating titles, descriptions, SEO metadata, pricing, inventory, and variants through the Shopify MCP Server.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
productIdYesThe GID of the product to update (e.g., "gid://shopify/Product/1234567890")
titleNoThe new title for the product
descriptionHtmlNoThe new HTML description for the product
seoNoSEO information for the product
statusNoProduct status (ACTIVE, ARCHIVED, or DRAFT)
vendorNoThe vendor or manufacturer of the product
productTypeNoThe type or category of the product
tagsNoArray of tags to categorize the product
variantsNoProduct variants to update

Implementation Reference

  • The `execute` method of the `updateProduct` tool object, which contains the core logic for updating Shopify product details and variants using GraphQL mutations.
    execute: async (input: UpdateProductInput) => { if (!updateProduct.client) { throw new Error('GraphQL client not initialized. Call initialize() first.'); } try { const { productId, variants, ...productInput } = input; let response: ProductUpdateResponse; // If we're only updating variants, fetch the initial product data if (Object.keys(productInput).length === 0) { response = await updateProduct.client.request<ProductUpdateResponse>(updateProductMutation, { input: { id: productId } }); } else { // Update product details response = await updateProduct.client.request<ProductUpdateResponse>(updateProductMutation, { input: { id: productId, ...productInput } }); if (response.productUpdate.userErrors.length > 0) { throw new Error( `Failed to update product: ${response.productUpdate.userErrors .map((error) => error.message) .join(", ")}` ); } } // Update variants if provided if (variants && variants.length > 0) { const variantResponse = await updateProduct.client.request<VariantsBulkUpdateResponse>(updateVariantsMutation, { productId, variants: variants.map(variant => ({ id: variant.id, price: variant.price, compareAtPrice: variant.compareAtPrice, sku: variant.sku, barcode: variant.barcode, inventoryPolicy: variant.inventoryPolicy })) }); if (variantResponse.productVariantsBulkUpdate.userErrors.length > 0) { throw new Error( `Failed to update variants: ${variantResponse.productVariantsBulkUpdate.userErrors .map((error) => error.message) .join(", ")}` ); } // Fetch the latest product data after variant update response = await updateProduct.client.request<ProductUpdateResponse>(updateProductMutation, { input: { id: productId } }); } // Format variants for response const formattedVariants = response.productUpdate.product.variants.edges.map((edge) => ({ id: edge.node.id, title: edge.node.title, price: edge.node.price, compareAtPrice: edge.node.compareAtPrice, sku: edge.node.sku, barcode: edge.node.barcode, inventoryQuantity: edge.node.inventoryQuantity, inventoryPolicy: edge.node.inventoryPolicy })); return { product: { id: response.productUpdate.product.id, title: response.productUpdate.product.title, descriptionHtml: response.productUpdate.product.descriptionHtml, handle: response.productUpdate.product.handle, status: response.productUpdate.product.status, vendor: response.productUpdate.product.vendor, productType: response.productUpdate.product.productType, tags: response.productUpdate.product.tags, seo: response.productUpdate.product.seo, variants: formattedVariants, updatedAt: response.productUpdate.product.updatedAt } }; } catch (error: unknown) { if (error instanceof Error) { throw new Error(`Failed to update product: ${error.message}`); } throw new Error('Failed to update product: Unknown error'); } },
  • Zod input schema defining all parameters for the update-product tool, used in the tool definition.
    const UpdateProductInputSchema = z.object({ productId: z.string().min(1).describe("The GID of the product to update (e.g., \"gid://shopify/Product/1234567890\")"), title: z.string().optional().describe("The new title for the product"), descriptionHtml: z.string().optional().describe("The new HTML description for the product"), seo: z.object({ title: z.string().optional().describe("SEO-optimized title for the product"), description: z.string().optional().describe("SEO meta description for the product") }).optional().describe("SEO information for the product"), status: z.enum(["ACTIVE", "ARCHIVED", "DRAFT"]).optional().describe("Product status (ACTIVE, ARCHIVED, or DRAFT)"), vendor: z.string().optional().describe("The vendor or manufacturer of the product"), productType: z.string().optional().describe("The type or category of the product"), tags: z.array(z.string()).optional().describe("Array of tags to categorize the product"), variants: z.array(z.object({ id: z.string().optional().describe("The GID of the variant to update"), price: z.string().optional().describe("The price of the variant"), compareAtPrice: z.string().optional().describe("Compare at price for showing a markdown"), sku: z.string().optional().describe("Stock keeping unit (SKU)"), barcode: z.string().optional().describe("Barcode (ISBN, UPC, GTIN, etc.)"), inventoryQuantity: z.number().optional().describe("Available inventory quantity"), inventoryPolicy: z.enum(["DENY", "CONTINUE"]).optional().describe("What happens when a variant is out of stock"), fulfillmentService: z.string().optional().describe("Service responsible for fulfilling the variant"), weight: z.number().optional().describe("Weight of the variant"), weightUnit: z.enum(["KILOGRAMS", "GRAMS", "POUNDS", "OUNCES"]).optional().describe("Unit of weight measurement") })).optional().describe("Product variants to update") });
  • src/index.ts:309-342 (registration)
    MCP server registration of the 'update-product' tool, including duplicated inline schema and wrapper that calls the tool's execute method.
    server.tool( "update-product", { productId: z.string().min(1).describe("The GID of the product to update (e.g., \"gid://shopify/Product/1234567890\")"), title: z.string().optional().describe("The new title for the product"), descriptionHtml: z.string().optional().describe("The new HTML description for the product"), seo: z.object({ title: z.string().optional().describe("SEO-optimized title for the product"), description: z.string().optional().describe("SEO meta description for the product") }).optional().describe("SEO information for the product"), status: z.enum(["ACTIVE", "ARCHIVED", "DRAFT"]).optional().describe("Product status (ACTIVE, ARCHIVED, or DRAFT)"), vendor: z.string().optional().describe("The vendor or manufacturer of the product"), productType: z.string().optional().describe("The type or category of the product"), tags: z.array(z.string()).optional().describe("Array of tags to categorize the product"), variants: z.array(z.object({ id: z.string().optional().describe("The GID of the variant to update"), price: z.string().optional().describe("The price of the variant"), compareAtPrice: z.string().optional().describe("Compare at price for showing a markdown"), sku: z.string().optional().describe("Stock keeping unit (SKU)"), barcode: z.string().optional().describe("Barcode (ISBN, UPC, GTIN, etc.)"), inventoryQuantity: z.number().optional().describe("Available inventory quantity"), inventoryPolicy: z.enum(["DENY", "CONTINUE"]).optional().describe("What happens when a variant is out of stock"), fulfillmentService: z.string().optional().describe("Service responsible for fulfilling the variant"), weight: z.number().optional().describe("Weight of the variant"), weightUnit: z.enum(["KILOGRAMS", "GRAMS", "POUNDS", "OUNCES"]).optional().describe("Unit of weight measurement") })).optional().describe("Product variants to update") }, async (args) => { const result = await updateProduct.execute(args); return { content: [{ type: "text", text: JSON.stringify(result) }] }; } );
  • GraphQL mutation for updating product details, used in the handler.
    const updateProductMutation = gql` mutation productUpdate($input: ProductInput!) { productUpdate(input: $input) { product { id title descriptionHtml handle status vendor productType tags seo { title description } variants(first: 50) { edges { node { id title price compareAtPrice sku barcode inventoryQuantity inventoryPolicy } } } updatedAt } userErrors { field message } } } `;
  • Initialization of the updateProduct tool with the Shopify GraphQL client.
    updateProduct.initialize(shopifyClient);

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/luckyfarnon/Shopify-MCP'

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