mon-marche-mcp
# mon-marche-mcp
An [MCP](https://modelcontextprotocol.io) server that lets an AI assistant search the
[mon-marché](https://www.mon-marche.fr) catalog and build a grocery basket from a few
instructions. It is a thin, pure-HTTP client over mon-marché's internal API (the Keplr
commerce platform) and Constructor.io search — **no browser automation**.
It deliberately **stops at the cart**: there is no checkout or payment tool. You review the
basket and pay yourself on the website.
## Tools
| Tool | Purpose | Auth |
|------|---------|------|
| `search_products` | Search the catalog (name, slug, price, bio/anti-gaspi) | none |
| `get_product` | Resolve a slug to its article id + SKU | none |
| `add_to_cart` | Set the quantity of one product (by slug) | sign-in |
| `add_many_to_cart` | Build a whole basket in one call | sign-in |
| `view_cart` | Show lines and total | sign-in |
| `remove_from_cart` | Remove a line by article id | sign-in |
| `clear_cart` | Empty the cart (does not delete it) | sign-in |
| `my_usual_products` | List most frequently ordered products | sign-in |
| `list_delivery_slots` | List bookable delivery slots for the saved address | sign-in |
| `set_delivery_slot` | Attach a slot — **creates the cart** | sign-in |
## Order flow
A cart can only hold products **once a delivery slot is attached**. Authentication is
automatic from the env credentials (it uses a bearer token *and* a session cookie). Follow
this sequence:
1. **Find products** — `my_usual_products` (frequently ordered) and/or `search_products`.
2. **Pick a slot** — `list_delivery_slots`, choose a `slotId`.
3. **Create the cart** — `set_delivery_slot(slotId)`. This creates the cart (or updates the
slot on an existing one) and is **required before adding products**. Skipping it makes
`add_to_cart` / `add_many_to_cart` fail with `404 "Le panier est introuvable"`.
4. **Add products** — `add_to_cart` / `add_many_to_cart` (by slug).
5. **Confirm** — `view_cart`.
Checkout and payment are intentionally **not** automated — review and pay on the website.
## Setup
```bash
npm install
cp .env.example .env # fill in MM_EMAIL / MM_PASSWORD
npm run build
```
The account in `.env` must already have a delivery zone/address configured on the website —
the cart is tied to that.
## Run
```bash
npm run dev # tsx, reads .env
# or
npm run build && npm start
```
### Register with an MCP client
```json
{
"mcpServers": {
"mon-marche": {
"command": "node",
"args": ["/absolute/path/to/mon-marche-mcp/dist/server.js"],
"env": {
"MM_EMAIL": "you@example.com",
"MM_PASSWORD": "your-password"
}
}
}
}
```
## Configuration
| Var | Required | Default |
|-----|----------|---------|
| `MM_EMAIL` | for cart ops | — |
| `MM_PASSWORD` | for cart ops | — |
| `MM_BASE_URL` | no | `https://www.mon-marche.fr` |
| `MM_CONSTRUCTOR_KEY` | no | public key from the site bundle |
## Notes & caveats
- **No payment.** By design. The assistant fills the cart; you check out manually.
- **Unofficial API.** mon-marché has no public API; this calls the same endpoints the
website uses. It may change without notice — keep usage personal, single-account, and
low-rate, and review your basket before paying. This may run against the site's terms of
service; use at your own discretion.
- **Cart shape.** The authenticated cart is normalized in `src/client.ts` (`normalizeCart`).
The upstream API uses **cents**; tools expose **euros**. Line quantity comes from
`quotation.count`, unit price from `itemPrice`, cart total from
`price.quotation.preauthorization` (includes shipping + prep fee).
- **`clear_cart` only empties.** There is no endpoint to fully delete a cart — `DELETE
/api/cart` clears the contents but the cart shell and its delivery slot persist for the
period. So the `GET /api/cart` → 404 ("no cart") state cannot be reproduced once a cart
exists; `set_delivery_slot` then just updates the slot instead of creating a new cart.
## Verified API contract
Reverse-engineered from the site's JS bundle and confirmed live. Base
`https://www.mon-marche.fr`.
| Operation | Call |
|-----------|------|
| Sign in | `POST /api/auth/signin` `{email, password}` → bearer token in body + `Set-Cookie`. Send **both** `Authorization: Bearer <t>` and `Cookie` on later calls. |
| Search | `GET ac.cnstrc.com/search/{q}?key=<MM_CONSTRUCTOR_KEY>&c=ciojs-client-2.45.0&...` (no auth) |
| Resolve product | `GET /api/articleDetailBySlug/{slug}` → `{ id, sku, name }` |
| Usual products | `GET /api/account/top-products` → `{ items: [...] }` |
| Saved addresses | `GET /api/account/addresses` → `{ items: [...] }` |
| Delivery slots | `POST /api/addresses/deliverySlots2` `{ postalCode, countryCode, location }` → `{ deliveryZones: [{ name, deliverySlots: [{ id, from, to, orderUntil, isExpired, isFull }] }] }` |
| Create/set delivery | `PATCH /api/cart/delivery2` `{ timeSlot, delivery: { note, address, deliveryZone }, reasonForChange }` — **creates the cart** |
| Add one | `PATCH /api/cart/product` `{ product: { id, quantity } }` |
| Add many | `PATCH /api/cart/products` `{ products: [{ id, quantity }] }` |
| View cart | `GET /api/cart` |
| Empty cart | `DELETE /api/cart` (empties only) |
| Payment | `PUT /api/cart/createPaymentIntent` — **never call; out of scope** |
## License
[MIT](./LICENSE). Note: this license covers only this project's code. It grants no rights to
mon-marché's API, data, or trademarks, and does not override the site's terms of service.
TDQS
Scored across 10 tools
Each tool has a clear, distinct purpose: search, product lookup, cart operations (add, remove, clear, view), delivery slot management, and usual products. Even the two add-to-cart tools serve different needs (single vs bulk), well explained in descriptions.
Most tools follow verb_noun pattern (e.g., search_products, view_cart), but 'my_usual_products' breaks the imperative style, being a descriptive possessive phrase. Otherwise consistent snake_case and verb use.
10 tools cover the full cycle of a grocery ordering workflow: product search, cart management, delivery slot selection, and reordering. No redundancy, each tool earns its place.
Covers core shopping steps (search, cart, slot) but lacks checkout or payment tools, which are essential for a complete ordering flow. Without them, the set feels incomplete for real-world use.