quick-commerce-mcp
by Hardik500
README.md
# π Quick Commerce MCP
Universal quick commerce aggregation via MCP - compare and order from Zepto, Blinkit, and Swiggy Instamart in one interface.
**Current verification scope:** Blinkit and Zepto search/cart flows were checked for
**1.5.1**. Checkout, payments, and order tracking were not reverified; Instamart was
not included in this regression check. See [flow status](#supported-platforms-and-flow-status)
before relying on a feature.
## β¨ Features
- **Multi-Platform Search**: Find products across all platforms simultaneously
- **Price Comparison**: See which app has the best deal
- **Smart Cart**: Automatically suggest optimal platform split
- **Item Resolution**: `resolve_items` ranks matches per platform; `add_to_cart` validates the cart (items, quantities, bill total) after adding
- **Itemised Bill**: Handling, late-night, GST and other fees listed separately in cart and order preview
- **Addresses**: `list_addresses` / `select_address` (retries once on flaky picker clicks)
- **Store Notices**: Closed/unserviceable stores and "Add address to proceed" are detected and reported with next steps
- **User Control (not reverified)**: Two-step `place_order` (preview token, then confirm); CVV read from `QC_CVV_<last4>`, never logged
- **Payment QR (not reverified)**: Zepto UPI QR support is implemented, including full-resolution cropping and an optional image viewer; successful payment is not guaranteed by generating a QR
- **OTP Handling**: Prompts for OTP when session expires
## Demo
[](https://youtu.be/XhLjgAiSnM8)
## π Quick Start
**Requirements:** Node 18+ and Google Chrome installed (the server drives your Chrome, no browser download). It runs locally over stdio, so it works in local MCP clients (Claude Desktop, Claude Code, Cursor, Windsurf), not hosted web apps.
**1. Add the server to your MCP client.** No install step; `npx` fetches it.
Claude Code:
```bash
claude mcp add quick-commerce -- npx -y quick-commerce-mcp
```
Claude Desktop, Cursor, Windsurf (add to the client's MCP config, then restart it):
```json
{
"mcpServers": {
"quick-commerce": {
"command": "npx",
"args": ["-y", "quick-commerce-mcp"]
}
}
}
```
**2. Set up from chat.** Ask your assistant, for example: "Save my phone 98XXXXXXXX and UPI me@bank, then log me in to Blinkit."
| Tool | What it does |
|------|--------------|
| `set_preferences` | Save phone, pincode, UPI ID, default payment method (`cod`/`upi`/`upi_qr`/`card`), `open_qr` (`"true"` opens each payment QR in an image viewer). No args = read. Empty string = clear. Stored in `~/.quick-commerce-mcp/preferences.json` |
| `check_login_status` | Is each platform logged in? |
| `request_otp` | Enter the phone number on the platform and send the OTP SMS (phone defaults to the saved one) |
| `submit_otp` | Complete login with the OTP you received |
| `logout` | Delete a platform's saved session (use before switching phone numbers) |
| `diagnose_flow` | Inspect or repair a broken browser flow (e.g. after a site changes its markup) |
| `list_addresses` / `select_address` | Pick the delivery address |
The verified shopping path for Blinkit and Zepto is `search_products` β `add_to_cart`
β `get_cart_summary` β `remove_from_cart` / `clear_cart`. `compare_prices` and
`resolve_items` have shared logic test coverage, but their full multi-platform flow
was not reverified. Checkout via `get_order_preview` / `place_order` remains outside this verified
shopping path. Blinkit history and latest-order lookup were live verified separately
on 2026-10-18; see [flow status](#supported-platforms-and-flow-status).
**Always pass `payment_method` explicitly to `place_order`.** Your saved default is a single value applied to every platform, and the same string means different things on different ones β `upi` is Blinkit-only, and Zepto needs `upi_qr` for a scannable QR. Relying on the default is the most common reason a payment method comes back unsupported.
Alternative login from a terminal (opens a browser; log in, then Ctrl+C):
```bash
npx -y -p quick-commerce-mcp quick-commerce-mcp-login zepto # also: blinkit, swiggy-instamart
```
Sessions are saved to `~/.quick-commerce-mcp/sessions/` and expire eventually; just log in again.
**3. Optional, for card payments:** export `QC_CVV_<last4>` in the client's `env` block. UPI needs no secret.
**From source:** `npm install && npm run build`, then point the client at `node /path/to/dist/index.js`.
**Tests:** install the test browser with `npx playwright install chromium`, then run `npm test` and `npm run lint`. To use an existing Chromium executable, set `QC_CHROME_PATH` when running the tests. The browser regression tests use local fixture storefronts; they do not use saved sessions or make live purchases.
## Supported platforms and flow status
Status for **1.5.1**, checked **2026-10-04**. Release verification ran **64 automated
tests** plus live Blinkit/Zepto checks against the packaged build. This is the scope
of those checks, not a guarantee that every product, address, store, or future site
update will behave identically.
- **Live verified**: exercised against the real platform during this release check.
- **Test covered**: exercised by unit tests or controlled browser fixtures, not a
dedicated live check of that scenario.
- **Not reverified**: implemented or previously reported working, but not checked
in this release. This does **not** mean it is known broken.
- **Unsupported / previously failed**: an explicit implementation gap or a prior
failure; a prior failure is not a fresh result for this release.
| Flow | Blinkit | Zepto | Swiggy Instamart |
|------|---------|-------|-----------------|
| Saved-session login | Live verified, including fresh-process restore | Live verified using the saved session | Not reverified |
| Fresh OTP login (`request_otp` β `submit_otp`) | Live verified; saved login survives restart | Not reverified | Not reverified |
| Product search (`search_products`) | Live verified | Live verified | Not reverified |
| ID-only add after cart navigation, with exact quantity (`add_to_cart`) | Live verified + test covered | Live verified + test covered | Not reverified |
| Repeating an add without duplicating the item | Live verified + test covered | Live verified + test covered | Not reverified |
| Cart summary and quantity readback (`get_cart_summary`) | Live verified + test covered | Live verified + test covered | Not reverified |
| Remove an item using its search label (`remove_from_cart`) | Live verified + test covered | Live verified + test covered | Not reverified |
| Clear a cart and confirm it stays empty after reload (`clear_cart`) | Live verified + test covered | Live verified + test covered | Not reverified |
| Out-of-stock handling as an individual item failure | Test covered | Test covered | Not reverified |
| Closed-store dialog dismissal and retained removed rows | Test covered | Not reverified | Not reverified |
| Bill parsing, pack-size matching, and validation helpers | Test covered | Test covered | Bill parsing test covered; live cart not reverified |
| Price-ranking/item-resolution helpers (`compare_prices`, `resolve_items`) | Shared logic test covered; full multi-platform flow not reverified | Shared logic test covered; full multi-platform flow not reverified | Full flow not reverified |
| Saved address listing (`list_addresses`) | Live verified after login and in a fresh process | Not reverified | Not reverified |
| Changing delivery address (`select_address`) | Not reverified | Not reverified | Not reverified |
| Checkout preview (`get_order_preview`) | Not reverified | Not reverified | Previously failed; not reverified |
| Order placement / payment (`place_order`, including COD) | Not reverified | Not reverified | Not reverified |
| Order history/status (`get_order_status`) | Live verified 2026-10-18; structured historical detail | Not reverified | Unsupported |
| Date-range item history (`get_order_history`) | Live verified; pagination and failure cases test covered | Live verified in development; multiple history pages | Unsupported |
| Live selector diagnosis/repair (`diagnose_flow`) | Not reverified | Not reverified | Not reverified |
### Purchase history (Blinkit, Zepto and BigBasket)
Use `get_order_history` to list ordered items and their historical prices for a
date range. For example:
```json
{
"platform": "blinkit",
"start_date": "2026-10-01",
"end_date": "2026-10-31",
"max_orders": 100
}
```
Dates are inclusive purchase dates in Asia/Kolkata, verified from merchant order
timestamps or dated order details, including the year. Recent today/yesterday labels resolve against the response
time in Asia/Kolkata. Active-order tracking links are supported too. Each order
includes status, item name, pack size, quantity,
charged `lineTotal`, derived `unitPrice`, item subtotal, fees and bill total.
A pack such as `4 x 750 ml` remains one product pack; ordered quantity is separate.
Discounted prices exclude crossed-out MRP. Item amounts must reconcile with the bill.
All three adapters navigate normal account pages and read the browser responses.
Zepto converts the merchant's paise amounts to rupees, combines its separate item
and bill page responses, and follows Load More. BigBasket flattens grouped
shipments and keeps active/recent/past pagination separate from any date-boundary
assumption. Blinkit and Zepto can stop after crossing a verified newest-first
purchase-date boundary; BigBasket exhausts its grouped history.
`complete: false` with `warnings` means orders could not be read/reconciled,
pagination did not progress, or an inspection limit was reached. Do not describe
such output as all orders. `max_orders` limits orders inspected (including
orders outside the range), defaults to 100 and accepts 1β200. Large scans may need
a longer MCP client timeout. The tool never reorders, changes the cart or submits
payment, and omits addresses and payment details.
Verified on 2026-10-18 through a fresh local stdio MCP process against the saved
Blinkit session. A running MCP process must reconnect after rebuilding to discover
changes to the tool schema. Set `platform` to `blinkit`, `zepto` or `bigbasket`.
Swiggy Instamart date-range history is not implemented.
Zepto and BigBasket development support is live verified through a fresh local
stdio MCP process: Zepto followed multiple history pages; BigBasket read the
available cancelled order through the existing Windows background-browser bridge.
BigBasket pagination beyond its available single page is fixture-tested.
Its native Linux browser failed in this environment; start the documented
`scripts/bigbasket-windows-bridge.mjs` from WSL and keep it running to share the
dedicated browser with MCP. No session or OTP is copied to an unrelated browser.
Cancelled/refunded orders retain their status and historical bill values; those
values are **not spending totals**. BigBasket returns `total` before wallet and
NeuCoins credits, `credits` separately, and `amountPayable` after those credits.
`refundTotal` is exposed when the merchant provides it. Historical item quantities
count ordered packs; BigBasket also reports `fulfilledQuantity` when available.
Item, bill, credit and refund parsing is fixture-tested, including waived charges,
discounts, wrong order identity, missing rows, scan limits and incomplete pagination.
### BigBasket development support (2026-10-04)
The working tree adds `bigbasket` to the MCP tools and interactive login helper.
It supports OTP login, search, ID-based cart additions with basket quantity
verification, individual removal, saved-address selection, and checkout preview.
Payment options are read from the Juspay iframe, and the preview reads the actual
payable total, including checkout discounts. Eligible wallet execution uses the
shared wallet controller. UPI QR generation uses a confirmed, one-shot handoff;
other payment execution and bulk clearing remain disabled. Checkout stops if BigBasket requests removal of
unavailable pre-existing items; it does not confirm that removal automatically.
After login, the connector reuses a confirmed address saved per platform. A
pincode selects a saved address only when the match is unique. Otherwise, the
login response lists the available saved addresses and asks the user to choose
with `select_address`; that confirmed choice persists across restarts. If a saved
choice disappears, the connector asks again instead of substituting another home.
Live stdio MCP verification completed OTP login in a dedicated native Windows
Chromium browser, reused the saved Bangalore Home address, increased an existing
biscuits item from one to two packs, and confirmed the persisted quantity by
reloading the basket. The original one-pack quantity was then restored. Checkout
preview returned the delivery address, payment options and actual payable total
of βΉ133.94 (items βΉ126.50, handling βΉ8, checkout discount βΉ0.56). No payment or
order was submitted. Live `prepare_payment` opened the UPI category through its
Juspay `article[role=none]` control without submitting anything. Collect/QR
transaction generation and authorization remain untested. Reconnecting a fresh MCP process reused the authenticated
browser and confirmed address without another OTP. Full browser restart login
restoration has not been verified live.
BigBasket's full listing service and product detail pages still return access
refusals in the authenticated native browser. **New-product search and additions
now work through the supported storefront autocomplete UI:** the adapter waits
for the rendered search input, uses the last visible input (the sticky header),
reads native suggestions and clicks their Add controls. It reports that these
are limited suggestions, not exhaustive catalog results. Refine the query when
a desired product is absent. The full listing remains a fallback when suggestions
are unavailable; a refusal is reported without requesting another OTP.
Live fresh stdio MCP verification searched Marie, returned ten variants, added
one Britannia Marie Gold Biscuits 190 g pack (ID 40001610, βΉ28.65), and reloaded
the basket to prove it persisted beside the existing biscuits. The two-item
subtotal was βΉ155.15. No payment or order was submitted. Search state is restored
after cart reads; new-product Add dispatches once and requires basket proof before
any subsequent quantity increment. Missing optional images never cause a locator
timeout. Fixtures cover autocomplete restoration, rejected writes, restored
basket IDs, unavailable-item protection, checkout authentication, address
extraction, iframe options and actual totals.
Actual MCP verification on 2026-10-04 also found that the already-connected
server was stale: it returned `Platform bigbasket not supported`, while a fresh
stdio connection to `dist/index.js` registered all 16 BigBasket tools. Restart
the MCP connection after building; rebuilding files does not update a running
Node process. `scripts/verify-bigbasket-mcp.mjs` exercises that fresh stdio
connection (newline-delimited tool requests on stdin, `quit` to close).
BigBasket uses native desktop browser APIs. Direct MCP launch now defaults to
headless (`QC_BIGBASKET_HEADLESS=false` explicitly enables visible recovery).
Live Windows and WSL headless tests on 2026-10-04 were rejected by the storefront;
changing the headless user-agent did not fix this. Login cookies remained valid
in the normal Windows browser. No new OTP or payment was sent during those tests.
The Windows bridge defaults to **background** mode: ordinary Chrome runs on a
private Windows desktop that is never switched into view. This is an invisible
local workaround, **not true headless** and not a cloud/Linux solution. The
launcher checks that Chrome created its window on that private desktop before
reporting ready. Live MCP checks verified saved login/address, native search,
cart contents, and checkout/payment options, including after reconnect/restart.
The MCP process, project, preferences and session files remain in WSL:
```bash
# From WSL, install the Windows browser runtime into the Windows user's home.
WINDOWS_HOME=$(wslpath -u "$(cmd.exe /d /c echo %USERPROFILE% | tr -d '\r')")
PLAYWRIGHT_HOST_PLATFORM_OVERRIDE=win64 \
PLAYWRIGHT_BROWSERS_PATH="$WINDOWS_HOME/.quick-commerce-mcp/browser-runtime" \
npx playwright install chromium
node scripts/bigbasket-windows-bridge.mjs
# Explicit recovery or headless experiments:
QC_BIGBASKET_BROWSER_MODE=visible node scripts/bigbasket-windows-bridge.mjs
QC_BIGBASKET_BROWSER_MODE=headless node scripts/bigbasket-windows-bridge.mjs
```
Stop the existing bridge before changing modes; one dedicated profile must not
have competing browser owners. Keep the bridge running while using MCP. It
publishes an owner-only loopback endpoint registry for automatic attachment and
never logs CDP frames or credentials. Optional `QC_WINDOWS_NODE_PATH` and
`QC_WINDOWS_BROWSER_PATH` specify WSL paths to Windows runtime executables;
the default Node runtime comes from the Codex desktop dependency cache. An
explicit `QC_BIGBASKET_CDP_URL` must be a plain loopback HTTP origin. This remains
a development helper, not a bundled npm installation feature. Claude's local
MCP connection can attach to it; remote clients cannot attach to your loopback
browser. Payment dispatch/redirects and fresh OTP login have not been verified
in background mode. Switch explicitly to visible recovery when the site requires
human interaction. MCP disconnect preserves the browser; logout clears its
cookies, origin storage and cached authenticated pages. Session files use
owner-only permissions. Rebuilding does not refresh an existing MCP process.
### Payment routing and user preferences (development)
All four apps share `get_payment_options`, `prepare_payment`, and
`set_payment_preferences`. The default order is UPI collect, UPI QR, wallets,
cards, then COD. A checkout advertising only βUPIβ must be inspected to determine
its actual modes; it does not prove collect or QR support. Disabled methods are
excluded. Missing UPI IDs, wallet providers, or saved-card choices are requested
before proceeding. Optional netbanking, Pay Later, and Pluxee options can also be
included in a custom order when advertised by the website.
Examples:
```json
{"order":["upi","wallet","card","cod"],"allow_fallback":true}
{"platform":"bigbasket","order":["wallet","upi_qr","cod"],"wallet_provider":"Amazon Pay"}
{"platform":"blinkit","order":["upi_collect"],"upi_id":"person@bank","allow_fallback":false}
{"platform":"zepto","order":["card","upi_qr"],"card_last4":"1234"}
```
Pass these to `set_payment_preferences`. Omitted methods are excluded from the
priority order. Per-app fields inherit global fields; `reset:true` removes that
scope. Preferences persist across restarts. Full card numbers, CVV, bank
credentials and payment OTPs are never stored in these preferences.
`get_payment_options` returns option IDs, observed availability, prerequisites,
a preferred option, and whether submission has an adapter or needs manual
completion. `prepare_payment` opens a unique safe category tab, heading or
recognized category button and
inspects sub-options. It does not click final payment/provider buttons, initiate
a collect request, generate a transaction QR, debit wallets, authorize cards or
place orders. Ambiguous/unknown controls require choosing in the app. Website
capabilities determine the available flow; app-only options are not fabricated.
Existing automated submission coverage remains:
| App | Adapter submission | Preparation / manual when advertised |
| --- | --- | --- |
| Blinkit | UPI collect, saved card, COD, eligible wallets | QR, unsupported wallets, new cards, other modes |
| Zepto | UPI QR, saved card, COD, eligible wallets | Collect, unsupported wallets, new cards, other modes |
| Instamart | COD, eligible wallets | UPI, unsupported wallets, cards, other modes |
| BigBasket | UPI QR handoff, eligible wallets (fixtures; live submission pending) | UPI collect, unsupported wallets, cards, COD, other modes |
`place_order` accepts `auto` or an omitted method for preference routing, but
only adapter-supported modes can submit. Explicit order approval remains
required; confirmation binds the same platform, method and UPI/card details.
No fallback or retry occurs after submission, failure, timeout or an uncertain
payment outcome. Resolve pending status or ask the user before another attempt.
New routing/preparation is covered by browser fixtures and fresh stdio MCP
integration tests. Live payment submission tests remain pending. BigBasket's
MCP login, existing-cart updates and checkout are verified via the Windows
browser bridge. Full listing-service search remains blocked; native autocomplete
search and new-product addition are verified through fresh stdio MCP.
Live read-only MCP verification reached Instamart's payment screen and returned
UPI, wallet, card, netbanking and pay-on-delivery options at the saved Bangalore
address. Zepto and Blinkit returned checkout-unavailable for their current
sessions/carts. None of these checks submitted a payment or order.
Wallet execution depends on the actual checkout UI. `get_wallet_status` opens
the safe Wallets category and lists native/linked provider balances and bill
coverage. App credit (bbWallet, Zepto Cash, Swiggy Money, Blinkit wallet) and
linked wallets such as Amazon Pay or MobiKwik use the shared controller when
a unique balance and checkbox/radio are visible. Provider-only buttons, missing
balances and linking/login requirements remain manual.
Use `place_order(payment_method: "wallet", wallet_provider: "bbWallet", ...)`
for the normal two-step approval flow. Preparation spends nothing. Confirmation
rechecks cart items, address, total, wallet identity and available balance;
balance equal to the bill is sufficient. Applied wallet credit and zero residual
payable must be observable before a separate final click. Linked-provider
selection can itself initiate payment and is tracked as a possible dispatch.
Authentication/pending/timeout outcomes never trigger retry, top-up, split
payment or fallback. Success requires a new order confirmation and order ID;
a click or balance change alone is insufficient.
Pending wallet attempts are recorded privately beside the platform session and
block another attempt across MCP restarts. An exclusively created `.pending`
marker guards overlapping processes. Reconcile unresolved attempts against
order history before an operator removes their pending journal/marker; logout
does not clear this protection.
Browser fixtures cover wallet success/failure on all four apps, linked balances
and provider authentication. **Actual wallet debits remain untested.** Live
BigBasket MCP inspection found bbWallet βΉ0 against a βΉ133.94 bill and PayZapp
without a usable linked balance/control. Both were refused for automatic
payment. No real order or wallet debit was submitted.
### Instamart development verification (2026-10-04)
The working-tree Instamart adapter now restores searches for ID-only adds after
cart navigation, includes pack size in product IDs, rejects ambiguous pack
matches, detects out-of-stock items, and proves quantity changes against both
the counter and completed cart writes. Removed rows showing `ADD` are excluded
from the cart. OTP submission waits for authenticated state before saving, and
checkout preview distinguishes `Select Address` from `Proceed to Pay`.
These changes have 13 browser fixture regressions in
[src/instamart-flows.test.ts](src/instamart-flows.test.ts), covering inline and
variant adds, repeat adds, delayed/debounced saves, removal, clearing, rejected
writes, session restoration, and checkout preview. This extends the working
tree's coverage; the **1.5.1 release table above remains historical**.
Live checks restored the saved session, returned 20 search results, read the
cart, and removed a test item while preserving the original cart. Full live
quantity/repeat-add verification was blocked by Instamart's HTTP-200 application
error `User Addresses not found for user`. The adapter now reports that as a
failure with `list_addresses` / `select_address` recovery. Select a valid delivery
address before rerunning the live cart regression; successful full live parity
has **not** been established. Payments and order history remain outside these
checks.
Run `npx tsx scripts/test-instamart-addtocart.ts` for the live cart regression
after configuring the address. It asserts outcomes and restores the original
cart rather than clearing pre-existing items. `QC_INSTAMART_TEST_QUERY` can
override the default test search (`amul milk`).
### Known limitations and recovery
- **Payments were deliberately excluded from the 1.5.1 regression checks.** Older
Blinkit UPI and Zepto QR demonstrations do not establish current reliability.
Do not treat a QR or a returned success message as proof of payment or a confirmed
order; check the platform's own app/order history.
- **Instamart checkout preview previously failed**, and this release did not retest
that failure. Instamart order-status retrieval is not implemented. Its older
search/cart results have not been reverified either.
- **Configured payment modes are not a live verification promise:** Blinkit
accepts `cod`/`upi`/`card`, Zepto `cod`/`upi_qr`/`card`, and Instamart `cod`.
The working tree also supports eligible native and linked `wallet` checkout
on Blinkit, Zepto, Instamart and BigBasket through the shared wallet controller.
Real wallet debits remain untested. New cards, netbanking and Pay Later remain
manual; platform eligibility can disable a method for a particular cart.
- **Older incomplete Blinkit sessions need one fresh OTP login.** Version 1.5.1
waits for authenticated client state before saving; a leftover legacy cookie
alone no longer counts as a logged-in account.
- **Cart actions require confirmation where prompted.** Repeat adds are treated
as already present, not as instructions to add the requested quantity again.
After removal/clearing, read `get_cart_summary` to confirm the result. Live
verification used only test items and restored both carts to empty.
- **Stock, store hours, and address eligibility remain platform-controlled.** A
closed/unserviceable notice is not a promise that checkout can proceed. Browser
markup and bot checks can change; inspect a broken flow with `diagnose_flow`
rather than assuming an earlier verification still applies.
The automated browser regressions are in
[src/platform-flows.test.ts](src/platform-flows.test.ts); shared logic tests are in
[src/logic.test.ts](src/logic.test.ts). They use fixtures, not live accounts or
purchases. Passing them does not certify checkout or payment flows.
See [AUTHENTICATION.md](AUTHENTICATION.md) for login troubleshooting - rejected OTPs, missing delivery locations, and how to log in by hand when the automated flow won't cooperate.
## π Usage Examples
### Search for a product
```
"Find Coke Zero 6-pack"
"Where is milk cheapest right now?"
"Search for Maggi noodles on Zepto and Swiggy"
```
### Build a cart
```
"Add to cart: 1L milk, 6 eggs, bread"
"Show me the best platform for these items"
```
### Compare before ordering
```
"Compare prices for my cart"
"What's the cheapest way to get these items?"
```
### Pay by UPI QR
This feature is implemented but **not reverified for 1.5.1**. The example describes
the intended flow, not a guarantee of payment success.
```
"Pay for my Zepto cart with a UPI QR"
```
The first call previews the order and stops. The second generates the QR,
which is valid for a few minutes. It comes back cropped to the QR itself at full
resolution, and the file path is always included. Run
`set_preferences(open_qr: "true")` once to have it open in an image viewer
automatically β see [below](#why-a-payment-qr-opens-in-a-separate-viewer) for
why that is worth turning on.
> Zepto only: pass `payment_method: "upi_qr"` explicitly. Your saved default is
> used for every platform, and `upi` means something different on Blinkit than
> it does on Zepto.
## π Security
- **No card data stored**: CVV is read from the `QC_CVV_<last4>` env var only, and is never written anywhere. What *is* written locally, all under `~/.quick-commerce-mcp/`: `preferences.json` (phone, pincode, UPI ID, default payment method, `open_qr`), session cookies in `sessions/`, repaired selectors in `flows/`, and payment QR images in `sessions/`
- **A payment QR is saved to disk**: a UPI QR is a scannable payment instruction β it carries the payee VPA, the amount and a transaction reference. It is written to `sessions/` so you can open it full size, at mode `0600`. Deleting it after you pay is up to you
- **OTP required**: You always supply the OTP yourself
- **Confirm before order**: Preview shown, you confirm final purchase
- **Session isolation**: Each platform login is separate
- **Payment QRs are never auto-opened unless you ask**: `set_preferences(open_qr: "true")` opts in to launching an image viewer when a QR is generated. It is off by default because it starts a process on your machine
### Why a payment QR opens in a separate viewer
MCP clients render tool-result images inside a short container with its own
scrollbar β Claude Desktop's `Place order` block is one β so a QR sent inline is
clipped across the fold and will not scan from the chat. The protocol has no way
for a server to change that layout, so the full-resolution PNG is always written
to `~/.quick-commerce-mcp/sessions/` and its path returned in the message. Set
`open_qr` to `"true"` to have it also launch in your image viewer automatically.
## ποΈ Architecture
Each platform is driven through a single shared browser page, so tool calls that
touch the **same** platform are serialised automatically β you can fire several at
once and they queue rather than collide. Calls against **different** platforms run
in parallel, so comparing three platforms is still concurrent.
```
βββββββββββββββ βββββββββββββββ βββββββββββββββ
β Claude ββββββΆβ MCP Server ββββββΆβ Playwright β
β /Cursor βββββββ (this repo) βββββββ Automation β
βββββββββββββββ βββββββββββββββ ββββββββ¬βββββββ
β
βββββββββββ΄βββββββββββ
β Zepto | Blinkit | β
β Swiggy Instamart β
ββββββββββββββββββββββ
```
## π Status
See the [versioned flow-status table](#supported-platforms-and-flow-status) for the
single source of verification scope and known limitations. Implemented tools and
older demonstrations are not a claim of current end-to-end support.
## π€ Contributing
This is a personal project. Open to suggestions!
Use Node.js 24, run `npm ci`, and install fixture browsers with
`npx playwright install chromium`. Run `npm run setup:hooks` once per checkout.
The pre-commit hook runs `npm run check` (the full test suite, lint, and browser
helper syntax checks, and the high-severity dependency audit), refuses unstaged
code changes, and checks that generated
`dist/` files are staged. GitHub Actions runs the same checks on pushes and pull
requests using the committed dependency lockfile.
Tests cover cart persistence and rejected writes, OTP/session restoration,
saved-address selection, MCP reconnect/handshake and preference persistence,
payment preferences and category navigation, and native
and linked wallet preparation/confirmation across all four platforms. They use
local browser fixtures and never charge a real account. Live payment execution
still requires separate verification; passing fixtures do not establish support
for every current merchant checkout variant.
## β οΈ Disclaimer
This is an unofficial project, not affiliated with Zepto, Blinkit or Swiggy. It automates a real browser logged in as you. Automating these sites may violate their Terms of Service and can get your account rate-limited or blocked; you use it at your own risk.
`place_order` spends real money. It only runs after a two-step confirmation, but always check the order summary your assistant shows you before approving. Sessions (login cookies) are stored unencrypted in `~/.quick-commerce-mcp/sessions/`; keep that folder private.
---
**Created**: 2026-02-12
### BigBasket UPI QR handoff
The observed BigBasket Juspay desktop UPI screen offers **Generate QR Code**.
It has no UPI-ID/phone input, and the bank handles shown underneath are suggestions,
not a saved UPI account. `prepare_payment` opens this screen without generating a
transaction. `place_order(payment_method: "upi_qr")` prepares a confirmation token;
the confirmed second call generates once and returns the QR image and private file
for scanning with any UPI app. It reports **pending**, never a paid/confirmed order.
A shared wallet/UPI attempt journal prevents duplicate generation or fallback after
an uncertain result, including across MCP restarts. Reconcile the attempt in the
merchant app before clearing that guard. Cart, address and payable amount must
still match the approved preview. Live QR generation was verified on 2026-10-04: Juspay returned a GIF QR,
normalized from native image pixels to PNG and successfully decoded as a UPI payment for
βΉ162.59 INR to INNOVATIVE RETAIL CONCEPTS PRIVATE LIMITED. The adapter now checks
decodability, exact amount, currency and merchant before returning a QR as ready.
The image and private full-resolution file are returned to the client; no payment
was made. Fixtures include GIF extraction and mismatched/invalid payloads. Actual
payment completion remains untested. UPI collect is not
offered in the observed screen and is not enabled for BigBasket.
### Post-payment tracking
Confirmed `place_order` calls now persist the payment attempt before dispatch,
then inspect merchant order-detail redirects without leaving the payment screen.
`get_payment_status(platform, wait_ms: 30000)` watches the current attempt across
all four platforms, including new tabs. It distinguishes confirmed orders, failed
payments, cancellation, pending and unknown outcomes. An order-history URL alone
never proves success, and a confirmed order is marked paid only if the merchant
explicitly shows payment completion. Baseline old orders, unrelated merchant
hosts, history lists, conflicting status text and mismatched amounts cannot count
as completion. Tracking survives MCP restarts. A matching terminal outcome
archives and releases the wallet/UPI attempt guard without retrying a payment.
No navigation, payment submission or automatic fallback happens during watching.
Redirect tracking is fixture-tested on all four apps; the BigBasket unpaid QR
redirect and merchant cancellation were observed live. Paid completion still
requires the final user-controlled payment test.
### BigBasket blocked-browser recovery (issue #1)
BigBasket may refuse the default headless browser even with a correct OTP.
Logging in to your normal browser or an incognito window does **not** log MCP
in: it uses a separate profile. Do not keep requesting OTPs on a blocked page.
Install the browser once with `npx playwright install chromium`. **Fully quit
Claude Desktop or stop the MCP server first**, so its headless browser releases
the dedicated profile. Then keep a separate terminal running:
```sh
npx -y --package=quick-commerce-mcp quick-commerce-mcp-bigbasket-browser
```
Reopen Claude Desktop (or reconnect your MCP client) after the helper reports
ready. MCP automatically attaches to that dedicated browser. Ask the assistant
to check BigBasket login, then supply your phone number, pincode and a fresh OTP
only if requested. Keep the terminal running throughout shopping.
On native Windows this command defaults to an invisible isolated desktop.
On macOS/Linux it opens a visible browser; true headless access is not assured.
If a challenge requires manual interaction, stop the helper and rerun it with
`--visible`. Complete the check **in that dedicated browser**, then reconnect MCP.
Use the same OS account and environment for the helper and MCP; a Windows
helper does not publish its endpoint into a WSL home directory. WSL deployments
must use the Windows bridge described in the README. `QC_CHROME_PATH` can select
an installed Chrome executable instead of Playwright Chromium. The background
helper does not require Codex or a Codex-managed Node installation.
This recovery command is available starting with **1.6.1**, or from the
current source checkout (`node scripts/open-bigbasket-browser.mjs`). Do not
assume an older cached `npx` package includes it. Fresh Windows background startup, MCP-compatible browser attachment and the
logged-out BigBasket login button were verified with a temporary profile on
2026-10-05. The isolated desktop now starts on a blank page before MCP navigates,
avoiding the fresh-profile attachment timeout observed when it launched directly
into BigBasket. A clean native Windows installation of the candidate tarball was also tested
with freshly downloaded Chromium, without QC_CHROME_PATH or a custom CDP URL.
MCP sent one OTP, completed login, and returned the saved Bangalore address.
A fresh MCP process preserved the pending OTP screen; after verification, a
complete browser restart plus another fresh MCP process remained logged in
without requesting another OTP. One separate clean run timed out waiting for
login controls, so initial site loading can still fail. These checks apply to
the Windows recovery route, not true headless browsing or all operating systems.
Actual payment submission remains untested in this recovery route.
### Linux and macOS recovery verification (2026-10-05)
A clean candidate tarball installation was checked in Ubuntu 24.04 WSL x86-64
using Node 24 and freshly downloaded native Linux Chromium (Playwright 1.63.0).
No Windows executable, Windows bridge, `QC_CHROME_PATH`, or custom CDP URL was
used. The ordinary headless MCP route was blocked by BigBasket. The recovery
helper on an Xvfb virtual display started successfully, published a private
loopback endpoint, attached through a fresh stdio MCP connection, and reached
the login phone form. Profile permissions were `0700`; endpoint permissions
were `0600`. BigBasket then rejected the single OTP request with HTTP 400 and
did not show an OTP screen. Linux login completion and persistence are therefore
**not verified**. The status alone does not establish why the server rejected it.
On Linux, an Xvfb display keeps headed Chromium off the user desktop:
```sh
# Stop the existing MCP server first. On Ubuntu, install xvfb and xauth if absent.
xvfb-run -a npx -y --package=quick-commerce-mcp quick-commerce-mcp-bigbasket-browser
```
Keep the wrapper running while MCP attaches. This is headed Chromium on a
virtual display; access and login still depend on BigBasket's site checks.
The recovery executable requires **1.6.1 or later**, or a source checkout;
1.6.0 does not expose that executable.
macOS uses the native Playwright Chromium executable and a dedicated visible
browser, without the Windows PowerShell desktop helper. Playwright currently
supports macOS 14 or later; use a supported Node release such as Node 24
([system requirements](https://playwright.dev/docs/intro#system-requirements)).
The validation workflow now runs the build and browser regressions on both
Ubuntu and a native macOS runner. Fixture tests do not establish live BigBasket
login acceptance. A fresh Mac login still needs on-device verification.
TDQS
B3.2/5.0
Scored across 1 tool
Disambiguation5/5
With only one tool, there is no risk of confusion between tools. The unique tool has a clear purpose.
Naming Consistency5/5
The sole tool 'get_cart_summary' follows a clear verb_noun pattern, which is consistent and descriptive.
Tool Count1/5
A single tool for a commerce server is far too few. Typical commerce operations require multiple tools (e.g., add/remove items, checkout), so this is an extreme mismatch.
Completeness1/5
The tool only retrieves cart summary, lacking any means to modify the cart, browse products, or complete purchases. This is severely incomplete for the stated domain.
Maintenance
ActivityMaintained
ResponsivenessNo issues