Skip to main content
Glama
DENNISDGR

efood-mcp

by DENNISDGR
README.md
# efood-mcp

An **unofficial** [Model Context Protocol](https://modelcontextprotocol.io) server for the
**efood.gr** consumer app API. It lets an MCP client (Claude Code, Claude Desktop, etc.) discover
restaurants, browse menus, build a cart, and place orders on your behalf.

> ⚠️ **Read the [Disclaimer](#disclaimer) before using this.** This talks to efood's private,
> undocumented app API. The account/order features are not sanctioned by efood and using them may
> violate efood's Terms of Service. `place_order` spends real money.

## What this is (and isn't)

efood has two very different APIs:

| API | Who it's for | This project? |
| --- | --- | --- |
| **Partner API** (`developer-qc.e-food.gr`, `efood.partner.deliveryhero.io`) | Shops/vendors selling *on* efood — manage catalog, incoming orders, promotions | ❌ Not this. It has no way to browse restaurants or order as a customer. |
| **Consumer app API** (`api.e-food.gr`) | The efood mobile app / website — browse and order as a customer | ✅ This. Unofficial/undocumented. |

## Tools

**Discovery — no login required**
- `search_restaurants` — restaurants delivering to a `lat`/`lng` (or geocoded `address`), with
  filters (`open_now`, `query`, `cuisine`, `min_rating`, `has_offers`, `max_delivery_fee`,
  `max_minimum_order`, `vertical`, `favorites_only`) and `sort`. When credentials are configured,
  results include an `is_favorite` flag; `favorites_only:true` returns only your favorited places
  that deliver to that location (favorites are location-scoped — efood has no global favorites list,
  so this uses the listing's server-side `filters={"is_favorite":true}`).
- `get_restaurant_menu` — full menu (categories + priced items), hours, offers, discounts. Each item
  carries an `available` flag (false = out of stock / "Μη διαθέσιμο"; such items fail order
  validation). Pass `available_only: true` to drop out-of-stock items and empty categories.
- `get_menu_item_options` — customization/variation options for an item.

All three discovery tools (and `add_item`) accept an optional **`lang`** (e.g. `"en"`, `"el"`).
efood localizes menu/option names via `Accept-Language`; `EFOOD_LANG` sets the default (`en`), and
`lang` overrides per call — set it to match the conversation so option names line up with search
terms. Codes and prices are identical across languages.

**Account — requires authentication**
- `get_addresses` — your saved delivery addresses (for the `address_id` used at checkout).
- `get_payment_methods` — your saved payment methods as opaque tokens (no card numbers).
- `get_order_history` — your previous orders (most recent first) with restaurant, date, total,
  payment, status, and items; optional `restaurant_id` filter for re-ordering the usual.
- `get_order_status` — status of an existing order.

**Cart — efood's server-side basket (there is no local cart)**
Every cart tool takes a `restaurant_id` and operates on that shop's persistent basket — the one shown
in the efood app. `add_item`/`remove_item` read the basket, change it, and re-persist it; no address
is needed until checkout.
- `add_item` — add a customizable item by naming its options: `item_code` + `options` (names or
  codes), e.g. `["traditional pita","tomato","tzatziki"]`. Resolves names→codes, auto-fills required
  choices (bread / all-vs-choose), computes the price, rejects out-of-stock. `dry_run` previews;
  unknown names return the option catalog. `lang` = the language of the option names you pass.
- `get_cart` — read the basket: indexed line items with options, quantities, prices, and total.
- `remove_item` — remove a line by its `index` (from `get_cart`); removing the last line clears it.
- `clear_cart` — delete the shop's basket entirely (removes it from the app).

**Checkout — real purchase**
- `place_order` — submits the shop's basket as a **real, paid** order. `confirm:false` (default)
  validates against the delivery `address_id` and returns a summary (items, total, fees, min-order);
  `confirm:true` submits. Cash on delivery or a saved payment token only (no card entry).

## Setup

Requires **Node.js 20+**.

```bash
npm install
npm run build
```

Copy the env template and fill it in:

```bash
cp .env.example .env
```

- Discovery tools need **no** configuration.
- Account/cart/checkout tools need credentials in `.env`:
  - `EFOOD_EMAIL` + `EFOOD_PASSWORD` — the server logs in programmatically and caches the session.
  - or `EFOOD_SESSION_ID` — a session id you captured yourself (takes priority; see below).

### How credentials are handled

Your password is read only from your local `.env`/environment and is sent **only** to efood's own
`/api/v1/user/login` endpoint to obtain a session id. It is never logged, printed, or sent anywhere
else. The resulting session id is cached in memory and sent as the `x-core-session-id` header.

If programmatic login is blocked (e.g. device verification), log in yourself in the efood app or
website, copy the `x-core-session-id` value from a request in your browser's dev tools (Network
tab), and set it as `EFOOD_SESSION_ID`.

## Use with Claude Code

Use the absolute path to the built `dist/index.js` in this project:

```bash
claude mcp add efood -- node /absolute/path/to/efood-mcp/dist/index.js
```

Or add to a project `.mcp.json`:

```json
{
  "mcpServers": {
    "efood": {
      "command": "node",
      "args": ["/absolute/path/to/efood-mcp/dist/index.js"]
    }
  }
}
```

## Quick check (no credentials needed)

Inspect the tools interactively:

```bash
npx @modelcontextprotocol/inspector node dist/index.js
```

Then call `search_restaurants` with `lat=37.9838`, `lng=23.7275` (central Athens) — you should get a
list of restaurants. `get_restaurant_menu` with one of the returned `id`s returns its menu.

## Typical flow

`search_restaurants` → `get_restaurant_menu` → `add_item` … → `get_cart` → `get_addresses`
→ `place_order` (preview, `confirm:false`) → `place_order` (`confirm:true`).

## Disclaimer

- **Unofficial & undocumented.** `api.e-food.gr` is efood's private app API. It may change or break
  at any time, rate-limit you, or flag/suspend your account. Use at your own risk.
- Most of the API has been verified live: discovery (search, menus, options), authentication,
  addresses, payment methods, order history, favorites, availability, and the full server-side cart
  flow (`add_item` / `get_cart` / `remove_item` / `clear_cart`) including order validation. The paths
  **not** yet exercised are the final real-order submission (`place_order` with `confirm:true`) and
  order-status lookup — their request shapes derive from an older community SDK
  ([kpapadatos/efoodgr](https://github.com/kpapadatos/efoodgr)) and **will be tested and verified in
  a future pass**.
- **`place_order` spends real money.** It cannot enter card details — pay with cash on delivery or a
  saved payment token. Always confirm the exact items and total first.
- Not affiliated with, endorsed by, or supported by efood / Delivery Hero.

TDQS

A4.3/5.0

Scored across 12 tools

Disambiguation5/5

Each tool targets a distinct resource (restaurant, menu, cart, order, account) and action, with clear boundaries. Even cart-related tools are unambiguous: add_item, remove_item, get_cart, and clear_cart perform different operations on different scales.

Naming Consistency5/5

Every tool follows the verb_noun pattern with underscores, using consistent verbs like get, add, remove, clear, search, and place. Minor singular/plural variations (e.g., get_addresses vs get_cart) are natural and do not break the pattern.

Tool Count5/5

With 12 tools, the server is well-scoped for a food delivery domain. It covers restaurant discovery, menu browsing, cart management, order placement, and order tracking without unnecessary bloat or missing core actions.

Completeness4/5

The core ordering lifecycle is fully covered: search restaurants, fetch menus, customize items, manage cart, place order, and check status. Minor gaps such as editing cart line quantities or canceling an order exist, but agents can work around them (e.g., remove and re-add items).

Maintenance

ActivitySlowing
ResponsivenessNo issues