list_variants
List all variants of a product to inspect its full SKU matrix, including option definitions, prices, SKUs, barcodes, inventory, and taxable status. Use to review variant details before creating, updating, or deleting variants.
Instructions
List all variants of a single product, plus the product's option definitions (Size, Color, etc.) and possible values. For each variant returns: title, GID, price, compareAtPrice, SKU, barcode, current inventory quantity, taxable flag, inventory policy, and the option-value combination that produced it. Use to inspect a product's full SKU matrix before calling create_variants/update_variants/delete_variants.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| productId | Yes | Product GID. | |
| first | No |
Implementation Reference
- src/tools/variants.ts:270-317 (handler)The async handler that executes the list_variants tool logic: calls the Shopify GraphQL API with LIST_VARIANTS_QUERY, formats and returns product options and variants as text.
async (args) => { const data = await client.graphql<{ product: | { id: string; title: string; options: ProductOptionNode[]; variants: { edges: Array<{ node: VariantNode }>; pageInfo: { hasNextPage: boolean }; }; } | null; }>(LIST_VARIANTS_QUERY, { productId: args.productId, first: args.first }); if (!data.product) { return { content: [ { type: "text" as const, text: `Product not found: ${args.productId}` }, ], }; } const p = data.product; const optionLines = p.options.map( (o) => ` ${o.name} (#${o.position}): ${o.optionValues.map((v) => v.name).join(", ")}`, ); const variantLines = p.variants.edges.map(({ node }) => formatVariant(node)); return { content: [ { type: "text" as const, text: [ `${p.title} — ${p.id}`, "Options:", ...optionLines, `Variants (${p.variants.edges.length}):`, ...variantLines, p.variants.pageInfo.hasNextPage ? "(more variants available; raise `first` to page further)" : "", ] .filter(Boolean) .join("\n"), }, ], }; }, ); - src/tools/variants.ts:193-196 (schema)Input schema for list_variants: productId (string GID) and first (int, 1-100, default 50).
const listVariantsSchema = { productId: z.string().describe("Product GID."), first: z.number().int().min(1).max(100).default(50), }; - src/tools/variants.ts:266-317 (registration)Registration of the 'list_variants' tool on the McpServer inside registerVariantTools(), wired up in src/server.ts at line 64.
server.tool( "list_variants", "List all variants of a single product, plus the product's option definitions (Size, Color, etc.) and possible values. For each variant returns: title, GID, price, compareAtPrice, SKU, barcode, current inventory quantity, taxable flag, inventory policy, and the option-value combination that produced it. Use to inspect a product's full SKU matrix before calling create_variants/update_variants/delete_variants.", listVariantsSchema, async (args) => { const data = await client.graphql<{ product: | { id: string; title: string; options: ProductOptionNode[]; variants: { edges: Array<{ node: VariantNode }>; pageInfo: { hasNextPage: boolean }; }; } | null; }>(LIST_VARIANTS_QUERY, { productId: args.productId, first: args.first }); if (!data.product) { return { content: [ { type: "text" as const, text: `Product not found: ${args.productId}` }, ], }; } const p = data.product; const optionLines = p.options.map( (o) => ` ${o.name} (#${o.position}): ${o.optionValues.map((v) => v.name).join(", ")}`, ); const variantLines = p.variants.edges.map(({ node }) => formatVariant(node)); return { content: [ { type: "text" as const, text: [ `${p.title} — ${p.id}`, "Options:", ...optionLines, `Variants (${p.variants.edges.length}):`, ...variantLines, p.variants.pageInfo.hasNextPage ? "(more variants available; raise `first` to page further)" : "", ] .filter(Boolean) .join("\n"), }, ], }; }, ); - src/tools/variants.ts:249-260 (helper)Helper function that formats a VariantNode into a human-readable string used in the list_variants handler output.
function formatVariant(v: VariantNode): string { const opts = v.selectedOptions?.map((o) => `${o.name}=${o.value}`).join(", ") ?? "(no options)"; const sku = v.sku ? ` SKU:${v.sku}` : ""; const cmp = v.compareAtPrice ? ` cmp:${v.compareAtPrice}` : ""; const qty = v.inventoryQuantity !== null && v.inventoryQuantity !== undefined ? ` qty:${v.inventoryQuantity}` : ""; return ` ${v.title} [${opts}] ${v.price}${cmp}${sku}${qty} — ${v.id}`; } - src/tools/variants.ts:28-59 (helper)GraphQL query used by the list_variants tool to fetch product options and variants.
const LIST_VARIANTS_QUERY = /* GraphQL */ ` query ListVariants($productId: ID!, $first: Int!) { product(id: $productId) { id title options { id name position optionValues { id name hasVariants } } variants(first: $first) { edges { node { id title price compareAtPrice sku barcode position taxable inventoryPolicy inventoryQuantity selectedOptions { name value } } } pageInfo { hasNextPage endCursor } } } } `;