For developers and AI agents
Dubai grocery prices: REST API & MCP server
Ask “where is my grocery list cheapest in Dubai?” from a script, ChatGPT, Claude or Cursor and get the same answer as the website, with a link to open it on prices.brainy.ae. No API key; fair-use limits per IP.
Read-only. API usage metrics contain aggregate counts, not IP addresses or query text. The service does not persist comparison lists. Online search text is stored for queueing and shared caching (results are valid for 24 hours); expired records are removed asynchronously. Infrastructure request logs are separate.
What you get
- Prices observed on the websites of Dubai supermarkets and delivery sites (Spinneys, Waitrose, Union Coop, Grandiose, LuLu, Kibsons, Carrefour, Amazon.ae, Amazon Now and more), plus published delivery rules per store.
- A list comparison that buys whole packs, keeps unknown delivery fees as unknown (never 0) and ranks stores on the same comparable set of products. Missing items and provisional recommendations stay explicit.
- Live online price references from Google Shopping for products outside the catalogue: indicative, queued through a small daily quota.
- All amounts in AED with two decimals. Every response includes
attributionandopen_in_browser.
REST API (JSON, CORS enabled)
Base URL https://prices.brainy.ae/api/v1. Machine-readable description: /api/v1/openapi.json (OpenAPI 3.1).
| Endpoint | Returns |
|---|---|
| GET /api/v1 | Service name, version and links to docs, OpenAPI and MCP. |
| POST /api/v1/compare GET /api/v1/compare?items=milk,eggs&area=JLT | Recommendation for a list: store, subtotal, delivery (min/max or null with a reason), total, per-store ranking, items compared / not compared / not found, stores below minimum order, single-product mode with unit prices, catalogue date, open_in_browser. Max 40 items of 120 characters. |
| GET /api/v1/products?q= | Catalogue products matching the text: id, name, size, offers per store (AED price, unit price, store URL, observed date, exact or equivalent), product page when it exists. |
| GET /api/v1/products/{id} | Product detail and price history when available. |
| GET /api/v1/stores | Stores with delivery summary: minimum order, fee rule, source and date. |
| GET /api/v1/search?q= | Live online reference (Google Shopping): state ready, queued, rejected or capped; results[] with title, merchant, price_aed, url, relevance; retry_after_s; cached_at. |
Examples
curl -s 'https://prices.brainy.ae/api/v1/compare?items=milk,eggs,tomatoes&area=JLT'
curl -s https://prices.brainy.ae/api/v1/compare \
-H 'content-type: application/json' \
-d '{"items":["2 x milk","eggs","1 kg tomatoes"],"area":"Jumeirah Park"}'
curl -s 'https://prices.brainy.ae/api/v1/products?q=pampers'
curl -s https://prices.brainy.ae/api/v1/stores
curl -s 'https://prices.brainy.ae/api/v1/search?q=nescafe%20gold%20200g'
Live search is asynchronous: a queued answer carries retry_after_s; call again after that delay. Results are cached for 24 hours and shared by everyone who asks the same thing.
Individual product history may be empty: the current daily index publishes basket-total history, which is never attributed to a single product. The website can preload up to 4,000 list characters; browser_handoff_truncated flags longer links while the API still compares all supplied items.
Errors
Always {"error":{"code":"…","message":"…"}} with HTTP 400 (bad input), 404 (unknown product), 405, 413 (body too large), 422 (query not allowed), 429 (rate limit, with Retry-After) or 503 (data or live search temporarily unavailable).
MCP server
Remote server over Streamable HTTP, stateless, JSON responses, no authentication: https://prices.brainy.ae/mcp. Protocol versions 2025-06-18 and 2025-03-26. Server name dubai-grocery-prices.
| Tool | Input | What it does |
|---|---|---|
| compare_grocery_list | items: string[], area?: string | Compare the total cost of a grocery list across Dubai supermarkets, delivery included when known. |
| search_products | query: string | Find catalogue products and their prices per store. |
| get_product | product_id: string | Product detail and price history when available. |
| find_price_online | query: string | Live online reference price (limited quota; may answer queued with a retry delay). |
| list_stores | — | Stores and their delivery rules. |
Every tool is read-only, returns structuredContent plus a short text summary ending with the link to open the result on the website, and reports input problems as a tool result with isError: true.
Connect a client
Claude Code (terminal):
claude mcp add --transport http dubai-grocery-prices https://prices.brainy.ae/mcp
Cursor: add to .cursor/mcp.json in your project (or the global one):
{
"mcpServers": {
"dubai-grocery-prices": { "url": "https://prices.brainy.ae/mcp" }
}
}
Claude (web and desktop apps): Settings → Connectors → Add custom connector, then paste https://prices.brainy.ae/mcp. This is done in the app's settings; there is no configuration file or URL shortcut.
ChatGPT: enable Developer mode in Settings → Security and login, then open Plugins and use the plus button to create a connection to https://prices.brainy.ae/mcp. Availability depends on your account and workspace policy. See the official connection guide.
Any other MCP client that supports remote servers over Streamable HTTP without authentication: use the same URL.
Raw JSON-RPC session with curl
# 1. initialize
curl -s https://prices.brainy.ae/mcp \
-H 'content-type: application/json' -H 'accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"1.0"}}}'
# 2. acknowledge initialization
curl -s https://prices.brainy.ae/mcp \
-H 'content-type: application/json' -H 'accept: application/json, text/event-stream' \
-H 'mcp-protocol-version: 2025-06-18' \
-d '{"jsonrpc":"2.0","method":"notifications/initialized"}'
# 3. tools/list
curl -s https://prices.brainy.ae/mcp \
-H 'content-type: application/json' -H 'accept: application/json, text/event-stream' \
-H 'mcp-protocol-version: 2025-06-18' \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'
# 4. tools/call
curl -s https://prices.brainy.ae/mcp \
-H 'content-type: application/json' -H 'accept: application/json, text/event-stream' \
-H 'mcp-protocol-version: 2025-06-18' \
-d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"compare_grocery_list","arguments":{"items":["milk","eggs","1 kg tomatoes"],"area":"JLT"}}}'
The server keeps no session (no Mcp-Session-Id); notifications/initialized is accepted with 202 and no body. GET and DELETE on /mcp return 405. JSON-RPC batches are rejected with a standard error.
Limits and fair use
- 60 requests per minute and 1,500 per day per IP across REST and MCP, tracked in memory per instance (at most two instances). Over the limit: HTTP 429 with
Retry-After. - Live online search (
/api/v1/search,find_price_online) shares a small daily budget with the website: 30 new searches per day for all API clients and 5 per client per day, within the existing 80-search global daily cap. Cached answers (24 hours) are free and do not count. When the budget is used up the answer iscappedwith a retry time. - Catalogue data refreshes once a day (about 06:30 Dubai time). Responses carry a short
Cache-Control; please cache on your side too. - Version 1 has no API keys and no accounts. If you build something that needs more, write to us via brainy.ae.
Attribution and accuracy
Every response includes attribution: “Prices observed by prices.brainy.ae on <date>; online references from Google Shopping are indicative”. Please keep it, and the open_in_browser link, when you show results to people.
Prices are what the stores published when we looked; they can change during the day and at checkout. Delivery fees are estimates from public store rules or unknown, never invented. Availability, delivery slots and final totals are confirmed only at the store's checkout.
Links
- OpenAPI 3.1 document (
/api/v1/openapi.json) - API index (
/api/v1) - MCP endpoint:
https://prices.brainy.ae/mcp(POST only) - llms.txt: a plain-text summary for language models
- The website: same data, for people