Koskamo

Pinch Grocery Prices MCP

An official MCP server operated by Pinch that provides Australian grocery price intelligence. It enables AI agents to search products across Woolworths, Coles, ALDI, and Harris Farm, retrieve 52-week price history, and build cheapest-correct shopping baskets.

Endpoint and access

No sign-in to connect and list tools. Individual tools may still need a vendor account, credentials, or permissions; check the documented prerequisites.

Pinch Grocery Prices MCP logo, by PinchVendor evidenceStreamable HTTPNo sign-inEndpoint checked 2026-11-06Operated by Pinch
You need:Free API keys
MCP endpoint (Streamable HTTP)
https://pinch-app.com/api/mcp
Vendor documentation

What its tools do

10 tools, grouped by the hints the server advertises. Hints are self-declared, not verified behavior.

10 of 10 have a description · 0 of 10 declare behavior hints · 8 of 10 with parameters document them all

Checks and signals

Each line is separate evidence, not a trust score.

  • Passed Endpoint answered the live check ·
  • Passed Official MCP Registry namespace is tied to pinch-app.com ·
  • Passed Endpoint is on the registry namespace domain ·
  • Availability 1 of 1 checks passed in 30 days

What you can do with it

  • Search for grocery products across multiple Australian retailers
  • Retrieve 52-week price history for specific items
  • Build the cheapest shopping basket from a raw list
  • Generate shareable basket URLs for price comparison

Source and maintenance

Vendor evidenceRegistry 1.0.0

Protocol and capabilities

Server
pinch-grocery-data 1.0.0
MCP protocol negotiated in check
2025-06-18
Tools
10 advertised
Resources
Not advertised
Resource templates
Not advertised
Prompts
Not advertised
Server-advertised capabilities
{
  "tools": {}
}

Server-provided instructions

Untrusted server output shown for inspection. It is not Koskamo guidance and is excluded from knowledge search.

Pinch provides Australian grocery price data (Woolworths, Coles, Aldi, Harris Farm). SHOPPING LISTS (2 or more items): call build_basket ONCE with the full list of item strings. Include any size or quantity in the string ("2L", "1kg", "12 pack"). build_basket searches every item server-side, picks the cheapest product per item, and returns the basket with per-retailer options plus a share_url. Do NOT call decompose_product, search_products, or batch_search per item for a list. IMPORTANT: before rendering, review every pick for correctness (the search engine uses keyword matching and sometimes returns wrong products). Follow the VALIDATION instructions in the build_basket tool description. SINGLE ITEM or a price question: use search_products, get_cheapest, compare_prices, or get_price_history. decompose_product, batch_search and save_basket are advanced tools for overriding build_basket's pick on one specific item only; do not use them for a normal shopping list. Guidance: default to cheapest-first; only filter to a brand or retailer if the user explicitly asks. A product sold loose or priced per-each (loose produce, a single bar) is a valid pick. Honour requested sizes and counts.

Tools

10 advertised

search_products
Advertised by the server during the last successful anonymous check.

Search Australian grocery products across Woolworths, Coles, Aldi, and Harris Farm. Returns product name, price, brand, category, unit price, and whether it's on special.

search_products input schema
{
  "type": "object",
  "required": [
    "query"
  ],
  "properties": {
    "sort": {
      "enum": [
        "relevance",
        "price_asc",
        "price_desc",
        "unit_price_asc"
      ],
      "type": "string",
      "default": "relevance"
    },
    "limit": {
      "type": "number",
      "description": "Number of results (1-50, default 20)"
    },
    "query": {
      "type": "string",
      "description": "Search query (e.g., 'full cream milk', 'chicken breast')"
    },
    "category": {
      "type": "string",
      "description": "Filter by category"
    },
    "retailer": {
      "enum": [
        "Woolworths",
        "Coles",
        "Aldi",
        "Harris Farm"
      ],
      "type": "string"
    },
    "on_special": {
      "type": "boolean",
      "description": "If true, only return products on special"
    }
  }
}
get_product
Advertised by the server during the last successful anonymous check.

Get detailed information about a specific grocery product by its ID. Product IDs are returned in search results.

get_product input schema
{
  "type": "object",
  "required": [
    "product_id"
  ],
  "properties": {
    "product_id": {
      "type": "string",
      "description": "Product ID from search results"
    }
  }
}
compare_prices
Advertised by the server during the last successful anonymous check.

Compare prices for the same product across retailers using its barcode. Returns all retailers stocking the product, sorted cheapest first. About 7,800 products have barcode matches.

compare_prices input schema
{
  "type": "object",
  "required": [
    "barcode"
  ],
  "properties": {
    "barcode": {
      "type": "string",
      "description": "EAN-13 barcode (e.g., '9300675016902')"
    }
  }
}
get_price_history
Advertised by the server during the last successful anonymous check.

Get historical price data for a product. Shows price changes over time with stats (lowest, highest, average). History depth depends on your tier (30-365 days).

get_price_history input schema
{
  "type": "object",
  "required": [
    "product_id"
  ],
  "properties": {
    "days": {
      "type": "number",
      "description": "Number of days of history (default: max for your tier)"
    },
    "product_id": {
      "type": "string",
      "description": "Product ID from search results"
    }
  }
}
get_specials
Advertised by the server during the last successful anonymous check.

Get current grocery specials and promotions. Filter by retailer or category. Results include savings amounts. Updated weekly. Specials captured before the most recent Wednesday catalogue changeover (Coles/Woolworths) are excluded as unconfirmed; after a changeover the list can be near-empty until the next collection. Individual products still expose such prices via get_product with special_may_have_ended: true.

get_specials input schema
{
  "type": "object",
  "properties": {
    "limit": {
      "type": "number",
      "description": "Number of results (1-50, default 20)"
    },
    "category": {
      "type": "string",
      "description": "Filter by category"
    },
    "retailer": {
      "enum": [
        "Woolworths",
        "Coles",
        "Aldi",
        "Harris Farm"
      ],
      "type": "string"
    }
  }
}
get_cheapest
Advertised by the server during the last successful anonymous check.

Find the cheapest option for a product across all Australian grocery retailers. Searches by name and returns results sorted by price ascending.

get_cheapest input schema
{
  "type": "object",
  "required": [
    "product_name"
  ],
  "properties": {
    "limit": {
      "type": "number",
      "description": "Number of results (1-50, default 10)"
    },
    "product_name": {
      "type": "string",
      "description": "Product to search for (e.g., 'full cream milk 2L')"
    }
  }
}
decompose_product
Advertised by the server during the last successful anonymous check.

ADVANCED / single item. Do NOT use this to build a shopping list: for any list of 2 or more items, call build_basket (one call, server-side). Use decompose_product only to break ONE item into structured search attributes when you intend to override build_basket's pick for that single item. This does not call any API; it is a structured reasoning step. OUTPUT: canonical_query, disqualifiers, and suggested_category for that single item. Fill in every field based on what a typical Australian family would mean by this item. CORE RULE: Unless the user literally specifies a brand, brand_preference MUST be null and the strategy is cheapest-first (unit_price_asc, no retailer filter).

decompose_product input schema
{
  "type": "object",
  "required": [
    "raw_input",
    "category_path",
    "canonical_query",
    "quantity",
    "qualifiers",
    "disqualifiers",
    "barcode_eligible"
  ],
  "properties": {
    "quantity": {
      "type": "object",
      "properties": {
        "size": {
          "type": "string",
          "description": "Expected size, e.g. '1kg', '2L', '6-pack'"
        },
        "intent": {
          "type": "string",
          "description": "Size intent: 'family' (2-3L/1-2kg), 'single serve', 'standard', 'bulk'"
        }
      },
      "description": "Target size. Use to filter results after search. Family intent means prefer larger sizes for better unit price."
    },
    "raw_input": {
      "type": "string",
      "description": "The item exactly as the user wrote it"
    },
    "qualifiers": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Soft preferences that improve a match but don't disqualify if absent. e.g. ['skinless', 'boneless'] for chicken breast, ['Australian'] for sultanas"
    },
    "category_path": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Ontological path from general to specific, e.g. ['meat', 'poultry', 'chicken', 'breast'] or ['pantry', 'cereal', 'wheat biscuits']"
    },
    "disqualifiers": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Terms that indicate a WRONG product. Results containing these MUST be excluded. e.g. for 'chicken breast': ['thigh', 'drumstick', 'wing', 'nugget', 'schnitzel', 'crumbed', 'marinated']. For 'Vegemite': ['twist', 'scroll', 'shapes', 'cheesy bite']. For 'strawberries': ['yoghurt', 'jam', 'ice cream', 'flavoured']. For 'milk': ['flavoured', 'chocolate', 'coffee', 'almond', 'oat', 'soy', 'coconut']."
    },
    "canonical_query": {
      "type": "string",
      "description": "The cleaned search term to use with search_products. Strip sizes and brands (unless brand IS the product, like 'Vegemite'). 'chicken breast bulk pack' becomes 'chicken breast fillets'. 'Sanitarium Weet-Bix' becomes 'Weet-Bix'. 'full cream milk 2L' becomes 'full cream milk'."
    },
    "barcode_eligible": {
      "type": "boolean",
      "description": "true for branded packaged goods (Weet-Bix, Vegemite, cheese slices, chips). false for fresh produce, meat, and store-brand generics. When true AND a result has a barcode, call compare_prices to check if another retailer has it cheaper."
    },
    "brand_preference": {
      "type": "string",
      "description": "ONLY set this if the user LITERALLY named a brand (e.g. 'Weet-Bix', 'Vegemite'). If the user wrote a generic item like 'milk', 'chicken breast', 'eggs', 'bread', this MUST be null. When null, Pinch finds the cheapest option regardless of brand."
    },
    "suggested_category": {
      "type": "string",
      "description": "The grocery store category to filter search results. Use this to prevent wrong-category contamination. e.g. 'Pantry' for rice crackers (prevents dairy lunch packs), 'Fruit & Vegetables' for fresh produce, 'Meat & Seafood' for meat, 'Dairy, Eggs & Fridge' for dairy, 'Frozen' for frozen items. Only set when the item clearly belongs to one category and cross-category results would be noise."
    }
  }
}
batch_search
Advertised by the server during the last successful anonymous check.

ADVANCED / manual selection. Do NOT use this to build a shopping list: for any list of 2 or more items, call build_basket (one call, server-side, cheapest pick per item). Use batch_search only when you need the RAW candidate products for items you intend to select MANUALLY (for example, to override build_basket's pick on one item). It searches multiple items in parallel and returns raw candidate products per query (up to candidates_per_retailer per retailer) with NO filtering or scoring applied. WORKFLOW: 1. Call batch_search with your shopping list items 2. Review the candidates for each item. For each query, pick the single best product_id per retailer that actually matches what the user wants (correct product type, reasonable size, not a different product). If none of the candidates are a good match for a query, call batch_search again with a refined query (e.g., more specific terms, different wording) 3. Once you have confirmed product_id selections for all items, call save_basket with your picks TIPS: - Set product_type to help narrow results to the right category (e.g., fresh_produce for herbs and vegetables) - Each candidate includes a product_categories field (JSON array of retailer category labels like 'Yoghurt', 'Herbs & Spices', 'Sausages'). Use this to distinguish the actual product type when names are ambiguous (e.g., 'oregano' the herb vs 'oregano sausages') - Prefer products where the name clearly matches the query intent - For staples (milk, eggs, bread), the cheapest option is usually the store brand - If results look wrong (e.g., searching 'rosemary' returns snacks instead of herbs), retry with a more specific query like 'fresh rosemary' - Each item includes a 'cheapest' hint with one entry per retailer. This is the cheapest candidate whose product_categories match the inferred subcategory for the query, NOT necessarily the lowest unit_price overall: a clearly off-category cheaper item (e.g., a snack bar under 'peanut butter') is deliberately excluded. When no category signal is available it falls back to the raw lowest unit_price. Treat the hint as advisory and confirm against the full candidate list and the user's intended format. AMBIGUITY: When candidates for a query span clearly different product formats (e.g., microwave rice pouches vs dry rice bags, single-serve vs family/bulk sizes, flavoured vs plain variants, fresh vs frozen), ASK the user which format they prefer before selecting a product. Compare the size field across candidates to detect this: a spread from 125g to 5kg signals format ambiguity. Do not silently pick the cheapest option when it may be the wrong format (e.g., a 250g microwave pouch when the user likely wants a 1kg bag).

batch_search input schema
{
  "type": "object",
  "required": [
    "items"
  ],
  "properties": {
    "items": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "query"
        ],
        "properties": {
          "query": {
            "type": "string",
            "description": "Item name as on a shopping list (e.g., 'chicken breast 1kg', 'fresh rosemary', 'sea salt')"
          },
          "category": {
            "type": "string",
            "description": "Explicit category filter (e.g., 'Fruit & Vegetables'). Overrides product_type."
          },
          "product_type": {
            "enum": [
              "fresh_produce",
              "meat",
              "dairy",
              "pantry",
              "frozen",
              "drinks",
              "bakery",
              "deli"
            ],
            "type": "string",
            "description": "Category hint. Set fresh_produce for fruits/vegetables/herbs, meat for raw proteins, dairy for milk/cheese/eggs/yoghurt, pantry for canned/dried/shelf-stable goods."
          }
        }
      },
      "description": "List of grocery items to search (1-20 items)."
    },
    "retailers": {
      "type": "array",
      "items": {
        "enum": [
          "Woolworths",
          "Coles",
          "Aldi",
          "Harris Farm"
        ],
        "type": "string"
      },
      "description": "Filter to these retailers only. If omitted, all 4 are searched."
    },
    "candidates_per_retailer": {
      "type": "number",
      "description": "Number of candidate products to return per retailer per item (1-30, default 10). Use more candidates if you expect ambiguous results."
    }
  }
}
save_basket
Advertised by the server during the last successful anonymous check.

ADVANCED / manual commit. Do NOT use this to build a basket from a shopping list: for any list of 2 or more items, call build_basket (it searches, picks the cheapest, totals, and returns a share_url in one call). Use save_basket only to commit a basket from product_ids you have ALREADY chosen yourself (for example, after overriding build_basket's pick on an item). It computes totals and returns a shareable basket URL. For each item, provide the query string and one product_id per retailer (the best match you found in batch_search results). You do NOT need a pick for every retailer; omit a retailer if no good match was found. IMPORTANT: Only call this after you have reviewed batch_search results and confirmed your picks. Do not pass product_ids blindly from search results.

save_basket input schema
{
  "type": "object",
  "required": [
    "selections"
  ],
  "properties": {
    "selections": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "query",
          "picks"
        ],
        "properties": {
          "picks": {
            "type": "object",
            "description": "Best product_id per retailer. Keys are retailer names (Woolworths, Coles, Aldi, Harris Farm). Values are product_id strings.",
            "additionalProperties": {
              "type": "string"
            }
          },
          "query": {
            "type": "string",
            "description": "Original search query (for display in basket)"
          }
        }
      },
      "description": "List of confirmed product selections, one entry per shopping list item."
    }
  }
}
build_basket
Advertised by the server during the last successful anonymous check.

MANDATORY for shopping lists. When the user gives you 2 or more grocery items, call this tool ONCE with the full list. Do NOT call decompose_product, search_products, or batch_search per item: this tool searches every item in parallel with built-in query analysis (category routing, brand aliases, subcategory boost) and returns a basket with per-item cheapest pick, per-retailer options, basket total, retailer totals, and a shareable share_url. If the user named the stores they shop at, pass them in 'retailers'; otherwise omit it to search all four. VALIDATION (mandatory before rendering): The search engine uses keyword matching, so wrong products leak through. Items flagged with a 'review' field on their cheapest pick are LIKELY WRONG and need your attention first. Then scan ALL picks (flagged or not) and check: (1) Is the product actually what was asked for? (e.g. 'frozen chips' is NOT 'frozen blueberries', 'sweet potato' is NOT 'potato', 'chicken fingers crumbed' is NOT 'chicken breast') (2) Is the size/form correct? (e.g. 400g pack is not a valid match for '2kg') (3) Is the selected option the cheapest CORRECT product, not just the cheapest product? If a pick is wrong: pick the correct product from by_retailer options for that item, or mark as '(check in store)'. Recalculate basket_total from your corrected picks. OUTPUT FORMAT: Line 1: '**Cheapest basket: $X.XX**' (use corrected basket_total). Then ONE markdown table with columns: Item | Product | Store | Price | Size. Then one line: 'View and share this basket: <share_url>'. Use '(check in store)' in the Product cell for items in items_missing or where no correct product exists. No preamble, no per-item narration, no follow-up offers.

build_basket input schema
{
  "type": "object",
  "required": [
    "items"
  ],
  "properties": {
    "items": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Shopping list items exactly as the user wrote them, e.g. ['4 bananas', 'whole chicken', '12 free range eggs', 'full cream milk 2L', 'spaghetti', 'sliced white bread']. Include any size/quantity in the string ('2L', '1kg', '12 pack') so the cheapest CORRECT size is chosen."
    },
    "retailers": {
      "type": "array",
      "items": {
        "enum": [
          "Woolworths",
          "Coles",
          "Aldi",
          "Harris Farm"
        ],
        "type": "string"
      },
      "description": "Only return results from these stores. Omit to search all four."
    }
  }
}

Prompts

Not advertised

No prompt definitions available.

Resources

Not advertised

No resource definitions available.

90-day uptime

A lightweight connection check about every six hours, sampled on hosts with many listings. It shows the server answered, not that its tools work.

Too few checks for a percentage yet (2 of 2 answered).

  1. 2026-11-06: 1 of 1 checks answered
  2. 2026-11-07: 1 of 1 checks answered

30-day availability

Aggregated from read-only remote checks; this is not a tool-execution or security guarantee.

Successful checks
1 of 1 (100%)
Average latency
679 ms
95th percentile latency
679 ms

Maintenance history

Public check and source-refresh events. Editorial and ownership records remain private.

  • · probe · passed · 679 ms · metadata changed · 10 tool(s)

Connect from your client

Each snippet registers the same endpoint; pick the client you use.

This server is operated by the named third party. Listing and endpoint checks are not an endorsement or a security audit. Review the operator's permissions, terms, and data handling before connecting. How listings are checked and corrected.

Claude Code

Run this once in a terminal. It registers the remote server. Use --scope project to write .mcp.json for the repo.
Claude Code configuration
claude mcp add --transport http pinch-grocery-prices-mcp https://pinch-app.com/api/mcp

Codex

Run this once. Codex stores MCP servers in ~/.codex/config.toml (or .codex/config.toml in a trusted project).
Codex configuration
codex mcp add pinch-grocery-prices-mcp --url https://pinch-app.com/api/mcp

Cursor

Merge this server into .cursor/mcp.json in your project, then enable pinch-grocery-prices-mcp in your MCP settings.
Cursor configuration
{
  "mcpServers": {
    "pinch-grocery-prices-mcp": {
      "url": "https://pinch-app.com/api/mcp"
    }
  }
}

Cline

Merge this into cline_mcp_settings.json (Cline → MCP Servers → Configure).
Cline configuration
{
  "mcpServers": {
    "pinch-grocery-prices-mcp": {
      "type": "streamableHttp",
      "url": "https://pinch-app.com/api/mcp",
      "disabled": false
    }
  }
}

VS Code

Merge this server into .vscode/mcp.json. Use MCP: List Servers to start pinch-grocery-prices-mcp and inspect its tools.
VS Code configuration
{
  "servers": {
    "pinch-grocery-prices-mcp": {
      "type": "http",
      "url": "https://pinch-app.com/api/mcp"
    }
  }
}

Gemini CLI

Run this once. It writes .gemini/settings.json in the current project; pass --scope user for ~/.gemini/settings.json.
Gemini CLI configuration
gemini mcp add --transport http pinch-grocery-prices-mcp https://pinch-app.com/api/mcp

Claude Desktop

Open Claude Settings > Connectors > Add custom connector, enter this server URL and enable it for the conversation. This is a manual remote-connector handoff, not a desktop JSON configuration.
Claude Desktop configuration
https://pinch-app.com/api/mcp

Windsurf

Merge this into ~/.codeium/windsurf/mcp_config.json, then refresh MCP in Cascade. Windsurf remote servers use serverUrl, not url.
Windsurf configuration
{
  "mcpServers": {
    "pinch-grocery-prices-mcp": {
      "serverUrl": "https://pinch-app.com/api/mcp"
    }
  }
}

Let your agent find its tools

Find servers like Pinch Grocery Prices MCP from your agent. Add Koskamo once to search the index for endpoints, access requirements, and client setup. Public discovery needs no key.

Do you run Pinch Grocery Prices MCP?

Prove ownership with a DNS record, a well-known file, or your Official MCP Registry entry, and your edits publish immediately. Proofs are re-checked weekly; admins can still hide or remove a listing.

Claim this listing