Skip to main content
Glama

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
NameRequiredDescriptionDefault
product_urlYesFull Sephora product URL
quantityNoQuantity to add (1-10, default: 1)
sku_idNoSpecific SKU ID for a variant (shade/size). If omitted, the default variant is used.

Implementation Reference

  • 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),
      });
    }
  • 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"],
    },
  • 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);
    },

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/markswendsen-code/mcp-sephora'

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