关于 cuddlynest-mcp
cuddlynest-mcp 是用于搜索 CuddlyNest 酒店并读取房源详情的 MCP 服务,面向旅行查询场景。它只读地获取客房、价格、可订状态和取消政策,不支持预订或付款。
主要功能
- 01搜索目的地及酒店
- 02读取酒店静态详情
- 03提取客房与价格
- 04查看可订数量和取消政策
- 05支持 stdio 与 Streamable HTTP
适用场景
- 01查找某城市的酒店候选
- 02比较房源的房型和价格
- 03核对客房剩余数量与取消条款
MCP 相关
该 MCP 服务向客户端提供目的地搜索和酒店详情工具。工具仅读取数据,不进行预订或付款。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
2收录的工具列表 · 更新于 2 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| rooms | number | 否 | 房间数(默认:1) |
| adults | number | 否 | 成人数(默认:2) |
| checkin | string | 否 | 入住日期(YYYY-MM-DD) |
| infants | number | 否 | 婴儿数(默认:0) |
| checkout | string | 否 | 退房日期(YYYY-MM-DD) |
| children | number | 否 | 儿童数(默认:0;也可根据 childAges 推导) |
| currency | string | 否 | 价格使用的 ISO 4217 货币代码(默认:USD),例如 USD、EUR、COP |
| childAges | array | 否 | 每个孩子入住时的年龄,例如 [2, 7]。提供此参数时会设置 `children`。 |
| hotelsOnly | boolean | 否 | 仅返回酒店列表,跳过地点候选项(默认 false)。 |
| destination | string | 是 | 要搜索的目的地(城市/地区),例如 'Santa Marta, Colombia'。 |
| fullCityList | boolean | 否 | 如果可以解析,则通过 geo-page API 额外获取更广泛的城市酒店列表(约 60 家);这会多发几次请求。默认 true。 |
详细介绍
CuddlyNest 搜索与房源 — MCP 服务
用于搜索 CuddlyNest 酒店并获取房源详情的 Model Context Protocol(MCP)服务,包括房型选项、价格、空房情况和取消政策。
该服务从设计上便为只读:仅搜索和获取房源详情。不预订、不付款。
数据获取方式
本服务以访客相同的方式读取数据:通过无头浏览器(Playwright/Chromium)打开真实的公开房源页面,让页面自身的 JavaScript 加载房型,等待其渲染完成,然后从 DOM 中读取结果。
| 数据 | 来源 |
|---|---|
| 名称、描述、地址、坐标、星级、便利设施、图片 | 房源页面的 schema.org ld+json 和 Open Graph 标签(cuddlynest.ts) |
房型标题、合作方、unit_price、remaining_rooms、price_breakdown、cancellation_policy(包括 .text)、room_filters | 通过 React fiber 遍历获取渲染后的房源页面 DOM(scrape-listing.ts) |
| 目的地 → 地点候选项 + 热门酒店 | autosuggestion-2-0.cuddlynest.com(公开,无需身份验证) |
| 目的地 → 更多城市酒店列表(约 60–250 家) | discovery-pages.cuddlynest.com/fetch_geopage/<ct-id>(公开);从酒店的产品详情页面包屑中提取 <ct-id> |
product_id → 名称 / 城市 / 面包屑 | ldp-2-0-product-details.cuddlynest.com/api/v1/productDetail(公开) |
product_id → 规范房源路径 | /hotel/-<id> 服务端重定向 |
DOM 提取方式及其失效原因
extractRoomsFromDom() 会遍历所有价格格式的文本节点(COL$742,637),然后沿着React fiber 树向上查找,找到 props 同时包含 unit_price 和 roomGroups 的最近祖先组件。这些 props 就是页面已渲染的房型报价。
此实现与 CuddlyNest 当前的前端内部结构紧密耦合(依赖 React prop 形状,而非稳定契约)。如果其前端发生变化,即使公开页面仍显示价格,也可能导致返回的房型数量变为 0。需要更新的唯一位置是 scrape-listing.ts 中的检测条件 'unit_price' in p && 'roomGroups' in p。npm run e2e:sansiraka 旨在及早发现此问题(以非零退出码报告,而不是悄无声息地返回空结果)。
fromPriceText(“From COL$…”)字段使用较宽松的启发式方法,即使抓取正常,也可能返回 null;rooms.fromPrice(提取到的最便宜房型)才是可靠价格。
要求
- Node.js 18+
- Playwright 所需的 Chromium 构建版本。
npm install会自动运行playwright install chromium(postinstall);如果在你的环境中无法执行,请手动运行一次npx playwright install chromium。
安装
已在 npm 上发布为 cuddlynest-mcp,并收录于官方 MCP 注册表,名称为 io.github.mafedelahoz/cuddlynest-mcp。
{
"mcpServers": {
"cuddlynest": {
"command": "npx",
"args": ["-y", "cuddlynest-mcp"]
}
}
}
在 args 中添加 "--ignore-robots-txt",即可在获取房源页面时绕过 robots.txt。CUDDLYNEST_SCRAPE_TIMEOUT_MS(默认值为 35000)限制浏览器等待价格渲染的时长。
每个 GitHub release 都附有适用于 Claude Desktop 的 MCPB bundle(.mcpb)——请注意,它不包含 Chromium,因此通过这种方式安装后,请运行一次 npx playwright install chromium。
远程 / Streamable HTTP
默认传输方式为 stdio。对于托管部署,请通过 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
工具
两个工具都标注了 readOnlyHint: true——它们绝不会写入数据、预订或付款。
cuddlynest_search
通过 CuddlyNest 的公开 API 搜索目的地及当地热门酒店
(使用 autosuggestion-2-0 进行模糊匹配,使用 discovery-pages 地理页面获取
更全面的城市列表)。这里不包含价格——请将酒店的 productId 传给
cuddlynest_listing_details。
| 参数 | 必填 | 说明 |
|---|---|---|
destination | 是 | 城市/地区字符串,例如 "Cartagena, Colombia" |
hotelsOnly | 否 | 不包含 places[] 区块(默认 false) |
fullCityList | 否 | 如果能够解析并验证目的地,也获取地理页面的城市列表(约 60–250 家酒店)——这会多发几次请求(默认 true) |
checkin、checkout、adults、children、childAges、infants、rooms、currency | 否 | 回传这些参数,供下游使用 |
返回: { query, guests, places[], city, hotelSource, hotelCount, hotels[], note }。
hotels[] 中的每个条目包括:productId、name、url、slug、propertyType、
starRating、guestRating(/10)、guestRatingText、reviewCount,以及从
地理页面获取的 images[]、distanceFromCenterKm、featuredAmenities[]。
hotelSource 为 "autosuggest" 或 "autosuggest+geopage"。此列表仅包含
热门匹配结果,并非完整房源——CuddlyNest 的真实结果页面
(/sr/…)被机器人屏蔽,并在 robots.txt 中被 Disallow 禁止访问。
cuddlynest_listing_details
获取单家酒店的静态基本信息以及房间/价格信息。
| 参数 | 必填 | 说明 |
|---|---|---|
hotel | 是 | 房源 URL 或数字形式的 product_id(URL 末尾的数字) |
checkin、checkout | 获取价格时必填 | YYYY-MM-DD — 读取房间/价格信息时必填 |
adults、children、childAges、infants、rooms | 否 | 默认值为 2 / 0 / – / 0 / 1 |
currency | 否 | ISO 4217,默认 USD |
ignoreRobotsText | 否 | 获取静态信息时忽略 robots.txt |
返回: { productId, hotelUrl, guests, staticListing, staticError, rooms, roomsError, notes }。
rooms.units[] 为提取到的房间报价,每项包含 title、partnerName、
unitPrice、currency、remainingRooms、guests、cancellationPolicyType、
cancellationPolicyText、priceBreakdown、roomFilters。rooms 还包含
fromPrice、partnersSeen、listingUrl、scrapedAt。
开发
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
架构
index.ts— MCP 服务、工具架构、stdio 和 Streamable HTTP 传输方式、robots.txt处理cuddlynest.ts— 酒店 URL 解析、静态房源ld+json解析、 目的地自动建议、结果整理scrape-listing.ts—resolveListingPath、buildListingUrl、scrapeListing(无头浏览器)、extractRoomsFromDom(React-fiber 遍历)util.ts— 通用对象/JSON 辅助工具
许可证
MIT — 请参阅 LICENSE。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。