Skip to main content
Glama
CupOfOwls

Kroger MCP Server

search_products

Find grocery items at Kroger stores by searching product names, filtering by brand or fulfillment method, and specifying store location.

Instructions

    Search for products at a Kroger store.
    
    Args:
        search_term: Product search term (e.g., "milk", "bread", "organic apples")
        location_id: Store location ID (uses preferred location if not provided)
        limit: Number of results to return (1-50)
        fulfillment: Filter by fulfillment method (csp=curbside pickup, delivery, pickup)
        brand: Filter by brand name
    
    Returns:
        Dictionary containing product search results
    

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
search_termYes
location_idNo
limitNoNumber of results to return (1-50)
fulfillmentNo
brandNo

Implementation Reference

  • The core handler function decorated with @mcp.tool() that implements the search_products tool logic: validates inputs, gets Kroger client, calls API, formats results (products with pricing, inventory, aisles, images), handles errors.
    @mcp.tool()
    async def search_products(
        search_term: str,
        location_id: Optional[str] = None,
        limit: int = Field(default=10, ge=1, le=50, description="Number of results to return (1-50)"),
        fulfillment: Optional[Literal["csp", "delivery", "pickup"]] = None,
        brand: Optional[str] = None,
        ctx: Context = None
    ) -> Dict[str, Any]:
        """
        Search for products at a Kroger store.
        
        Args:
            search_term: Product search term (e.g., "milk", "bread", "organic apples")
            location_id: Store location ID (uses preferred location if not provided)
            limit: Number of results to return (1-50)
            fulfillment: Filter by fulfillment method (csp=curbside pickup, delivery, pickup)
            brand: Filter by brand name
        
        Returns:
            Dictionary containing product search results
        """
        # Use preferred location if none provided
        if not location_id:
            location_id = get_preferred_location_id()
            if not location_id:
                return {
                    "success": False,
                    "error": "No location_id provided and no preferred location set. Use set_preferred_location first."
                }
        
        if ctx:
            await ctx.info(f"Searching for '{search_term}' at location {location_id}")
        
        client = get_client_credentials_client()
        
        try:
            products = client.product.search_products(
                term=search_term,
                location_id=location_id,
                limit=limit,
                fulfillment=fulfillment,
                brand=brand
            )
            
            if not products or "data" not in products or not products["data"]:
                return {
                    "success": False,
                    "message": f"No products found matching '{search_term}'",
                    "data": []
                }
            
            # Format product data
            formatted_products = []
            for product in products["data"]:
                formatted_product = {
                    "product_id": product.get("productId"),
                    "upc": product.get("upc"),
                    "description": product.get("description"),
                    "brand": product.get("brand"),
                    "categories": product.get("categories", []),
                    "country_origin": product.get("countryOrigin"),
                    "temperature": product.get("temperature", {})
                }
                
                # Add item information (size, price, etc.)
                if "items" in product and product["items"]:
                    item = product["items"][0]
                    formatted_product["item"] = {
                        "size": item.get("size"),
                        "sold_by": item.get("soldBy"),
                        "inventory": item.get("inventory", {}),
                        "fulfillment": item.get("fulfillment", {})
                    }
                    
                    # Add pricing information
                    if "price" in item:
                        price = item["price"]
                        formatted_product["pricing"] = {
                            "regular_price": price.get("regular"),
                            "sale_price": price.get("promo"),
                            "regular_per_unit": price.get("regularPerUnitEstimate"),
                            "formatted_regular": format_currency(price.get("regular")),
                            "formatted_sale": format_currency(price.get("promo")),
                            "on_sale": price.get("promo") is not None and price.get("promo") < price.get("regular", float('inf'))
                        }
                
                # Add aisle information
                if "aisleLocations" in product:
                    formatted_product["aisle_locations"] = [
                        {
                            "description": aisle.get("description"),
                            "number": aisle.get("number"),
                            "side": aisle.get("side"),
                            "shelf_number": aisle.get("shelfNumber")
                        }
                        for aisle in product["aisleLocations"]
                    ]
                
                # Add image information
                if "images" in product and product["images"]:
                    formatted_product["images"] = [
                        {
                            "perspective": img.get("perspective"),
                            "url": img["sizes"][0].get("url") if img.get("sizes") else None,
                            "size": img["sizes"][0].get("size") if img.get("sizes") else None
                        }
                        for img in product["images"]
                        if img.get("sizes")
                    ]
                
                formatted_products.append(formatted_product)
            
            if ctx:
                await ctx.info(f"Found {len(formatted_products)} products")
            
            return {
                "success": True,
                "search_params": {
                    "search_term": search_term,
                    "location_id": location_id,
                    "limit": limit,
                    "fulfillment": fulfillment,
                    "brand": brand
                },
                "count": len(formatted_products),
                "data": formatted_products
            }
            
        except Exception as e:
            if ctx:
                await ctx.error(f"Error searching products: {str(e)}")
            return {
                "success": False,
                "error": str(e),
                "data": []
            }
  • Pydantic-based input schema defined by function parameters, including search_term (required), optional filters like limit, fulfillment, brand, with validation via Field.
    async def search_products(
        search_term: str,
        location_id: Optional[str] = None,
        limit: int = Field(default=10, ge=1, le=50, description="Number of results to return (1-50)"),
        fulfillment: Optional[Literal["csp", "delivery", "pickup"]] = None,
        brand: Optional[str] = None,
        ctx: Context = None
    ) -> Dict[str, Any]:
  • Registers all product tools including search_products by calling the register_tools function from product_tools module.
    product_tools.register_tools(mcp)
  • Imports the product_tools module which contains the register_tools function.
    from .tools import product_tools
  • Uses helper get_client_credentials_client() and calls the underlying Kroger SDK client.product.search_products() API method.
    client = get_client_credentials_client()
    
    try:
        products = client.product.search_products(
            term=search_term,
            location_id=location_id,
            limit=limit,
            fulfillment=fulfillment,
            brand=brand
        )

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