Skip to main content
Glama
README.md
# RappiMCP

<!-- mcp-name: io.github.bgirardi99/rappi-mcp -->

```
Program : RappiMCP
Author  : Bastian Girardi
Date    : April 2, 2026
Purpose : Built to automate grocery and delivery purchases on Rappi Chile
          through Claude — eliminating the need to manually browse the app
          when you just want to tell an AI what you need and have it ordered.
```

---

An MCP (Model Context Protocol) server that gives Claude full control over Rappi Chile — browse stores, search products, manage the cart, and open checkout — all through natural language.

## How it works

The server is built with [FastMCP](https://github.com/jlowin/fastmcp) and exposes tools that Claude can call. It communicates with Rappi via their internal web API (`services.rappi.cl`), authenticated with tokens extracted directly from a Chrome browser session using the Chrome DevTools Protocol (CDP).

```
Claude ──tools──▶ rappi_mcp.py ──HTTP──▶ services.rappi.cl
                       │
                       └──CDP──▶ Chrome (auth + checkout navigation)
```

## Setup

### 1. Install dependencies

```bash
pip install -r requirements.txt
```

### 2. Configure Claude Code

Add this to your Claude Code MCP settings (`claude_desktop_config.json` or equivalent):

```json
{
  "mcpServers": {
    "RappiMCP": {
      "command": "python",
      "args": ["C:/path/to/RappiMCP/rappi_mcp.py"]
    }
  }
}
```

### 3. Authenticate

On first use, call `rappi_auth` to extract your Rappi credentials from Chrome and save them to `.env`. No manual token copying needed.

## Authentication

Rappi uses rotating JWT tokens stored as browser cookies. The auth flow:

1. **`rappi_auth(use_existing_chrome=False)`** — launches a dedicated Chrome window at rappi.cl (on CDP port `9223`) and waits up to 2 minutes for you to log in
2. Once logged in, it reads three cookies via CDP:
   - `rappi.data` (Base64 JSON) → `user_id`
   - `deviceid` → `device_id`
   - `rappi_refresh_token` → `refresh_token`
3. Exchanges the refresh token for a fresh `access_token` via `POST /api/rocket/refresh-token`
4. Writes all four values to `.env`

**`rappi_auth(use_existing_chrome=True)`** (default) — attaches to an already-running Chrome with `--remote-debugging-port=9223` and reads cookies immediately (you must already be logged in).

### Token refresh

`RappiClient` handles token rotation automatically. If any API response includes the header `x-refresh-token: true`, it transparently refreshes both tokens and retries the request.

### Environment variables

```
RAPPI_ACCESS_TOKEN   — Bearer token for API calls
RAPPI_REFRESH_TOKEN  — Used to obtain new access tokens
RAPPI_DEVICE_ID      — UUID identifying the browser session
RAPPI_USER_ID        — Numeric Rappi user ID
```

See `.env.example` for the expected format.

## Tools reference

### `rappi_auth(use_existing_chrome=True)`
Extract credentials from Chrome and write them to `.env`. Set `use_existing_chrome=False` to launch a fresh Chrome window and wait for login.

---

### `rappi_reload()`
Reload tokens from `.env` and restart the API client — without restarting the MCP server. Useful after manually editing `.env`.

---

### `rappi_list_stores(category, query, limit)`
List stores available for delivery near your saved address.

| Param | Default | Description |
|-------|---------|-------------|
| `category` | `"market"` | Store category: `"market"`, `"restaurant"`, `"farma"`, `"licores"`, `"express-big"`, or any Rappi store_type slug |
| `query` | `""` | Optional name filter |
| `limit` | `50` | Max results |

Returns: `store_id`, `name`, `store_type`, `lat`, `lng`, `eta`, `shipping_cost`.

> `store_id` is used by `rappi_search_products`. `store_type` is used by all cart tools.

---

### `rappi_get_store(store_id)`
Look up metadata for a specific store by its numeric ID. Returns `store_type` (the slug needed for cart operations).

---

### `rappi_search_products(store_id, query, size, offset)`
Search products within a store. Queries in Spanish work best.

| Param | Default | Description |
|-------|---------|-------------|
| `store_id` | required | From `rappi_list_stores` |
| `query` | required | Search term (e.g. `"cerveza"`, `"preservativos"`) |
| `size` | `40` | Results per page (max 40) |
| `offset` | `0` | Pagination offset |

Returns: `composite_id`, `name`, `trademark`, `price`, `real_price`, `discount`, `quantity`, `unit_type`, `sale_type`, `in_stock`.

> Use `composite_id` and `sale_type` when adding to cart.

---

### `rappi_get_cart(store_type)`
Read the current cart contents for a given store. Returns a list of items with `composite_id`, `units`, `sale_type`, `name`, `price`.

---

### `rappi_add_to_cart(store_id, store_type, composite_id, units, sale_type)`
Add a product to the cart (or increment its quantity if already present). Internally: reads current cart → appends/increments → writes back via a full PUT.

---

### `rappi_remove_from_cart(store_id, store_type, composite_id)`
Remove a specific product from the cart by its `composite_id`.

---

### `rappi_clear_cart(store_id, store_type)`
Empty the entire cart for a store.

---

### `rappi_checkout(store_type)`
Navigate Chrome to the checkout page for a store. Each store has its own checkout URL:

```
https://www.rappi.cl/checkout/{store_type}
```

Examples:
- `turbo_rappidrinks_nc` → `rappi.cl/checkout/turbo_rappidrinks_nc`
- `cruz_verde_rappido_nc` → `rappi.cl/checkout/cruz_verde_rappido_nc`
- `lider` → `rappi.cl/checkout/lider`

> Rappi does not support consolidated multi-store checkout. Each store cart must be checked out separately.

## Typical flow

```
1. rappi_auth()                          # authenticate once
2. rappi_list_stores(category="farma")   # find pharmacies
3. rappi_search_products(store_id, "preservativos")  # search
4. rappi_add_to_cart(store_id, store_type, composite_id, 1, "U")
5. rappi_checkout(store_type)            # open checkout in Chrome
```

## File structure

```
RappiMCP/
├── rappi_mcp.py      # MCP server — tool definitions, auth logic, CDP helpers
├── rappi_client.py   # Rappi API client with automatic token refresh
├── requirements.txt  # Python dependencies
├── .env              # Credentials (git-ignored)
└── .env.example      # Credentials template
```

## Notes

- The server uses CDP port `9223` (not the default `9222`) to avoid conflicts with other tools
- Checkout navigation also uses CDP — the same Chrome instance used for auth
- `store_type` slugs come from `rappi_list_stores` and must be passed exactly as returned (e.g. `"turbo_rappidrinks_nc"`, not `"turbo"`)

TDQS

A4/5.0

Scored across 12 tools

Disambiguation5/5

Each tool targets a distinct operation: auth, store lookup, product search, cart CRUD, address management, checkout, and token reload. No overlaps or ambiguity.

Naming Consistency5/5

All tools follow a uniform 'rappi_verb_noun' snake_case pattern (e.g., rappi_add_to_cart, rappi_clear_cart). Verbs are descriptive and consistent across the set.

Tool Count5/5

12 tools cover the essential interactions for a Rappi integration (auth, store browsing, product search, cart management, addresses, checkout, maintenance). Not too many, not too few.

Completeness4/5

The surface covers the core workflow: search, cart operations, address management, and checkout initiation. Missing a direct order placement API (likely an external limitation) but otherwise complete for agent-based shopping.

Maintenance

ActivityInactive
ResponsivenessNo issues