booksmandala.com

find-product

Installation

Adds this website's skill for your agents

 

Summary

Search, browse, and look up books on Books Mandala (Nepal's largest dedicated online bookstore, 50,000+ titles including deep Nepali / South-Asian literature). Returns title, authors, ISBN, NPR price, stock status, genres, and a canonical purchase URL. Uses Books Mandala's public MCP server (no auth) by default, with REST API and browser fallbacks documented.

FIG. 01
FIG. 02
FIG. 03
SKILL.md
270 lines

Books Mandala — Find a Book

Purpose

Search, browse, and look up books from Books Mandala — Nepal's largest dedicated online bookstore (50,000+ titles, with deep coverage of Nepali / Hindi / Sanskrit / South-Asian literature and international bestsellers). Returns title, author(s), ISBN, formatted NPR price + numeric value, stock status (in / out), genres, description, and a canonical booksmandala.com/books/{slug}-{id} purchase link for each match. Read-only — never adds to cart, places an order, or hits authenticated endpoints.

When to Use

  • A user (anywhere in the world) is looking for a specific Nepali or South-Asian title and wants to know whether Books Mandala stocks it, at what price, and where to buy.
  • Discovery flows: "show me bestsellers", "what's new", "books in the nepali-literature genre", "everything by Buddhisagar".
  • Agentic shopping where you need a stable, structured catalog surface — Books Mandala publishes a public MCP server and a documented REST API specifically so AI agents can browse the catalog programmatically.
  • Anywhere you'd otherwise scrape booksmandala.com HTML — the MCP / API path is ~100× cheaper and structurally more reliable than rendering the Next.js front-end.

Workflow

Books Mandala ships three machine-friendly surfaces; pick in this order of preference:

  1. MCP server (recommended, no auth)https://bm-agent-mcp.booksmandala.workers.dev/mcp. Public, no API key required, 7 tools covering every browse / lookup use case. Streamable HTTP, MCP protocol 2025-03-26.
  2. REST API (requires key)https://booksmandala.com/api/agent/v1. Same 7 operations as the MCP, returns clean JSON, but every endpoint except /health and /docs requires an X-API-Key header. Keys are issued by emailing dev@mandalatech.io. Rate limit 100 req/min per key.
  3. Browser fallback — only when MCP is down and you have no API key. The site is Next.js SSR + JSON-LD; works without stealth or proxies.

1. Recommended path — MCP (Streamable HTTP, no auth)

If your agent host (Claude Desktop, Cursor, etc.) supports MCP config, just add it:

{
  "mcpServers": {
    "books-mandala": {
      "url": "https://bm-agent-mcp.booksmandala.workers.dev/mcp"
    }
  }
}

If you're a code-driven agent without a built-in MCP client, talk to it over plain HTTP with two POSTs (initialize + tools/call). The server returns SSE-framed JSON-RPC responses (event: message\ndata: {...}\n\n):

# 1. Initialize → server returns an mcp-session-id header you must echo on subsequent calls
INIT=$(curl -s -D - -X POST https://bm-agent-mcp.booksmandala.workers.dev/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"my-agent","version":"1.0"}}}')
MCP_SID=$(printf '%s' "$INIT" | grep -i '^mcp-session-id:' | awk '{print $2}' | tr -d '\r')

# 2. (optional but spec-compliant) — fire-and-forget initialized notification
curl -s -X POST https://bm-agent-mcp.booksmandala.workers.dev/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "mcp-session-id: $MCP_SID" \
  -d '{"jsonrpc":"2.0","method":"notifications/initialized"}'

# 3. Call a tool — search_books, get_book, list_genres, browse_genre, bestsellers, new_arrivals, get_author
curl -s -X POST https://bm-agent-mcp.booksmandala.workers.dev/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "mcp-session-id: $MCP_SID" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"search_books","arguments":{"query":"palpasa cafe","limit":3}}}'

The 7 MCP tools and when to use each:

ToolRequired argsUse for
search_booksquery (min 2 chars)Lookup by title / author / ISBN. Optional: page (default 1), limit (default 20, max 50).
get_bookidentifier (ISBN or slug)Full details for one book — publisher, pages, edition, weight, rating, full description. Slug is the part of the URL between /books/ and the trailing -{id} (e.g. atomic-habits for /books/atomic-habits-15626) — though either the bare slug or the full slug-id resolves. ISBN-13 also works.
list_genresAll 177 genres with their parent category (e.g. nepali-literature → parent nepali). Returns slugs you feed into browse_genre.
browse_genregenre_slugPaged list of books in a genre.
bestsellersCurrent top sellers, paged.
new_arrivalsBooks added in the last 45 days, paged.
get_authorauthor_slugAuthor bio + their books. Slugs are kebab-case author names (e.g. james-clear, narayan-wagle, buddhisagar); the same slug appears in https://booksmandala.com/author/{slug} URLs.

Response shape. Every tool returns {"content": [{"type": "text", "text": "..."}]} — a single Markdown-formatted text block, NOT structured JSON book objects. Each book entry looks like:

**Palpasa Cafe**
by Narayan Wagle
Price: NPR 595 | In Stock
ISBN: 9789937905855
Genres: Nepali, Nepali Literature

<full description>

Buy: https://booksmandala.com/palpasa-cafe-2739

If your downstream system needs structured fields, parse with a per-entry block split on \n---\n and a regex pass per line (^by\s+(.+)$, ^Price:\s+(NPR \d[\d,]*)\s*\|\s*(In Stock|Out of Stock)$, ^ISBN:\s+(\d+)$, etc.). For machine-clean JSON, use the REST API instead.

2. Alternative — REST API (key required, returns clean JSON)

Same operations as the MCP but with structured Book objects. Request a key from dev@mandalatech.io, then:

curl -s -H "X-API-Key: $BM_KEY" \
  "https://booksmandala.com/api/agent/v1/search?q=palpasa+cafe&limit=3"

Endpoints (all GET, all under https://booksmandala.com/api/agent/v1):

PathNotes
/search?q=<text>min q length 2; page, limit (max 50)
/books/{isbn-or-slug}full BookDetail
/genresflat list
/genres/{slug}/bookspaged
/bestsellerspaged
/new-arrivalspaged
/authors/{slug}author + books
/healthno auth
/docsno auth — full OpenAPI 3.0 spec

The OpenAPI spec at /docs defines the canonical Book / BookDetail schemas — fetch it once and use it as your typed contract. Without X-API-Key, every non-/health / non-/docs endpoint returns HTTP 401 {"error":"API key required...","code":"AUTH_REQUIRED"}.

3. Browser fallback (when no MCP + no API key)

Bare session is fine (no Akamai, no proxies, no stealth needed):

sid=$(browse cloud sessions create --keep-alive | jq -r .id)
export BROWSE_SESSION="$sid"

Three browser sub-flows depending on intent:

Search — the homepage has no ?q= URL param. /search?q=... is a 404. Search is a Ctrl+K modal that fires inline typeahead results:

browse open "https://booksmandala.com/" --remote
browse wait load --remote
# Click the "What do you want to read ? Ctrl + K" button (top right of nav)
browse click "button:What do you want to read*" --remote
# Type into the searchbox (don't press Enter — autocomplete renders as you type)
browse fill "searchbox:Search By Title*" "palpasa cafe" --remote
browse wait timeout 2000 --remote
browse snapshot --remote
# urlMap entries shaped like https://booksmandala.com/books/{slug}-{id} are the matches

Genre browse — direct URL works: https://booksmandala.com/books/genres/{genre-slug} (e.g. /books/genres/nepali, /books/genres/fiction-and-literature). Add ?sub_genres={sub} to scope to a sub-genre (e.g. /books/genres/self-improvement-and-relationships?sub_genres=self-help). Genre slugs match list_genres output exactly.

Book detailhttps://booksmandala.com/books/{slug}-{id}. Either browse get markdown body to get clean Markdown of the page, or grep the raw HTML for "@type":"Book" — the Next.js hydration payload embeds JSON-LD with the full schema.org Book object (title, image, ISBN, description, publisher, price NPR, availability, aggregateRating). Note the JSON-LD is embedded inside a <script>self.__next_f.push(...)</script> Next.js streaming chunk, not a clean <script type="application/ld+json"> tag — use a substring search for "@type":"Book" then carve from the surrounding object literal.

Release the session when done: browse cloud sessions update "$sid" --status REQUEST_RELEASE.

Site-Specific Gotchas

  • The MCP server is genuinely public — don't bother passing API keys. bm-agent-mcp.booksmandala.workers.dev requires no auth header, no client registration, no OAuth. Verified 2026-05-20: a cold initialize from a fresh Browserbase IP returned protocolVersion 2025-03-26 and a session id in the first response. The REST API at /api/agent/v1 is the surface that requires X-API-Key; the MCP is the unauthenticated mirror.
  • MCP returns Markdown text, not JSON book objects. Despite being a structured tool-calling protocol, every Books Mandala tool returns a single {"type":"text","text":"..."} block formatted for human/LLM reading. If you need typed fields, either (a) regex-parse the text block, or (b) switch to the REST API which returns proper {"data": Book, "meta": {...}} JSON.
  • MCP transport is Streamable HTTP with SSE framing. Responses look like event: message\ndata: <json>\n\n. If your HTTP client treats the body as plain JSON it will fail to parse — strip the event: / data: prefixes first, or use a real MCP client. Also: you MUST send Accept: application/json, text/event-stream (both) on every POST; sending only application/json is rejected.
  • MCP session id is REQUIRED on every call after initialize. The server sets mcp-session-id: <hex> in the response headers of the initialize call; echo it back as the mcp-session-id request header on every subsequent tools/call / tools/list. Calls without it return an MCP protocol error.
  • REST API rate limit is per endpoint and SHARED with the docs endpoint. Observed: X-Ratelimit-Limit: 20 on the /docs endpoint, and the documented per-key rate is 100/min. Don't loop on /docs — fetch it once, cache it.
  • URL paths use /books/{slug} (plural), not /book/{slug} (singular). The llms.txt at https://booksmandala.com/llms.txt documents the singular form; the live site serves the plural. All MCP Buy: links and the front-end's urlMap use plural.
  • Slugs carry a numeric id suffix. Canonical URL shape is /books/{kebab-title}-{id} (e.g. /books/palpasa-cafe-2739, /books/atomic-habits-15626). The get_book tool accepts either ISBN-13, the bare slug, or the full slug-with-id.
  • Prices are in NPR (Nepalese Rupees) in the API, but the front-end auto-converts based on browser geolocation. Same book on the rendered homepage shows $1.56 while bestsellers MCP returns NPR 209. If you're routing the user to the front-end for purchase, surface both — the user may see a different display currency.
  • /search?q=... is a 404 page. The site has no URL-routed search. Browser fallback for search MUST go through the Ctrl+K modal (see workflow). The search button has accessible name "What do you want to read ? Ctrl + K".
  • The Ctrl+K modal does NOT navigate on Enter. Results render inline in the modal as a typeahead. Use browse snapshot after fill (with a 1–2s wait for the debounce) and read result anchors from the urlMap. Pressing Enter just submits without going anywhere useful.
  • JSON-LD on book pages is embedded inside Next.js hydration chunks, not in clean <script type="application/ld+json"> tags. A naive grep '<script[^>]*ld+json' finds nothing parseable. Search for the literal string "@type":"Book" and carve the enclosing {...} — or just use browse get markdown body, which gives a clean prose version of the same data.
  • No anti-bot, no stealth needed. Cloudflare in front of the site (cf-ray header present) but no challenges, no captcha, no IP-based blocking observed. A bare Browserbase session loads the homepage and any deep link cleanly. --proxies and --verified are NOT required for any of the three paths.
  • get_book description fields can contain Nepali (Devanagari) script and the MCP / API both preserve UTF-8 correctly. Don't assume ASCII-only output when displaying descriptions.
  • Phase 1 only. The MCP and REST API are documented as Phase 1 (discovery / browsing). Real-time stock-by-ISBN, shipping-cost-by-city, and order placement are advertised as Phase 2+ and are NOT in the current tool set. Don't attempt to place an order through any of these surfaces.
  • llms.txt and llms-full.txt are the canonical reference. https://booksmandala.com/llms.txt is the short overview; https://booksmandala.com/llms-full.txt is the full catalog + taxonomy + tech doc. Both update; pull them at runtime if you need the genre tree or the latest endpoint list.

Expected Output

When the caller asks "find {query} on Books Mandala", normalize to this shape regardless of which path you used:

{
  "query": "palpasa cafe",
  "method": "mcp",
  "total_results": 3,
  "page": 1,
  "books": [
    {
      "title": "Palpasa Cafe",
      "authors": ["Narayan Wagle"],
      "isbn": "9789937905855",
      "price": "NPR 595",
      "price_value": 595,
      "currency": "NPR",
      "in_stock": true,
      "genres": ["Nepali", "Nepali Literature"],
      "description": "Felicitated by Madan Purashkar in the year 2005…",
      "url": "https://booksmandala.com/books/palpasa-cafe-2739"
    }
  ]
}

For a single-book detail lookup (get_book / /books/{id}):

{
  "method": "mcp",
  "book": {
    "title": "Palpasa Cafe",
    "alternate_title": "पल्पसा क्याफे",
    "authors": ["Narayan Wagle"],
    "isbn": "9789937905855",
    "publisher": "Nepalaya",
    "pages": 286,
    "cover_type": "paper back",
    "edition": "1",
    "weight_grams": 240,
    "languages": ["Nepali"],
    "genres": ["Nepali", "Nepali Literature"],
    "average_rating": 5,
    "reviews_count": 1,
    "price": "NPR 595",
    "price_value": 595,
    "currency": "NPR",
    "in_stock": true,
    "description": "…full text…",
    "url": "https://booksmandala.com/books/palpasa-cafe-2739"
  }
}

Empty / not-found result:

{
  "query": "definitely not a real book xyz",
  "method": "mcp",
  "total_results": 0,
  "books": []
}

Always include the canonical https://booksmandala.com/books/{slug}-{id} URL on every result so the caller has a one-click path to the purchase page. Prices are NPR; surface conversion to the user's locale on the caller side if needed.

Books Mandala — Find a Book · browse.sh