sephora_add_to_basket
Add products to your Sephora shopping basket. Specify a SKU ID for specific shades or sizes, or use the default variant.
Instructions
Add a product to the Sephora shopping basket. You can optionally specify a SKU ID to select a specific shade or size variant. Use sephora_get_product first to find available variant SKU IDs.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| product_url | Yes | Full Sephora product URL | |
| quantity | No | Quantity to add (1-10, default: 1) | |
| sku_id | No | Specific SKU ID for a variant (shade/size). If omitted, the default variant is used. |
Implementation Reference
- src/tools/addToBasket.ts:25-174 (handler)The main handler function that implements the sephora_add_to_basket tool logic. It navigates to a product URL, selects a variant SKU if specified, sets quantity, clicks the Add to Basket button, handles confirmation, and updates session state.
export async function addToBasket(input: AddToBasketInput): Promise<string> { const session = getSession(); const page = await session.navigateTo(input.product_url); // Wait for the Add to Basket button try { await page.waitForSelector( '[data-at="add_to_basket"], [data-at="add-to-basket"], button[data-at*="basket"]', { timeout: 15000 } ); } catch { await page.waitForTimeout(3000); } // Select specific SKU/variant if provided if (input.sku_id) { try { const variantSelector = `[data-sku-id="${input.sku_id}"], [data-id="${input.sku_id}"]`; const variantEl = page.locator(variantSelector).first(); if (await variantEl.isVisible({ timeout: 3000 })) { await variantEl.click(); await page.waitForTimeout(500); } } catch { // Variant selector not found, proceed with default } } // Get product name before adding const productInfo = await page.evaluate(() => { const nameEl = document.querySelector('[data-at="product_name"]') ?? document.querySelector("h1"); const brandEl = document.querySelector('[data-at="brand_name"]') ?? document.querySelector('[class*="brand-name"]'); const priceEl = document.querySelector('[data-at="price"]') ?? document.querySelector('[class*="price-value"]'); const selectedVariantEl = document.querySelector( '[data-at="sku_item"].selected, [class*="sku-item"].active' ); return { name: nameEl?.textContent?.trim() ?? "Product", brand: brandEl?.textContent?.trim() ?? "", price: priceEl?.textContent?.trim() ?? "", selectedVariant: selectedVariantEl?.getAttribute("data-shade-name") ?? undefined, }; }); // Handle quantity (if supported by the page) if (input.quantity && input.quantity > 1) { try { const qtySelector = 'select[data-at="quantity_selector"], input[data-at="quantity_input"]'; const qtyEl = page.locator(qtySelector).first(); if (await qtyEl.isVisible({ timeout: 2000 })) { const tagName = await qtyEl.evaluate((el) => el.tagName.toLowerCase()); if (tagName === "select") { await qtyEl.selectOption(String(input.quantity)); } else { await qtyEl.fill(String(input.quantity)); } await page.waitForTimeout(300); } } catch { // Quantity selector not available } } // Click Add to Basket const addButtonSelectors = [ '[data-at="add_to_basket"]', '[data-at="add-to-basket"]', 'button[data-at*="basket"]', 'button[data-at*="add"]', 'button:has-text("Add to Basket")', 'button:has-text("Add to Cart")', ]; let added = false; for (const selector of addButtonSelectors) { try { const btn = page.locator(selector).first(); if (await btn.isVisible({ timeout: 2000 })) { const isDisabled = await btn.isDisabled(); if (isDisabled) { return JSON.stringify({ success: false, message: "Product is out of stock or unavailable.", product: productInfo, }); } await btn.click(); added = true; break; } } catch { continue; } } if (!added) { return JSON.stringify({ success: false, message: "Could not find the 'Add to Basket' button. The product page may have loaded incorrectly.", product: productInfo, }); } // Wait for basket confirmation let confirmationMessage = "Item added to basket"; try { // Look for confirmation modal/toast const confirmationSelectors = [ '[data-at="basket_modal"]', '[data-at="add-to-basket-modal"]', '[class*="mini-basket"]', '[class*="basket-confirmation"]', '[role="dialog"][aria-label*="basket" i]', ]; for (const sel of confirmationSelectors) { const el = page.locator(sel).first(); if (await el.isVisible({ timeout: 3000 })) { const text = await el.textContent(); if (text) confirmationMessage = text.trim().slice(0, 200); break; } } } catch { // No confirmation modal found } // Update session state const state = session.getState(); session.updateState({ basketItemCount: state.basketItemCount + (input.quantity ?? 1) }); return JSON.stringify({ success: true, message: confirmationMessage, product: { ...productInfo, quantity: input.quantity ?? 1, sku_id: input.sku_id, }, basket_count: state.basketItemCount + (input.quantity ?? 1), }); } - src/tools/addToBasket.ts:4-21 (schema)Zod schema defining the input parameters for addToBasket: product_url (required URL), quantity (optional 1-10, default 1), and sku_id (optional variant identifier).
export const addToBasketSchema = z.object({ product_url: z .string() .url() .describe("Full Sephora product URL"), quantity: z .number() .int() .min(1) .max(10) .optional() .default(1) .describe("Quantity to add (1-10, default: 1)"), sku_id: z .string() .optional() .describe("Specific SKU ID for a variant (shade/size). If omitted, the default variant is used."), }); - src/index.ts:115-119 (registration)MCP tool registration defining the tool name 'sephora_add_to_basket', its description, and inputSchema converted from the Zod schema.
name: "sephora_add_to_basket", description: "Add a product to the Sephora shopping basket. You can optionally specify a SKU ID to select a specific shade or size variant. Use sephora_get_product first to find available variant SKU IDs.", inputSchema: zodToJsonSchema(addToBasketSchema) as Tool["inputSchema"], }, - src/index.ts:155-158 (handler)The tool dispatcher handler that validates input using addToBasketSchema and delegates to the addToBasket function.
sephora_add_to_basket: async (args) => { const input = addToBasketSchema.parse(args); return addToBasket(input); },