Build your own client with the Gondola MCP

Last updated September 9, 2026

This guide is for developers building their own MCP client or integration on top of the Gondola MCP server, for example embedding Gondola hotel, flight, and rental car search into your own assistant. Hotel and rental car tools can hand supported options to checkout. Flight search is discovery-only and names its source; flights cannot be booked through Gondola yet. If you just want to use Gondola from Claude Code, Claude Desktop, ChatGPT, or Cursor, those clients handle all of this for you, so you do not need this page.

The Gondola MCP server is a standard OAuth 2.1 protected resource. If your client implements standard MCP discovery and the authorization-code flow with PKCE, it works out of the box. You should never hand-build or hard-code tokens.

Find the server on MCP registries

The Gondola MCP server is listed on Glama and Smithery, where you can browse its tool list and install it into supported clients.

Endpoints

PurposeURL
Interactive MCP endpointhttps://mcp.gondola.ai/mcp/auth
Public registry-discovery endpointhttps://mcp.gondola.ai/mcp
Protected-resource metadata (RFC 9728)https://mcp.gondola.ai/.well-known/oauth-protected-resource
Authorization serverhttps://www.gondola.ai
Authorization-server metadata (RFC 8414)https://www.gondola.ai/.well-known/oauth-authorization-server

Discover everything from the metadata documents rather than hard-coding paths. The authorization-server metadata advertises the authorization, token, registration, and revocation endpoints.

Every tool call requires a signed-in user

Use the interactive endpoint for end-user clients. Its first unauthenticated request returns 401 with the WWW-Authenticate challenge required to start standard MCP OAuth.

The separate registry-discovery endpoint serves initialize, notifications/initialized, ping, and tools/list anonymously, rate limited per IP, so registries and directories can list the server. Its successful discovery responses include advisory OAuth metadata, but clients must not rely on a challenge attached to a 200 response to start OAuth.

Every tools/call requires a bearer token. If you built against an earlier version that let you search without an account, that path is gone: authenticate before calling a tool. An expired or malformed token is rejected everywhere, including on discovery, so a stale credential still triggers your refresh flow rather than silently downgrading you to anonymous.

The account behind the token also has to have finished Gondola onboarding, which means either connecting an email inbox or having full site access. A valid token for an account that has not done that gets 403 with {"error": "MCP access requires completed onboarding"}. Treat 403 differently from 401: it is not a token problem, so re-running the OAuth flow will not fix it. Tell the user to finish setup at gondola.ai and try again.

How discovery works

Your client does not configure tools manually. It authenticates against the interactive endpoint and calls the standard tools/list method, which returns each tool with its name, description, and input schema. Registries can read the full public catalog from the discovery endpoint without a token. Once you authenticate, the list narrows to the tools your granted scopes allow.

Authorization flow

  1. Send any request to https://mcp.gondola.ai/mcp/auth with no or expired credentials. The server responds 401 with a WWW-Authenticate: Bearer ... resource_metadata="https://mcp.gondola.ai/.well-known/oauth-protected-resource" header.
  2. Fetch the protected-resource metadata. It returns the authorization_servers list pointing at https://www.gondola.ai.
  3. Fetch the authorization-server metadata to learn the authorization, token, registration, and revocation endpoints.
  4. Register your client with Dynamic Client Registration (RFC 7591) if you do not already have a client_id. See below.
  5. Run the authorization-code flow with PKCE (S256 is required). The user signs in to Gondola in a browser and approves the requested scopes.
  6. Exchange the code at the token endpoint for an access token, plus a refresh token if you registered for it.
  7. Send the access token as Authorization: Bearer <token> on MCP requests.

Dynamic client registration

POST https://www.gondola.ai/api/oauth/register (open registration, no auth required). Example body:

{
  "client_name": "Your App",
  "client_uri": "https://your-app.example.com",
  "redirect_uris": ["https://your-app.example.com/oauth/callback"],
  "grant_types": ["authorization_code", "refresh_token"],
  "response_types": ["code"],
  "token_endpoint_auth_method": "none"
}

A few rules:

  • redirect_uris must be https, loopback http for local development, or Cursor's legacy DCR/fallback compatibility URI, cursor://anysphere.cursor-mcp/oauth/callback. Current Cursor clients document loopback HTTP for desktop, but may still include the custom URI during dynamic registration. Redirects exact-match at authorize time, may not contain fragments, and are limited to 10 entries.
  • Include refresh_token in grant_types to receive refresh tokens.
  • For token_endpoint_auth_method, use none for a public client (PKCE protects the exchange) or client_secret_post to receive a client_secret. The secret is shown only once at registration and stored as a hash, so capture it then.
  • The response also returns a registration_access_token. Keep it for future client management.

Scopes

ScopeGrants
mcp:readSearch, plus reading the member's own trips, loyalty accounts, and saved searches. Granted by default when scope is omitted.
mcp:writeCreate and delete price alerts on the member's account. Must be requested and approved explicitly.
mcp:bookCharge a saved card to book, cancel a rental, and list saved payment methods. Approved booking partners only — see below.

Request mcp:read mcp:write. That is the full surface available through the public connect flow, and it covers everything except charging a card.

mcp:book is not obtainable by registering a client and asking for it. If a client requests it, the authorization server narrows it away and issues the rest, so the connection still works — you simply won't be offered book_hotel, book_vehicle, cancel_vehicle_booking, or get_payment_methods. Those tools are filtered out of tools/list for your connection, and calling one anyway returns a message pointing at the checkout link instead.

To book, use get_booking_link (hotels) or get_vehicle_booking_link (cars): they return a Gondola checkout URL for the exact rate you selected, and the traveler completes payment there. If you are integrating as a booking partner and need the in-conversation path, contact us — it is granted per client, out of band.

Rate limits

Limits are per signed-in user, not per client, so a user with two integrations shares one budget.

An overall gateway ceiling of 30 requests per minute, 200 per hour, and 500 per day applies across all tools. Exceeding it returns 429 with a Retry-After header in seconds and an X-RateLimit-Horizon header naming which window you hit (minute, hour, or day). Honour Retry-After rather than backing off on a guess, because the three windows recover on very different timescales.

Tools that reach the same paid supplier also share a budget, so switching tools does not buy more capacity:

BudgetPer minutePer hourPer day
Hotel and vehicle supply1040100
Flight search1040100
Event search630100
Hotel reviews1060200
Creating and editing data51540
Booking and cancellation136

Which tools draw on which budget:

  • Hotel and vehicle supply: search_hotels, get_hotel_rates, compare_rates, get_similar_hotels, get_multi_night_rates, diagnose_rates, search_vehicles, get_vehicle_details. get_hotel_details now returns stored property information and amenities only and does not draw on this budget; call get_hotel_rates with dates when you need prices.
  • Flight search: search_flights returns source-attributed discovery results, cash fares, and any cached award pricing right away. It starts award lookups for the rest; get_flight_points polls for those results with the returned search_id and is free, since the supplier spend was already charged to the search. Flight booking is not available through Gondola yet.
  • Event search: search_events
  • Hotel reviews: get_hotel_reviews
  • Creating and editing data: create_rate_alert, delete_rate_alert, update_traveler_profile
  • Booking and cancellation: book_hotel, book_vehicle, and cancel_vehicle_booking when confirmed

Most calls cost one unit, but a few cost more because they fan out behind the scenes. compare_rates costs one unit per hotel you pass, up to five. get_similar_hotels costs three. A search_flights call with a return date costs three because the round-trip fallback fans out; a one-way search costs one. Previewing a cancellation is free, and only confirm: true spends a booking unit.

The hotel and vehicle row is the one most integrations hit first, since almost every hotel and car tool draws on it. Comparing five hotels and then asking for similar ones is already eight of the ten units you get per minute.

When a supplier budget is exhausted, the tool returns a normal successful result whose text explains the budget was reached, rather than a protocol error. Surface that text to the user as a "try again shortly" state instead of treating it as an empty result.

A 503 with Retry-After means the limiter itself is briefly unavailable and the request was refused rather than risk spending supplier capacity. Retry after the interval.

If you are a partner whose integration genuinely needs more headroom, contact us rather than working around the limits with multiple accounts.

Token lifetimes and rotation

  • Access token: a signed JWT sent as a bearer token. Revocation is enforced on every request independent of the token's own expiry, so a Disconnect by the user or a re-consent takes effect within about 30 seconds regardless.
  • Refresh token: opaque, stored hashed, and rotated on every use. Each refresh returns a new refresh token and invalidates the one you presented. Always persist the newest refresh token you receive and discard the old one.
  • Authorization code: single-use, 5-minute lifetime, PKCE-bound.

Refresh-token reuse detection

Gondola rotates refresh tokens and detects reuse (RFC 6819 section 5.2.2.3). If a refresh token that has already been rotated is presented again, the server treats it as a theft signal and revokes the entire token family for that user and client. The user then has to sign in again.

What this means for you:

  • Never present a refresh token more than once. After a successful refresh, use only the new one.
  • Never replay an old refresh token to "test" it. By design that is indistinguishable from an attacker replaying a stolen token, and it will revoke the live session too.
  • If two parts of your app might refresh at the same time, serialize refreshes so you never present the same token twice.

Re-authentication

When a refresh fails because the family was revoked (the user disconnected, reuse was detected, or a re-consent happened), there is no silent recovery. Start a fresh authorization-code flow and have the user sign in again. Surface a clear "reconnect" action rather than failing silently.

Security do's and don'ts

  • Do store tokens in OS-level secure storage (Keychain, Credential Manager, and the like), never in logs or chat transcripts.
  • Do persist and rotate to the newest refresh token on every refresh.
  • Do handle 401 with WWW-Authenticate by driving the standard flow, not by asking the user to paste a token.
  • Don't retry the OAuth flow on a 403. The token is fine and the account has not finished onboarding, so a retry loop just sends the user through sign-in repeatedly.
  • Don't retry a 429 immediately. Wait for Retry-After, and check X-RateLimit-Horizon before assuming a short pause is enough.
  • Don't print access or refresh tokens into any model context or chat. If a token is ever exposed, the user can revoke it instantly at Connected Agents.
  • Don't replay or reuse a rotated refresh token.

Questions

Reach out to the Gondola team. We are happy to help partners land a clean integration before they rely on it in production.