DEV Community

BuyWhere
BuyWhere

Posted on Originally published at buywhere.ai

Build a 4K monitor price watcher for Singapore with BuyWhere MCP

A 32-inch 4K panel in Singapore still jumps S$80–S$200 on sale days. Brand pages lag. Agent-readable prices do not.

This is a 40-line watcher that queries BuyWhere's MCP, filters SGD 4K monitors, and prints a ranked table. Pair it with the live comparison pages — they now render /r/ merchant links again (probed 2026-09-01):

Why MCP, not six retailer APIs

Shopee, Lazada, Amazon, and local electronics shops do not share a schema. BuyWhere's MCP (search_products) returns price.amount + price.currency nested under price. Always read it nested:

cur = item.get("price", {}).get("currency")
amt = item.get("price", {}).get("amount")
Enter fullscreen mode Exit fullscreen mode

If you flatten those fields you will silently drop SGD rows. That is the #1 integration bug we see.

Install

pip install mcp
# or call the HTTP catalog:
# GET https://buywhere.ai/api/search?country=SG&query=4k%20monitor
Enter fullscreen mode Exit fullscreen mode

Watcher

import json, urllib.parse, urllib.request

def search(q, country="SG"):
    url = "https://buywhere.ai/api/search?" + urllib.parse.urlencode({"country": country, "query": q})
    req = urllib.request.Request(url, headers={"User-Agent": "4k-monitor-watcher/1.0", "Accept": "application/json"})
    with urllib.request.urlopen(req, timeout=20) as r:
        data = json.loads(r.read())
    return data if isinstance(data, list) else data.get("data") or data.get("results") or []

def priced(items):
    out = []
    for x in items:
        p = x.get("price") or {}
        if isinstance(p, dict) and p.get("currency") == "SGD" and p.get("amount"):
            out.append((float(p["amount"]), x.get("title") or x.get("name"), p["currency"]))
    return sorted(out, key=lambda t: t[0])[:8]

for q in ("4k monitor", "4k oled monitor", "27 4k ips"):
    rows = priced(search(q))
    print(f"\n== {q} ({len(rows)} SGD-priced) ==")
    for amt, title, cur in rows:
        print(f"  {cur} {amt:8.2f}  {title[:70]}")
Enter fullscreen mode Exit fullscreen mode

Run it on a cron. When a SKU drops below your threshold, post to Slack / Telegram (see last week's bot: Dev.to 4545487).

What the live page already does for you

https://buywhere.ai/best-4k-monitors-singapore is an intent page: current-year title, product cards, /r/direct/{id} merchant hops (never raw merchant URLs), and an MCP snippet on the page. Use it as the human-readable counterpart of this watcher. Do not scrape the HTML for prices — call the search API.

Caveats (honest)

  • Catalog coverage flaps. A query that returns 20 hits at 15:00Z can return 0 at 16:00Z. Retry with backupQueries.
  • Currency is nested. US pages can leak USD into an SG search; filter currency == "SGD".
  • Affiliate clicks only fire if the product card rendered a /r/ href. If a page shows an empty state, the watcher still works — the HTML page is the SEO surface, the API is the agent surface.

Next

Wire this into Claude Desktop / Cursor via the BuyWhere MCP listing on Smithery. Tool name: search_products.

Questions: open an issue on BuyWhere/buywhere-mcp.

Top comments (0)