Skip to main content
Glama
MaheshPhuyal02

Daraz Nepal MCP Server

README.md
# Daraz Nepal MCP Server

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/downloads/)
[![MCP](https://img.shields.io/badge/MCP-server-6E56CF.svg)](https://modelcontextprotocol.io)

An [MCP](https://modelcontextprotocol.io) server that lets an AI assistant search
**Daraz Nepal** (https://www.daraz.com.np) — live prices in NPR, no API key, no
seller account. Point it at any Daraz region with one environment variable.

Ask your assistant *"find me a wireless mouse under Rs. 1500"* and it searches,
filters and sorts real listings.

```
search_daraz("wireless mouse", max_price=1500, sort="price_low")

1. Logitech M170 Wireless Mouse — Rs. 1,299  (was Rs. 1,799, -28%)
   ★ 4.6 (1,204 reviews) · 3.2K sold · Logitech Official Store · Kathmandu
   https://www.daraz.com.np/products/...
```

---

## Requirements

- **Python 3.10 or newer**
- No API key, no Daraz account
- Optional: [Playwright](https://playwright.dev/python/) Chromium, used only as a
  fallback if Daraz's JSON endpoint gets blocked

## Install

```bash
git clone https://github.com/MaheshPhuyal02/daraz-np-mcp.git
cd daraz-np-mcp

python3 -m venv .venv
source .venv/bin/activate          # Windows: .venv\Scripts\activate
pip install -r requirements.txt
```

Optional browser fallback:

```bash
playwright install chromium
```

<details>
<summary>Using <a href="https://docs.astral.sh/uv/">uv</a> instead</summary>

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

Then use `.venv/bin/python` (or `uv run python`) everywhere below.
</details>

## Verify it works

Before wiring it into an MCP client, check the scraper against the live site:

```bash
python daraz_cli.py doctor
```

Expected output ends with `All good — the MCP server should work.` If it doesn't,
see [Troubleshooting](#troubleshooting).

More CLI examples:

```bash
python daraz_cli.py search "wireless mouse" --limit 5
python daraz_cli.py search "gas stove" --sort price_low --max-price 8000
python daraz_cli.py search "tv" --category televisions --json
python daraz_cli.py details "https://www.daraz.com.np/products/....html"
python daraz_cli.py categories
```

Run the offline unit tests (no network needed):

```bash
pytest -q
```

## Run the server

```bash
python daraz_np_server.py
```

It speaks MCP over stdio, so on its own it will just sit there waiting for a
client — that is expected. Normally you don't run it by hand; your MCP client
launches it for you, as configured below.

## Register with an MCP client

MCP clients do **not** inherit your shell's working directory or virtualenv, so
every path below must be **absolute**. Get yours with:

```bash
cd daraz-np-mcp
echo "$PWD/.venv/bin/python"        # Windows: echo %CD%\.venv\Scripts\python.exe
echo "$PWD/daraz_np_server.py"
```

### Claude Desktop

Edit the config file:

- **macOS** — `~/Library/Application Support/Claude/claude_desktop_config.json`
- **Windows** — `%APPDATA%\Claude\claude_desktop_config.json`
- **Linux** — `~/.config/Claude/claude_desktop_config.json`

```json
{
  "mcpServers": {
    "daraz-np": {
      "command": "/absolute/path/to/daraz-np-mcp/.venv/bin/python",
      "args": ["/absolute/path/to/daraz-np-mcp/daraz_np_server.py"],
      "env": {
        "DARAZ_DOMAIN": "www.daraz.com.np",
        "DARAZ_CURRENCY": "Rs."
      }
    }
  }
}
```

Restart Claude Desktop, then look for the tools under the 🔌 / tools menu.
`mcp.example.json` in this repo has the same shape — copy it as a starting point.

### Claude Code

```bash
claude mcp add daraz-np \
  -e DARAZ_DOMAIN=www.daraz.com.np \
  -- /absolute/path/to/daraz-np-mcp/.venv/bin/python \
     /absolute/path/to/daraz-np-mcp/daraz_np_server.py
```

Check it registered with `claude mcp list`.

### Cursor / Windsurf / other clients

Anything that speaks MCP over stdio works — use the same `command` + `args`
shape as the Claude Desktop block above, in that client's MCP config
(`~/.cursor/mcp.json` for Cursor).

## Tools

### `search_daraz`

| Argument | Type | Default | Notes |
|---|---|---|---|
| `query` | str | — | e.g. `"wireless mouse"`, `"gas stove"` |
| `limit` | int | 10 | 1–50 results |
| `sort` | str | `relevance` | `price_low`, `price_high`, `popularity`, `newest`, `rating` |
| `min_price` / `max_price` | float | — | NPR, pushed to Daraz's own filter |
| `category` | str | — | slug, e.g. `mobile-phones` (see `list_categories`) |
| `in_stock_only` | bool | false | drop out-of-stock items |
| `pages` | int | 3 | result pages to pull, 1–10 |
| `as_json` | bool | false | structured output instead of markdown |

Queries containing "cheapest"/"cheap" auto-switch to `price_low`; "most
expensive"/"premium" to `price_high`.

### `product_details(url)`

Name, price, original price, brand, rating, review count, seller (+ positive
rating), stock and a trimmed description for a single product page.

### `list_categories()`

Common Daraz Nepal category slugs for focused searches.

## Configuration

All optional — set them in the `env` block of your MCP client config.

| Env var | Default | Purpose |
|---|---|---|
| `DARAZ_DOMAIN` | `www.daraz.com.np` | point at another Daraz region (`www.daraz.com.bd`, `www.daraz.lk`, `www.daraz.com.mm`) |
| `DARAZ_CURRENCY` | `Rs.` | display prefix |
| `DARAZ_TIMEOUT` | `20` | seconds per HTTP request |
| `DARAZ_LOG_FILE` | unset | write a debug log to this path |
| `DARAZ_LOG_LEVEL` | `INFO` | `DEBUG` for verbose tracing |

## How it works

Daraz's storefront renders from a JSON payload that the same URL returns when
you append `ajax=true`:

```
GET https://www.daraz.com.np/catalog/?ajax=true&q=mouse&page=1&_keyori=ss
GET https://www.daraz.com.np/{category}/?ajax=true&page=1
```

Products live at `mods.listItems` (the client also probes `data.mods.listItems`,
`listItems`, `results` and `data.products` since Daraz A/B-tests its response
shape). Sorting and price bounds are passed as `sort=` and `price=min-max` so
Daraz does the work server-side; the result is re-sorted locally as a guard.

If the JSON endpoint returns HTML (anti-bot page), the server falls back to
rendering the search page with Playwright — install it or that step is skipped
with a log line.

## Troubleshooting

**`doctor` says "response was not JSON (likely an anti-bot / captcha page)"**
Daraz is rate-limiting or challenging you. Wait a few minutes, and install the
Playwright fallback (`playwright install chromium`).

**`doctor` parses 0 items**
Daraz probably changed its response shape. `doctor` prints the raw item keys and
`mods` keys it received — that's the first place to look, and a great PR.

**Tools don't show up in the client**
Almost always a path problem. Use absolute paths, point `command` at the
**venv's** Python (not system `python3`), and check the client's MCP log. Running
the same command by hand in a terminal should hang silently rather than error.

**`ModuleNotFoundError: fastmcp`**
The client is using a Python without the dependencies installed — see above.

## Notes and limits

- Public endpoints only; no login, no seller API. Daraz can change or throttle
  them at any time — `python daraz_cli.py doctor` tells you which.
- Requests are paced 0.6–1.4 s apart with a rotating User-Agent. Don't raise
  `pages` far beyond the default if you're running many searches.
- Prices are live at fetch time; always confirm on the product page before buying.
- Scraping is best-effort and for personal use. Check Daraz's terms of service
  before running this at volume. This project is not affiliated with, endorsed
  by, or connected to Daraz or Alibaba Group.

## Contributing

Bug reports and PRs are welcome — see [CONTRIBUTING.md](CONTRIBUTING.md).

## License

[MIT](LICENSE) © MaheshPhuyal02.