create_variants
Create multiple product variants by specifying full option combinations, pricing, and initial stock per location. Remove the default placeholder variant when adding the first real variant.
Instructions
Create one or more variants on an existing product. Each variant's optionValues must cover EVERY option declared on the product (Size + Color + Material if there are 3 options) — partial coverage is rejected. New products from create_product start with a single hidden 'Default Title' variant; when adding the first real variants, pass strategy='REMOVE_STANDALONE_VARIANT' so Shopify replaces the placeholder rather than leaving it. inventoryQuantities seeds initial stock per location at create time; for ongoing changes use set_inventory_quantity instead.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| productId | Yes | Product GID. | |
| variants | Yes | ||
| strategy | No | DEFAULT: add to existing variants. REMOVE_STANDALONE_VARIANT: replace the auto-created 'Default Title' variant (use on first real variant create). |
Implementation Reference
- src/tools/variants.ts:319-351 (handler)The tool handler for 'create_variants'. Receives productId, variants (array of variantCreateSchema), and optional strategy. Calls the VARIANTS_BULK_CREATE_MUTATION GraphQL mutation and returns formatted results.
server.tool( "create_variants", "Create one or more variants on an existing product. Each variant's optionValues must cover EVERY option declared on the product (Size + Color + Material if there are 3 options) — partial coverage is rejected. New products from create_product start with a single hidden 'Default Title' variant; when adding the first real variants, pass strategy='REMOVE_STANDALONE_VARIANT' so Shopify replaces the placeholder rather than leaving it. inventoryQuantities seeds initial stock per location at create time; for ongoing changes use set_inventory_quantity instead.", createVariantsSchema, async (args) => { const data = await client.graphql<{ productVariantsBulkCreate: { productVariants: VariantNode[]; userErrors: ShopifyUserError[]; }; }>(VARIANTS_BULK_CREATE_MUTATION, { productId: args.productId, variants: args.variants, strategy: args.strategy, }); throwIfUserErrors( data.productVariantsBulkCreate.userErrors, "productVariantsBulkCreate", ); const created = data.productVariantsBulkCreate.productVariants; return { content: [ { type: "text" as const, text: [ `Created ${created.length} variant(s):`, ...created.map((v) => formatVariant(v)), ].join("\n"), }, ], }; }, ); - src/tools/variants.ts:198-207 (schema)Input schema (createVariantsSchema) for the tool. productId (string), variants (array of variantCreateSchema with 1-100 items), strategy (optional enum: DEFAULT|REMOVE_STANDALONE_VARIANT).
const createVariantsSchema = { productId: z.string().describe("Product GID."), variants: z.array(variantCreateSchema).min(1).max(100), strategy: z .enum(["DEFAULT", "REMOVE_STANDALONE_VARIANT"]) .optional() .describe( "DEFAULT: add to existing variants. REMOVE_STANDALONE_VARIANT: replace the auto-created 'Default Title' variant (use on first real variant create).", ), }; - src/tools/variants.ts:157-180 (helper)The variantCreateSchema defining the shape of each variant in the variants array: optionValues, price, compareAtPrice, sku, barcode, taxable, inventoryPolicy, inventoryQuantities.
const variantCreateSchema = z.object({ optionValues: z .array(optionValueInputSchema) .describe( "One entry per product option. Shape must match the product's options (order-insensitive, matched by optionName).", ), price: z.string().describe("Variant price as decimal string, e.g. '19.99'."), compareAtPrice: z.string().optional(), sku: z.string().optional(), barcode: z.string().optional(), taxable: z.boolean().optional(), inventoryPolicy: z .enum(["DENY", "CONTINUE"]) .optional() .describe( "Oversell policy: DENY blocks sales at 0 stock, CONTINUE allows backorder.", ), inventoryQuantities: z .array(inventoryQuantityInputSchema) .optional() .describe( "Initial stock per location. Only accepted on create — use set_inventory_quantity for subsequent updates.", ), }); - src/tools/variants.ts:61-82 (helper)The GraphQL mutation (VARIANTS_BULK_CREATE_MUTATION) used by the create_variants handler to perform the bulk create operation.
const VARIANTS_BULK_CREATE_MUTATION = /* GraphQL */ ` mutation VariantsBulkCreate( $productId: ID! $variants: [ProductVariantsBulkInput!]! $strategy: ProductVariantsBulkCreateStrategy ) { productVariantsBulkCreate( productId: $productId variants: $variants strategy: $strategy ) { productVariants { id title price sku selectedOptions { name value } } userErrors { field message } } } `; - src/server.ts:56-64 (registration)Registration of all variant tools (including create_variants) in the MCP server via registerVariantTools(s, shopify).
const s = new McpServer({ name: "shopify-mcp", version: "0.1.0" }); registerProductTools(s, shopify); registerOrderTools(s, shopify); registerInventoryTools(s, shopify); registerCustomerTools(s, shopify); registerMetafieldTools(s, shopify); registerDraftOrderTools(s, shopify); registerCollectionTools(s, shopify); registerVariantTools(s, shopify);