Skip to main content
Glama
CupOfOwls

Kroger MCP Server

bulk_add_to_cart

Add multiple grocery items to your Kroger cart simultaneously, streamlining shopping for pickup or delivery orders.

Instructions

    Add multiple items to the user's Kroger cart in a single operation.
    
    If the user doesn't specifically indicate a preference for pickup or delivery,
    you should ask them which modality they prefer before calling this tool.
    
    Args:
        items: List of items to add. Each item should have:
               - product_id: The product ID or UPC
               - quantity: Quantity to add (default: 1)
               - modality: PICKUP or DELIVERY (default: PICKUP)
    
    Returns:
        Dictionary with results for each item
    

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
itemsYes

Implementation Reference

  • The core handler function for the 'bulk_add_to_cart' tool. It takes a list of items, formats them for the Kroger API, adds them to the cart using client.cart.add_to_cart(), updates local cart tracking using _add_item_to_local_cart, and handles errors with detailed responses.
    @mcp.tool()
    async def bulk_add_to_cart(
        items: List[Dict[str, Any]],
        ctx: Context = None
    ) -> Dict[str, Any]:
        """
        Add multiple items to the user's Kroger cart in a single operation.
        
        If the user doesn't specifically indicate a preference for pickup or delivery,
        you should ask them which modality they prefer before calling this tool.
        
        Args:
            items: List of items to add. Each item should have:
                   - product_id: The product ID or UPC
                   - quantity: Quantity to add (default: 1)
                   - modality: PICKUP or DELIVERY (default: PICKUP)
        
        Returns:
            Dictionary with results for each item
        """
        try:
            if ctx:
                await ctx.info(f"Adding {len(items)} items to cart in bulk")
            
            client = get_authenticated_client()
            
            # Format items for the API
            cart_items = []
            for item in items:
                cart_item = {
                    "upc": item["product_id"],
                    "quantity": item.get("quantity", 1),
                    "modality": item.get("modality", "PICKUP")
                }
                cart_items.append(cart_item)
            
            if ctx:
                await ctx.info(f"Calling Kroger API to add {len(cart_items)} items")
            
            # Add all items to the actual Kroger cart
            client.cart.add_to_cart(cart_items)
            
            if ctx:
                await ctx.info("Successfully added all items to Kroger cart")
            
            # Add all items to local cart tracking
            for item in items:
                _add_item_to_local_cart(
                    item["product_id"],
                    item.get("quantity", 1),
                    item.get("modality", "PICKUP")
                )
            
            if ctx:
                await ctx.info("All items added to local cart tracking")
            
            return {
                "success": True,
                "message": f"Successfully added {len(items)} items to cart",
                "items_added": len(items),
                "timestamp": datetime.now().isoformat()
            }
            
        except Exception as e:
            if ctx:
                await ctx.error(f"Failed to bulk add items to cart: {str(e)}")
            
            error_message = str(e)
            if "401" in error_message or "Unauthorized" in error_message:
                return {
                    "success": False,
                    "error": "Authentication failed. Please run force_reauthenticate and try again.",
                    "details": error_message
                }
            else:
                return {
                    "success": False,
                    "error": f"Failed to add items to cart: {error_message}",
                    "items_attempted": len(items)
                }
  • The registration block in the main server file where cart_tools.register_tools(mcp) is called, which in turn defines and registers the bulk_add_to_cart tool using @mcp.tool() decorator.
    # Register all tools from the modules
    location_tools.register_tools(mcp)
    product_tools.register_tools(mcp)
    cart_tools.register_tools(mcp)
    info_tools.register_tools(mcp)
    profile_tools.register_tools(mcp)
    utility_tools.register_tools(mcp)
    auth_tools.register_tools(mcp)
  • Helper function _add_item_to_local_cart used by bulk_add_to_cart to maintain local cart tracking since Kroger API does not support cart viewing.
    def _add_item_to_local_cart(product_id: str, quantity: int, modality: str, product_details: Dict[str, Any] = None) -> None:
        """Add an item to the local cart tracking"""
        cart_data = _load_cart_data()
        current_cart = cart_data.get("current_cart", [])
        
        # Check if item already exists in cart
        existing_item = None
        for item in current_cart:
            if item.get("product_id") == product_id and item.get("modality") == modality:
                existing_item = item
                break
        
        if existing_item:
            # Update existing item quantity
            existing_item["quantity"] = existing_item.get("quantity", 0) + quantity
            existing_item["last_updated"] = datetime.now().isoformat()
        else:
            # Add new item
            new_item = {
                "product_id": product_id,
                "quantity": quantity,
                "modality": modality,
                "added_at": datetime.now().isoformat(),
                "last_updated": datetime.now().isoformat()
            }
            
            # Add product details if provided
            if product_details:
                new_item.update(product_details)
            
            current_cart.append(new_item)
        
        cart_data["current_cart"] = current_cart
        cart_data["last_updated"] = datetime.now().isoformat()
        _save_cart_data(cart_data)
  • Docstring providing the input schema (items list with product_id, quantity, modality) and output description for the bulk_add_to_cart tool.
    """
    Add multiple items to the user's Kroger cart in a single operation.
    
    If the user doesn't specifically indicate a preference for pickup or delivery,
    you should ask them which modality they prefer before calling this tool.
    
    Args:
        items: List of items to add. Each item should have:
               - product_id: The product ID or UPC
               - quantity: Quantity to add (default: 1)
               - modality: PICKUP or DELIVERY (default: PICKUP)
    
    Returns:
        Dictionary with results for each item
    """
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 describes the bulk operation nature and modality requirement, but lacks details on authentication needs, error handling, rate limits, or what happens if items are unavailable. The description doesn't contradict any annotations (none provided).

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?

Well-structured with clear sections: purpose statement, usage guidance, parameter details, and return value. Every sentence adds value - no wasted words. The information is front-loaded with the core purpose first.

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?

For a mutation tool with no annotations and no output schema, the description does well covering purpose, usage, and parameters. However, it could better explain the return value format ('Dictionary with results for each item' is vague) and lacks details on error cases or authentication requirements.

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

Parameters5/5

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

With 0% schema description coverage (schema only shows 'items' as array of objects), the description fully compensates by detailing the structure of each item object: product_id, quantity with default, modality with default and allowed values. This adds significant meaning beyond the bare schema.

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 tool's purpose with specific verb ('Add multiple items') and resource ('user's Kroger cart'), and distinguishes it from the sibling 'add_items_to_cart' by emphasizing bulk operation in a single call. The title being null doesn't affect this clarity.

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?

Explicit guidance is provided on when to use this tool: for adding multiple items in bulk, and when not to use it (if user hasn't specified pickup/delivery preference, ask first). This clearly differentiates it from the single-item 'add_items_to_cart' sibling tool.

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/CupOfOwls/kroger-mcp'

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