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);
    },
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries full burden. It mentions optional SKU ID selection for variants, which adds useful context about behavior, but lacks details on permissions, error handling, or what happens if the product is out of stock. For a mutation tool with zero annotation coverage, this leaves gaps in behavioral understanding.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, zero waste. The first sentence states the purpose, and the second provides essential usage guidance, making it front-loaded and efficiently structured without unnecessary details.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no annotations and no output schema, the description adequately covers the tool's purpose and usage in context with siblings. However, as a mutation tool, it could benefit from more behavioral details like confirmation of success or error scenarios, leaving minor gaps in completeness.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all parameters thoroughly. The description adds minimal value by mentioning the SKU ID for variants, but doesn't provide additional syntax or format details beyond what the schema specifies. Baseline 3 is appropriate when schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('Add a product') and resource ('to the Sephora shopping basket'), specifying it's for adding items to a shopping cart. It distinguishes from siblings like sephora_get_product (for finding products) and sephora_view_basket (for viewing the basket).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states when to use this tool ('Add a product to the Sephora shopping basket') and provides a clear alternative ('Use sephora_get_product first to find available variant SKU IDs'), guiding the agent on proper workflow and tool sequencing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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