Skip to main content
Glama
hung-ngm

coles-woolworths

by hung-ngm

get_coles_products

Search for products at Coles stores using specific queries and store IDs to find available items and pricing information.

Instructions

Search for products at Coles.

Args:
    query: The product search query.
    store_id: The Coles store ID to search in.
    limit: Maximum number of products to return.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
queryYes
store_idNo0584
limitNo

Implementation Reference

  • main.py:16-59 (handler)
    The primary handler function for the 'get_coles_products' tool. Decorated with @mcp.tool() for automatic registration in the MCP server. Implements the tool logic by calling helper functions to search and extract products from Coles API, applies limits, formats output.
    @mcp.tool()
    async def get_coles_products(query: str, store_id: str = COLES_DEFAULT_STORE_ID, limit: int = 10) -> str:
        """Search for products at Coles.
    
        Args:
            query: The product search query.
            store_id: The Coles store ID to search in.
            limit: Maximum number of products to return.
        """
        try:
            # The limit parameter in coles_search_products's signature is not used in its API call.
            # We will fetch all available (up to API's own limit) and then slice.
            # Also, the original coles_search_products signature includes a limit, but it's not used.
            # Forcing keyword arguments for clarity with asyncio.to_thread
            search_results = await asyncio.to_thread(
                coles_search_products,
                query=query,
                store_id=store_id
                # limit parameter is not passed here as the underlying coles_search_products doesn't use it in API call
            )
    
            if search_results.get("status") == "error":
                return f"Error fetching Coles products: {search_results.get('message', 'Unknown error')}\nResponse: {search_results.get('response_text', '')}"
    
            # extract_products is CPU-bound/quick, but run in thread for consistency with I/O
            products = await asyncio.to_thread(coles_extract_products, search_results)
    
            # Apply limit after extraction
            products = products[: min(limit, len(products))]
    
            if not products:
                return f"No products found at Coles for '{query}'."
    
            formatted_products = []
            for p in products:
                price_str = f"${p['price']:.2f}" if p['price'] is not None else "N/A"
                unit_str = p['unit'] if p['unit'] else "N/A" # Ensure unit is not None
                formatted_products.append(
                    f"Name: {p['name']}\nPrice: {price_str}\nUnit: {unit_str}\nStore: {p['store']}"
                )
            return "\n---\n".join(formatted_products)
        except Exception as e:
            return f"An unexpected error occurred in get_coles_products: {str(e)}"
  • Supporting helper 'search_products' (exposed as coles_search_products via __init__.py) that makes the HTTP request to Coles search API and returns raw response data or error.
    def search_products(query: str, store_id: str = DEFAULT_STORE_ID, limit: int = 10) -> Dict[str, Any]:
        """
        Search for products using the Coles API.
        
        Args:
            query (str): The search query
            store_id (str, optional): The store ID to search in. Defaults to DEFAULT_STORE_ID.
            limit (int, optional): The maximum number of results to return. Defaults to 10.
        
        Returns:
            Dict[str, Any]: The search results
        """
        try:
            # Use the exact URL format provided by the user
            search_url = f"{API_URL}/search"
            
            # Set up the API request parameters for search using the exact format provided
            search_params = {
                "storeId": store_id,
                "searchTerm": query,
                "start": "0",
                "sortBy": "salesDescending",
                "excludeAds": "true",
                "authenticated": "false",
                "subscription-key": API_KEY
            }
            
            # Set up the headers
            headers = {
                "Accept": "application/json",
                "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
            }
            
            # Make the API request
            response = requests.get(search_url, params=search_params, headers=headers)
            
            # Check if the request was successful
            if response.status_code != 200:
                return {
                    "status": "error",
                    "message": f"API request failed with status code {response.status_code}",
                    "response_text": response.text
                }
            
            # Parse the JSON response
            response_data = response.json()
            
            return {
                "status": "success",
                "query": query,
                "store_id": store_id,
                "response_data": response_data
            }
        except Exception as e:
            return {
                "status": "error",
                "message": str(e)
            }
  • Supporting helper 'extract_products' (exposed as coles_extract_products) that parses the raw Coles API search response to extract structured product data (name, price, unit).
    def extract_products(search_results: Dict[str, Any]) -> List[Dict[str, Any]]:
        """
        Extract product information from search results.
        
        Args:
            search_results (Dict[str, Any]): The search results from the Coles API
        
        Returns:
            List[Dict[str, Any]]: The extracted product information
        """
        products = []
        
        if search_results["status"] != "success":
            return products
        
        response_data = search_results["response_data"]
        
        # Check if the response contains products
        if "results" in response_data and response_data["results"]:
            api_products = response_data["results"]
            
            # Process the products
            for product in api_products:
                try:
                    # Extract product information
                    name = product.get("name", "")
                    
                    # Extract price information
                    pricing = product.get("pricing", {})
                    now_price = pricing.get("now", None)
                    was_price = pricing.get("was", None)
                    
                    # Use the current price if available, otherwise use the regular price
                    price = now_price if now_price is not None else was_price
                    
                    # Extract unit information - check multiple fields
                    unit = ""
                    
                    # Check package_size field
                    package_size = product.get("packageSize", "")
                    
                    # Check quantity field
                    quantity = product.get("quantity", "")
                    
                    # Check size field
                    size = product.get("size", "")
                    
                    # Check description field for unit information
                    description = product.get("description", "")
                    
                    # Try to extract unit information from available fields
                    unit_fields = [package_size, quantity, size, description]
                    for field in unit_fields:
                        if not field:
                            continue
                        
                        field = field.lower()
                        if "kg" in field:
                            unit = "kg"
                            break
                        elif "g" in field and not "mg" in field:
                            unit = "g"
                            break
                        elif "l" in field and not "ml" in field:
                            unit = "L"
                            break
                        elif "ml" in field:
                            unit = "ml"
                            break
                        elif "each" in field:
                            unit = "each"
                            break
                        elif "pack" in field:
                            unit = "pack"
                            break
                    
                    products.append({
                        "name": name,
                        "price": float(price) if price is not None else None,
                        "unit": unit,
                        "store": STORE_NAME
                    })
                except Exception as e:
                    continue
        
        return products
  • main.py:16-16 (registration)
    The @mcp.tool() decorator registers the get_coles_products function as an MCP tool with schema inferred from signature and docstring.
    @mcp.tool()
  • Constant COLES_DEFAULT_STORE_ID (aliased from DEFAULT_STORE_ID) used as default store_id parameter in the tool.
    DEFAULT_STORE_ID = "0584"
Behavior2/5

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

With no annotations provided, the description carries the full burden of behavioral disclosure. It states this is a search operation but doesn't describe what happens when no results are found, whether results are paginated, what authentication might be required, rate limits, or what the return format looks like. For a search tool with zero annotation coverage, this leaves significant behavioral questions unanswered.

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

Conciseness4/5

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

The description is appropriately sized and well-structured with a clear purpose statement followed by parameter explanations. The bullet-point format for parameters is efficient. However, the first sentence could be more specific (e.g., 'Search for grocery products at Coles supermarkets'), and the parameter descriptions could be slightly more informative.

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

Completeness2/5

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

For a search tool with 3 parameters, no annotations, and no output schema, the description is incomplete. It doesn't explain what the tool returns (product names, prices, availability?), error conditions, authentication requirements, or how results are ordered. The sibling tool context isn't leveraged to provide comparative guidance, leaving significant gaps for an AI agent.

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?

The description lists all three parameters with brief explanations, but the input schema has 0% description coverage. The description adds basic semantic meaning (e.g., 'The product search query' for 'query'), but doesn't provide format details, constraints, or examples. It compensates somewhat for the schema's lack of descriptions but doesn't fully address the coverage gap, earning a baseline score.

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

Purpose4/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 as 'Search for products at Coles' - a specific verb ('Search') and resource ('products at Coles'). It distinguishes from the sibling tool 'get_woolworths_products' by specifying the retailer. However, it doesn't explicitly mention what type of search this is (e.g., text-based product search vs. category browsing), which prevents a perfect score.

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

Usage Guidelines2/5

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

The description provides no guidance on when to use this tool versus alternatives. While the sibling tool name suggests a different retailer (Woolworths), the description doesn't mention this alternative or provide any context about when to choose Coles over Woolworths. There's no information about prerequisites, constraints, or typical use cases.

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/hung-ngm/coles-woolworths-mcp-server'

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