MCP server for CuddlyNest — search hotels and read live rooms, prices, availability and cancellation policies from the public listing page
- ✓Open-source license (MIT)
- ✓Actively maintained (<30d)
- ✓Clear description
- ✓Topics declared
- ✓Documented (README)
claude mcp add mcp-cuddlynest -- npx -y playwright{
"mcpServers": {
"mcp-cuddlynest": {
"command": "npx",
"args": ["-y", "playwright"]
}
}
}MCP Servers overview
<img src="assets/icon.png" alt="CuddlyNest" width="88" align="right">
# CuddlyNest Search & Listings — MCP Server
[](https://www.npmjs.com/package/cuddlynest-mcp)
[](https://registry.modelcontextprotocol.io/v0/servers?search=cuddlynest)
A Model Context Protocol (MCP) server for searching [CuddlyNest](https://www.cuddlynest.com)
hotels and retrieving listing details, including **room options, prices,
availability and cancellation policies**.
Read-only by design: search and listing details only. No booking, no payment.
## How it gets the data
CuddlyNest does not serve room prices in its static HTML. Pricing renders
client-side on the **public listing page**, backed by the site's own
infrastructure and third-party wholesale suppliers (`dida travels`,
`hotelplanner`, `ratehawk`, `hxpro`, `rakuten`, …).
This server reads that data **the same way a visitor does**: it opens the real,
public listing page in a headless browser (Playwright/Chromium), lets *the
page's own JavaScript* load the rooms, waits for them to render, and reads the
result out of the DOM.
| Data | Source |
| --- | --- |
| Name, description, address, coordinates, star rating, amenities, images | Listing page `schema.org` `ld+json` + Open Graph tags (`cuddlynest.ts`) |
| Room title, partner, `unit_price`, `remaining_rooms`, `price_breakdown`, `cancellation_policy` (incl. `.text`), `room_filters` | Rendered listing page DOM, via a React-fiber walk (`scrape-listing.ts`) |
| Destination → place candidates + top hotels | `autosuggestion-2-0.cuddlynest.com` (public, no auth) |
| Destination → broader city hotel list (~60–250) | `discovery-pages.cuddlynest.com/fetch_geopage/<ct-id>` (public); `<ct-id>` recovered from a hotel's product-detail breadcrumbs |
| `product_id` → name / city / breadcrumbs | `ldp-2-0-product-details.cuddlynest.com/api/v1/productDetail` (public) |
| `product_id` → canonical listing path | `/hotel/-<id>` server redirect |
### The DOM extraction, and how it breaks
`extractRoomsFromDom()` walks every price-shaped text node (`COL$742,637`), then
walks up its **React fiber tree** to the nearest ancestor component whose props
carry both `unit_price` and `roomGroups`. Those props are the room offer the
page already rendered.
This is coupled to CuddlyNest's current frontend internals (a React prop shape,
not a stable contract). If they ship a frontend change it can start returning
zero rooms even though the public page still shows prices. The single place to
update is the detector condition `'unit_price' in p && 'roomGroups' in p` in
[scrape-listing.ts](scrape-listing.ts). `npm run e2e:sansiraka` is meant to
catch that early (non-zero exit, not a silent empty result).
The `fromPriceText` ("From COL$…") field uses a looser heuristic and can come
back `null` even on a healthy scrape; `rooms.fromPrice` (cheapest extracted
unit) is the reliable figure.
---
## Requirements
- Node.js 18+
- A Chromium build for Playwright. `npm install` runs `playwright install
chromium` automatically (postinstall); if that is blocked in your
environment, run `npx playwright install chromium` once by hand.
## Installation
Published as [`cuddlynest-mcp`](https://www.npmjs.com/package/cuddlynest-mcp) on
npm and listed in the [official MCP registry](https://registry.modelcontextprotocol.io/v0/servers?search=cuddlynest)
as `io.github.mafedelahoz/cuddlynest-mcp`.
```json
{
"mcpServers": {
"cuddlynest": {
"command": "npx",
"args": ["-y", "cuddlynest-mcp"]
}
}
}
```
Add `"--ignore-robots-txt"` to `args` to bypass `robots.txt` for the
listing-page fetches. `CUDDLYNEST_SCRAPE_TIMEOUT_MS` (default `35000`) caps how
long the browser waits for prices to render.
An MCPB bundle (`.mcpb`) for Claude Desktop is attached to each
[GitHub release](https://github.com/mafedelahoz/mcp-cuddlynest/releases) — note it
does **not** bundle Chromium, so run `npx playwright install chromium` once after
installing it that way.
### Remote / Streamable HTTP
Default transport is stdio. For a hosted deployment, run it over Streamable HTTP:
```bash
node dist/index.js --http 8080 # or: MCP_TRANSPORT=http PORT=8080 node dist/index.js
# POST http://<host>:8080/mcp — JSON-RPC (stateless, no sessions)
# GET http://<host>:8080/health — liveness
```
---
## Tools
Both tools are annotated `readOnlyHint: true` — they never write, book, or pay.
### `cuddlynest_search`
Search a destination and the top hotels there, from public CuddlyNest APIs
(`autosuggestion-2-0` for the fuzzy match, `discovery-pages` geo pages for the
broader city list). Prices are **not** here — pass a hotel's `productId` to
`cuddlynest_listing_details`.
| Parameter | Required | Description |
| --- | --- | --- |
| `destination` | yes | City / area string, e.g. `"Cartagena, Colombia"` |
| `hotelsOnly` | no | Omit the `places[]` block (default `false`) |
| `fullCityList` | no | Also pull the geo-page city list (~60–250 hotels) when it can be resolved and verified against the destination — a few extra requests (default `true`) |
| `checkin`, `checkout`, `adults`, `children`, `childAges`, `infants`, `rooms`, `currency` | no | echoed back for downstream use |
**Returns:** `{ query, guests, places[], city, hotelSource, hotelCount, hotels[], note }`.
Each `hotels[]` entry: `productId`, `name`, `url`, `slug`, `propertyType`,
`starRating`, `guestRating` (/10) + `guestRatingText`, `reviewCount`, and — from
the geo page — `images[]`, `distanceFromCenterKm`, `featuredAmenities[]`.
`hotelSource` is `"autosuggest"` or `"autosuggest+geopage"`. The list is
top-matches scale, **not** full inventory — CuddlyNest's real results page
(`/sr/…`) is bot-blocked and `Disallow`ed in robots.txt.
### `cuddlynest_listing_details`
Static basics **and** rooms/pricing for one hotel.
| Parameter | Required | Description |
| --- | --- | --- |
| `hotel` | yes | Listing URL **or** numeric `product_id` (trailing number in the URL) |
| `checkin`, `checkout` | for pricing | `YYYY-MM-DD` — required to read rooms/prices |
| `adults`, `children`, `childAges`, `infants`, `rooms` | no | defaults 2 / 0 / – / 0 / 1 |
| `currency` | no | ISO 4217, default `USD` |
| `ignoreRobotsText` | no | ignore robots.txt for the static fetch |
**Returns:** `{ productId, hotelUrl, guests, staticListing, staticError, rooms, roomsError, notes }`.
`rooms.units[]` is the extracted room offers, each with `title`, `partnerName`,
`unitPrice`, `currency`, `remainingRooms`, `guests`, `cancellationPolicyType`,
`cancellationPolicyText`, `priceBreakdown`, `roomFilters`. `rooms` also carries
`fromPrice`, `partnersSeen`, `listingUrl`, `scrapedAt`.
---
## Development
```bash
npm install # installs deps + Chromium (postinstall)
npm run build # sync-version + tsc -> dist/
npm run typecheck
npm test # offline: smoke test (stdio) + scraper tests
npm run e2e:sansiraka # ONLINE: real scrape of cuddlynest.com, structural asserts
npm run watch
```
- `test-scrape.js` — `buildListingUrl` (pure) + `extractRoomsFromDom` replayed
against `fixtures/hotel-sansiraka-2026-10-05.json` (a **real** capture from
cuddlynest.com on 2026-09-01: Hotel Sansiraka `4395541`, 2026-10-05→08, 2
adults + 1 child age 2, COP — 9 rooms across dida travels / hxpro / ratehawk /
rakuten). A local headless Chromium rebuilds the page's DOM+fiber shape from
that fixture and checks the extractor reconstructs it — no network.
- `test-extension.js` — MCP handshake, tool listing, `cuddlynest_search`
(hits the autosuggestion API), `cuddlynest_listing_details` product_id parsing.
- `scripts/e2e-hotel-sansiraka.mjs` — runs a real scrape of the Sansiraka
listing and asserts the live result matches the fixture's **structure** (room
object shape/keys, non-empty, partner variety). Live prices and the exact
partner set drift from the fixture — that's expected.
## Architecture
- `index.ts` — MCP server, tool schemas, stdio **and** Streamable HTTP transports,
`robots.txt` handling
- `cuddlynest.ts` — hotel-URL parsing, static-listing `ld+json` parse,
destination autosuggestion, result shaping
- `scrape-listing.ts` — `resolveListingPath`, `buildListingUrl`, `scrapeListing`
(headless browser), `extractRoomsFromDom` (React-fiber walk)
- `util.ts` — generic object/JSON helpers
## License
MIT — see [LICENSE](LICENSE).
What people ask about mcp-cuddlynest
What is mafedelahoz/mcp-cuddlynest?
+
mafedelahoz/mcp-cuddlynest is mcp servers for the Claude AI ecosystem. MCP server for CuddlyNest — search hotels and read live rooms, prices, availability and cancellation policies from the public listing page It has 0 GitHub stars and its last recorded update is dated 2026-09-08.
How do I install mcp-cuddlynest?
+
You can install mcp-cuddlynest by cloning the repository (https://github.com/mafedelahoz/mcp-cuddlynest) or following the README instructions on GitHub. ClaudeWave also provides quick install blocks on this page.
Is mafedelahoz/mcp-cuddlynest safe to use?
+
Our security agent has analyzed mafedelahoz/mcp-cuddlynest and assigned a Trust Score of 95/100 (tier: Verified). See the full breakdown of passed checks and flags on this page.
Who maintains mafedelahoz/mcp-cuddlynest?
+
mafedelahoz/mcp-cuddlynest is maintained by mafedelahoz. The last recorded GitHub activity is dated 2026-09-08, with 0 open issues.
Are there alternatives to mcp-cuddlynest?
+
Yes. On ClaudeWave you can browse similar mcp servers at /categories/mcp, sorted by popularity or recent activity.
Deploy mcp-cuddlynest to your cloud
Ship this repo to production in minutes. Each platform spins up its own environment with editable env vars.
Maintain this repo? Add a badge to your README
Drop the badge into your GitHub README to show it's tracked on ClaudeWave. Each badge links back to this page and reflects the live Trust Score.
[](https://claudewave.com/repo/mafedelahoz-mcp-cuddlynest)<a href="https://claudewave.com/repo/mafedelahoz-mcp-cuddlynest"><img src="https://claudewave.com/api/badge/mafedelahoz-mcp-cuddlynest" alt="Featured on ClaudeWave: mafedelahoz/mcp-cuddlynest" width="320" height="64" /></a>More MCP Servers
Fair-code workflow automation platform with native AI capabilities. Combine visual building with custom code, self-host or cloud, 400+ integrations.
User-friendly AI Interface (Supports Ollama, OpenAI API, ...)
An open-source AI agent that brings the power of Gemini directly into your terminal.
Real-time global intelligence dashboard. AI-powered news aggregation, geopolitical monitoring, and infrastructure tracking in a unified situational awareness interface
The fastest path to AI-powered full stack observability, even for lean teams.
🕷️ An adaptive Web Scraping framework that handles everything from a single request to a full-scale crawl!