StayingAPI
About
Live availability, search, listing detail and cross OTA price comparison for Airbnb, Booking.com, Vrbo and Google Hotels in one unified schema, exposed as 7 read only MCP tools and 8 REST endpoints
Details
- Author
- stayingapi
- Categories
- Cloud Service, Search, Knowledge Base, Infrastructure
Jump to
Setup
Install StayingAPI in your MCP client (Claude Desktop, Cursor, Windsurf, and others).
Repository: https://github.com/stayingapi/hotel-vacation-rental-mcp
Follow the installation instructions in the repository README, then restart your MCP client.
Hotel & Vacation Rental MCP - live prices, availability & reviews across Booking.com, Airbnb, Vrbo & Google Hotels
Search stays, compare prices across Booking.com, Airbnb, Vrbo and Google Hotels, and pull reviews by just asking your AI. One hosted MCP, 300 free credits to start, no card.
Seven read-only tools - search, availability, listing detail, price, cross-OTA price compare, reviews, and job polling - for Claude, ChatGPT, Cursor, Claude Code, and any MCP client.
4 booking platforms, one schema · 7 read-only tools · cross-OTA price compare · OAuth 2.1, no key pasted into the agent · 300 free credits to start, no cardStayingAPIis an independent service for accommodation data. StayingAPI is not affiliated with, endorsed by, or sponsored by Airbnb, Booking.com, Vrbo, or Google Hotels. These are trademarks of their respective owners, used here descriptively to indicate the data sources StayingAPI's API and MCP server can query.
claude mcp add --transport http stayingapi https://mcp.stayingapi.com/mcp
Claude Desktop, ChatGPT, Cursor, or any other MCP client— add this as a Streamable HTTP server:
No API key to paste: the first call opens an OAuth sign-in (free account, 300 credits, no card). Per-client steps are inQuick Install, and the whole repo also installs as anAgent Plugin.
You are already comparing stays across four sites by hand: a hotel on Booking.com, an apartment on Airbnb, a villa on Vrbo, and Google Hotels to sanity-check the rate. Every one of them has a different page, a different rating scale, and no API you can just sign up for.
Connect once, then just ask.Add this MCP server to Claude, ChatGPT, Cursor, or any MCP client a single time, and your AI assistant can search real stays, quote real prices for your dates, compare one property's rate across booking sites, and read normalized reviews - inside the conversation, with no code and no repeated setup.
Everything comes back inone unified schema. A hotel room and a holiday villa return the same object shape, ratings carry their native scale instead of being silently rescaled, and the cross-OTA comparison returns each site's offer plus a computed lowest and median price, so you do not re-derive them yourself.
Find 2-bed stays in Lisbon for these dates under EUR 150, compare the top one's price across Airbnb, Booking.com and Vrbo, and summarize its reviews.
That single prompt spans three tools -search_stays,compare_prices,get_reviews- without you writing a line of code.
This repository root is a conformantAgent Plugins 1.0.0package — the portable format published 2026-08-06 and supported by ChatGPT, Codex, Cursor, GitHub Copilot, Kiro and VS Code. One install gets you the MCP serveranda bundledstaysskill that teaches your agent which tool answers which question, how to keep cross-platform fan-out cheap, and that Airbnb/Vrbo rate on a 5-point scale while Booking.com rates on 10 — so it never compares a 9 with a 4.5.
plugin.json # manifest mcp.json # hosted MCP server, streamable-http, OAuth (no keys) skills/stays/SKILL.md # when + how to use the 7 read-only tools
VS Code— Command Palette →Chat: Install Plugin From Source, then paste:
https://github.com/stayingapi/hotel-vacation-rental-mcp
Or register a local clone insettings.json:
"chat.pluginLocations": { "/absolute/path/to/hotel-vacation-rental-mcp": true }
Cursor—Customizein the sidebar → find the plugin →Install. For a local clone:
git clone https://github.com/stayingapi/hotel-vacation-rental-mcp ~/.cursor/plugins/local/stayingapi
ChatGPT, Codex, GitHub Copilot, Kiro, any other client— point your client's plugin mechanism at this repository, or at a local clone. Agent Plugins 1.0.0 standardizes thepackage format, not installation, so each client owns its own install flow.
Find a 2-bedroom apartment in Split, Croatia for 12-15 June, 2 adults, under EUR 150 a night.
Onesearch_stayscall returns Airbnb, Booking.com, Vrbo and Google Hotels merged into a single normalized list, each with its booking URL.No API key to configure— the first call opens an OAuth sign-in (free account, 300 credits, no card). Then the follow-ups that normally take twenty browser tabs:
Is that one cheaper on Booking or Airbnb? → compare_prices (one call, every OTA) Is it free all week, and what's the min stay? → check_availability (day by day)
All seven tools areread-only— nothing here can book, cancel or change a reservation.
There areno credentials in this package— Agent Plugins 1.0.0 forbids embedded secrets, and authorization is client-managed. Verify the package yourself:
curl -sO https://agent-plugins.org/schemas/1.0.0/plugin.schema.json curl -sO https://agent-plugins.org/schemas/1.0.0/mcp.schema.json npx ajv-cli@5 validate --spec=draft2020 -s plugin.schema.json -d plugin.json npx ajv-cli@5 validate --spec=draft2020 -s mcp.schema.json -d mcp.json
- A StayingAPI account (sign up- 300 free credits, no card)
- EitherOAuth (Claude, ChatGPT - no key handling at all)oran API key (stay_live_.../stay_test_...) from your dashboard
Recommended: add a rule so your AI invokes it automatically
Paste this into your client's custom instructions or rules file:
When I mention a hotel, an Airbnb/Booking.com/Vrbo/Google Hotels listing, a place to stay, travel dates, or ask to compare accommodation prices or read stay reviews, automatically use the StayingAPI MCP tools to fetch real data before answering.
Server URL:https://mcp.stayingapi.com/mcp(Streamable HTTP transport)
Settings → Connectors →Add custom connector→ paste:
Claude runs the OAuth 2.1 sign-in for you in a browser popup, which links the connector to your StayingAPI account and its credit balance -no API key needed.The seven read-only tools then appear in your tool list.
Prefer the desktop config file? Add toclaude_desktop_config.json:
{ "mcpServers": { "stayingapi": { "url": "https://mcp.stayingapi.com/mcp" } } }
claude mcp add --transport http stayingapi https://mcp.stayingapi.com/mcp
Then run/mcpinside Claude Code and complete the OAuth prompt.
Prefer a bearer key, or running headless?
claude mcp add --transport http stayingapi https://mcp.stayingapi.com/mcp \ --header "Authorization: Bearer stay_live_YOUR_KEY_HERE"
- EnableDeveloper Mode: Settings → Apps & Connectors → Advanced settings.
- Go toSettings → Connectors → Add MCP server(Create in the Connectors panel).
- Paste the server URL:
- Complete the OAuth sign-in when prompted -no API key needed.
One-click:use theInstall in Cursorbadge at the top of this README.
Manual:add to~/.cursor/mcp.json(global) or.cursor/mcp.json(per project):
{ "mcpServers": { "stayingapi": { "url": "https://mcp.stayingapi.com/mcp" } } }
To use a bearer key instead of the OAuth flow, add aheadersobject with"Authorization": "Bearer stay_live_YOUR_KEY_HERE".
Addhttps://mcp.stayingapi.com/mcpas aStreamable HTTPMCP server.
- Clients that support OAuth 2.1 with Dynamic Client Registration authenticate automatically - nothing to configure.
- Clients that do not can present a bearer key instead:Authorization: Bearer stay_live_....
Only formats verified againststayingapi.com/docs/mcpare listed above on purpose. If your client is not here, the generic Streamable HTTP setup is the whole configuration.
Two ways in, both ending at the same account and the same credit balance:
- OAuth 2.1 + PKCE (S256) with Dynamic Client Registration- recommended for Claude and ChatGPT. You authorize once in a browser popup and the connector is linked to your StayingAPI account. DCR-aware clients discover everything automatically, sono key is ever pasted into the agent.
- Bearer API key- for key-based clients and scripts. Keys arestay_live_...(real fan-out to live sources) orstay_test_...(deterministic sandbox fixtures, always 0 credits). Send asAuthorization: Bearer stay_live_....
One balance, separate rate bucket.MCP calls draw from the same single credit balance as your REST keys. REST is rate-limited per key; MCP is rate-limited per user - separate buckets, one wallet.
Security note:treatstay_live_keys like passwords. A new key's secret is shown once and stored only as a SHA-256 hash, so it is never recoverable. Never commit one to a repo or paste it into a shared config; revoke and re-mint from the dashboard if a key leaks.
All seven areread-only(annotatedreadOnlyHint: true,idempotentHint: true). There are no write tools, so nothing here can book, cancel, or change anything. Each tool maps 1:1 to a REST endpoint, runs the same validation and cache pipeline, and returns the same unified{ data, meta }envelope.
Discover properties across platforms by location, dates, occupancy and filters, merged into one schema. This is the breadth endpoint and the clearest demonstration of "one schema, every platform".
{ "data": [ { "id": "stays_booking_abramovic2", "platform": "booking", "platformListingId": "abramovic2", "url": "https://www.booking.com/hotel/hr/abramovic2.html", "name": "Apartments Abramović", "propertyType": "apartment", "location": { "lat": 43.51, "lng": 16.44, "city": "Split", "country": "HR" }, "starRating": null, "guestRating": 9.1, "ratingScale": 10, "reviewCount": 142, "maxOccupancy": 4, "bedrooms": 2, "bathrooms": 1, "amenities": ["pool", "kitchen", "air_conditioning", "wifi"], "host": { "name": "Marko", "isSuperhost": false }, "price": { "currency": "USD", "nightlyPrice": 303, "totalPrice": 2122, "nights": 7 } } ], "meta": { "platforms": ["airbnb", "booking"], "cached": false, "partial": false, "currency": "USD", "pagination": { "limit": 20, "cursor": null, "nextCursor": "eyJ…", "hasMore": true }, "platformResults": [ { "platform": "airbnb", "status": "ok", "cached": false, "count": 18 }, { "platform": "booking", "status": "ok", "cached": true, "count": 20 } ], "warnings": [] } }
Day-by-day availability for a known listing (or a batch of listings) on one platform over a date window. Each day reports whether it is available, its minimum-night requirement, and whether check-in, check-out and booking are allowed.
{ "data": [ { "platform": "airbnb", "listingId": "42307961", "dates": [ { "date": "2026-07-13", "available": true, "minNights": 7, "checkIn": true, "checkOut": false, "bookable": true }, { "date": "2026-07-14", "available": true, "minNights": 7, "checkIn": false, "checkOut": false, "bookable": true } ] } ], "meta": { "platforms": ["airbnb"], "cached": false, "partial": false, "warnings": [] } }
Full normalized detail for one listing: amenities on a canonical taxonomy, photos, host, geo, ratings, and - when you pass dates - an embedded live price. Detail is cached 24 h and any embedded price at the 1 h price TTL, composed at read time, so a stale price never rides on fresh detail.
{ "data": { "id": "stays_booking_abramovic2", "platform": "booking", "platformListingId": "abramovic2", "name": "Apartments Abramović", "propertyType": "apartment", "location": { "lat": 43.51, "lng": 16.44, "city": "Split", "country": "HR" }, "guestRating": 9.1, "ratingScale": 10, "reviewCount": 142, "maxOccupancy": 4, "bedrooms": 2, "bathrooms": 1, "amenities": ["pool", "kitchen", "air_conditioning", "wifi"], "images": ["https://…"], "host": { "name": "Marko", "isSuperhost": false }, "price": { "currency": "USD", "nightlyPrice": 303, "totalPrice": 2122, "nights": 7 } }, "meta": { "platforms": ["booking"], "cached": false, "partial": false, "warnings": [] } }
A real price quote for one listing, for your dates and occupancy. Pass the platform-native id returned bysearch_stays(numeric on Airbnb and Vrbo, a slug string on Booking.com and Google Hotels) or a full listing URL. The response is always a real numeric price or a typed error -never a different property's price.
{ "data": { "platform": "booking", "listingId": "abramovic2", "currency": "EUR", "nightlyPrice": 303, "totalPrice": 2122, "fees": { "cleaning": null, "service": null, "taxes": null }, "nights": 7, "occupancy": { "adults": 2, "children": 2, "childAges": [8, 13] }, "source": "booking", "url": "https://www.booking.com/hotel/hr/abramovic2.html" }, "meta": { "platforms": ["booking"], "cached": false, "partial": false, "warnings": [] } }
The flagship tool.Compare one property's price across booking sites in a single call, resolved through the Google Hotels backbone. The response carries the individual offers plus StayingAPI-computedminandmedianas first-class fields, so you read the cheapest and typical cross-site price without re-deriving them.
{ "data": { "property": "Hotel X, Sibenik", "checkIn": "2026-07-13", "checkOut": "2026-07-20", "currency": "EUR", "min": 2122, "median": 2151, "offers": [ { "ota": "booking.com", "totalPrice": 2122, "currency": "EUR", "url": "https://…" }, { "ota": "expedia", "totalPrice": 2180, "currency": "EUR", "url": "https://…" } ] }, "meta": { "platforms": ["google"], "cached": false, "partial": false, "warnings": [] } }
Normalized, paginated reviews for one listing on one platform.Native rating scales are preserved and echoed alongside each rating(Airbnb, Vrbo and TripAdvisor use 5; Booking.com, Expedia and Hotels.com use 10) and never silently rescaled, so a 9 and a 4.5 are not accidentally compared.
{ "data": [ { "platform": "booking", "listingId": "abramovic2", "reviewId": "r987", "rating": 9, "ratingScale": 10, "title": "Perfect family stay", "text": "Spotless apartment a short walk from the old town…", "author": "Jane D.", "date": "2026-05-10", "tripType": "family", "language": "en", "ownerResponse": "Thank you!", "liked": "Location and cleanliness", "disliked": null } ], "meta": { "platforms": ["booking"], "cached": false, "partial": false, "pagination": { "limit": 20, "cursor": null, "nextCursor": "eyJ…", "hasMore": true }, "warnings": [] } }
Poll a long-running scrape that was returned as an async job. When a request is projected to run longer than roughly 8 seconds it returns a job handle; the agent callsget_jobuntilstatusiscompletedorfailed.Polling always costs 0 credits- the underlying work is billed once, on successful completion.
Response while running, then on completion (trimmed):
// While running - polling is free { "data": { "jobId": "job_3kf…", "status": "running", "pollUrl": "/v1/jobs/job_3kf…", "estimatedSeconds": 12 }, "meta": { "creditsCharged": 0, "platforms": ["vrbo"] } } // On success - the payload arrives in data.result, in the same unified schema { "data": { "jobId": "job_3kf…", "status": "completed", "result": [ / the endpoint's payload / ] }, "meta": { "platforms": ["vrbo"], "currency": "USD", "platformResults": [ { "platform": "vrbo", "status": "ok", "cached": false, "count": 15 } ], "warnings": [] } }
A failed job still returns successfully withstatus: "failed"and the reason nested atdata.error(a{ type, code, message, retryable }object). Failed work is free.
Every call returns the same unified{ data, meta }envelope, whether the property is a hotel or a holiday home:
Coverage:Booking.com, Airbnb, Vrbo and Google Hotels - hotels and short-term rentals in the same schema, so one integration covers both halves of the accommodation map.
This README stays number-free on paid pricing by design, so it never drifts from the livepricing page. MCP and REST draw from thesame single credit balance- there is no separate MCP wallet or MCP pricing.
Branch onerror.type(the class, mapped 1:1 to the HTTP status) and then onerror.code(a stable, finer-grained reason). Every error also carries arequestId, aretryableflag, and adocUrl.
Codes:missing_api_key,invalid_api_key,revoked_api_key.
- Check the key starts withstay_live_orstay_test_, and that no stray whitespace was copied.
- Confirm the key has not been revoked in your dashboard. A revoked key returnsrevoked_api_keyimmediately.
- On OAuth clients, remove and re-add the connector to re-authorize.
- Auth is checked before validation, billing or any upstream work, so a 401 isnever billed.
Codes:email_unverified,scope_insufficient,subscription_required.
Code:credit_balance_too_low. The balance is below what the call would cost. Check it programmatically instead of guessing - the account endpoint returnscredits.balance,plan, keyenvand yourrateLimit.requestsPerMinute. Top up or upgrade atstayingapi.com/pricing.
Most common codes:missing_parameter,invalid_date_range(checkOutmust be strictly aftercheckIn),date_in_past(evaluated in UTC),child_ages_mismatch(childAges[]length must equalchildren),window_too_long(availability windows cap at 365 days),invalid_cursor,limit_out_of_range,mutually_exclusive_params(you passed bothlistingIdandurl, or neither),needs_country.
needs_countrydeserves a note: a bare Booking.com slug passed toget_listingis ambiguous, because Booking.com slugs arenot globally unique- the same slug exists per country. Pass the country, or pass the full listing URL.
Sign in to leave a review
Use Google, GitHub, or an email account so ratings stay tied to real people.
No reviews posted yet.


