CuddlyNest Search & Listings — MCP Server
MCP serverSearchSearch CuddlyNest hotels and read rooms, prices, availability and cancellation policies
Unavailable. This server has no hosted endpoint yet, so ahel can't serve it.
Connect ahel once, and every AI you use reads what you have installed.
From the project's README
As published by mafedelahoz/mcp-cuddlynest in README.md.
A Model Context Protocol (MCP) server for searching CuddlyNest 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
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. 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 installrunsplaywright install chromiumautomatically (postinstall); if that is blocked in your environment, runnpx playwright install chromiumonce by hand.
Installation
Published as cuddlynest-mcp on
npm and listed in the official MCP registry
as io.github.mafedelahoz/cuddlynest-mcp.
{
"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 — 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:
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 Disallowed 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
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
Architecture
index.ts— MCP server, tool schemas, stdio and Streamable HTTP transports,robots.txthandlingcuddlynest.ts— hotel-URL parsing, static-listingld+jsonparse, destination autosuggestion, result shapingscrape-listing.ts—resolveListingPath,buildListingUrl,scrapeListing(headless browser),extractRoomsFromDom(React-fiber walk)util.ts— generic object/JSON helpers
License
MIT — see LICENSE.
Signals
- GitHub stars
- 1
- Last commit
- Sep 2026
- Weekly downloads
- 432
Advanced
- Delivery
- cuddlynest-mcp MCP server → your ahel gateway (mcp.ahel.ai) → every connected AI client.
- Catalog kind
- mcp-server
- Gateway key
io-github-mafedelahoz-cuddlynest-mcp- Source
- github.com/mafedelahoz/mcp-cuddlynest