Treeple for AI agents

Treeple runs guided tours in Kazakhstan. This page describes how an AI agent can read the catalogue and hand a booking request to a human on a traveller’s behalf. No registration, no API key, no OAuth.

MCP server

A remote Model Context Protocol server over Streamable HTTP. Point any MCP-capable client at:

https://mcp.treeple.kz/mcp

For Claude Desktop, Claude Code and similar clients:

{
  "mcpServers": {
    "treeple": {
      "type": "http",
      "url": "https://mcp.treeple.kz/mcp"
    }
  }
}
  • search_toursSearch the catalogue by text, type or duration.
  • get_tourItinerary, inclusions, meeting point, cancellation policy and the full price table.
  • get_availabilityDeparture dates, or an honest “on request” when a tour has no fixed calendar.
  • get_quoteAn exact price for a named group and date, valid until the timestamp it returns.
  • create_booking_sessionTurns a quote into a checkout link on treeple.kz, where the traveller enters their own contact details.
  • get_booking_statusThe state of one booking, looked up by its token. There is no lookup by email or phone.
  • submit_booking_requestHands a request to a human manager. Not a reservation, and takes no payment.
  • search_contentPlaces to see, restaurants, travel articles and tour categories — the same search engine the site uses.
  • get_contentOne place, restaurant, article or category in full. A place also lists the tours that actually visit it.

REST API

The MCP server is a thin wrapper over this API — you can call it directly. OpenAPI 3.1 specification:

https://backend.treeple.kz/api/v1/agent/openapi.json

Search the catalogue:

curl "https://backend.treeple.kz/api/v1/agent/tours?lang=en&q=canyon&limit=5"

Submit a booking request:

curl -X POST "https://backend.treeple.kz/api/v1/agent/booking-requests" \
  -H "Content-Type: application/json" \
  -d '{
    "tour_slug": "charyn-canyon-tour-1-day",
    "date": "2026-09-15",
    "pax": { "adults": 2, "children": 0 },
    "lang": "en",
    "contact": { "email": "traveller@example.com" },
    "idempotency_key": "3f6d6d2e-4a1f-4c2b-9c3a-1a2b3c4d5e6f"
  }'

A flat product feed of the whole catalogue is available at:

https://backend.treeple.kz/api/v1/agent/feed.json

Beyond tours

Not every question is about booking. These counts are what the catalogue really holds — an agent promising more than this is inventing it.

  • locations116 places to see, all with coordinates. Each lists the tours that visit it; a curated list, so an empty one means Treeple sells no tour there.
  • tour_types16 tour categories, each with the number of published tours behind it.
  • restaurants5 restaurants — four in Almaty, one in Astana. Cuisine, price range, address, opening hours. No coordinates: the catalogue does not hold them, so no field is returned.
  • articles6 travel articles written by Treeple.
curl "https://backend.treeple.kz/api/v1/agent/content/locations?lang=en&q=Kolsai"
curl "https://backend.treeple.kz/api/v1/agent/content/locations/natspark-kolsay?lang=en"

How fresh this is

The site is rebuilt automatically when the catalogue changes. When the snapshot behind these pages was taken is public:

https://treeple.kz/catalogue-status.json

Fields returned for a tour

These are the exact field names in the response of get_tour and GET /tours/{slug} — not a paraphrase. The authoritative version is the OpenAPI specification linked above.

{
  "slug":              "localised, differs per language",
  "canonical_slug":    "stable identifier, same in every language",
  "title", "summary", "description", "url",
  "duration_days" | "duration_nights" | "duration_hours", "duration_label",
  "types":             ["trekking", "culture", ...],
  "price":             { "basis": "per_person", "currency", "from",
                         "by_group_size": [{ "pax", "price_per_person" }] },
  "itinerary":         [{ "day", "title", "description" }],
  "included":          ["what the price covers"],
  "excluded":          ["what it does not"],
  "meeting_place":     "text",
  "suitable_for", "not_suitable_for", "difficulty", "min_age", "max_age",
  "cancellation_policy": { "source": "tour" | "site_default",
                           "deadline_hours", "service_fee_percent",
                           "tiers": [{ "hours_before_start", "refund_percent" }] },

  "guide_languages":   { "live": [...], "audio": [...] },   // what the GUIDE speaks
  "content_languages": [...],                               // locales the PAGE is published in
  "confirmation_type": "instant" | "manual",
  "availability_type": "scheduled" | "on_request",
  "group":             { "type", "minimum_pax", "maximum_pax" },
  "operator":          "text"
}

A field that is absent from the response means Treeple has no data for it. It does not mean zero, none, or a default — say so instead of assuming. This is why minimum_pax appears only for tours that really have a minimum-departure rule, and why there is no payment_policy field at all.

Two language fields exist and they mean different things. guide_languages is what the guide actually speaks; content_languages is only which locales this web page is published in. Never answer “is there a guide who speaks X” from content_languages.

Things that will otherwise trip you up

  • Prices are per person and change with group size. Every price carries a by_group_size table — quote the row matching the actual group, not the “from” figure. The “from” figure only holds at the group size in min_group_size_for_from: on the Charyn day trip that is $30 at fifteen travellers, while two people pay $155 each.
  • Tour slugs differ per language. canonical_slug is the stable identifier; pass lang explicitly.
  • “on_request” means the date is arranged individually, not that the tour is sold out.
  • Booking requests cannot be read back. A manager contacts the traveller directly; there is no status to poll. This is deliberate — it is what prevents anyone enumerating other people’s requests.
  • Exactly one contact channel per request: email, phone or Telegram. No names, documents or payment details are collected.
  • Every booking request needs a UUID idempotency key. Repeating it within 24 hours returns the original request instead of creating a second lead, so a retry after a timeout is always safe.

Rate limits

  • 60 read requests per minute per IP.
  • 5 booking requests per minute and 20 per day per IP.
  • Over the limit you get 429 with a Retry-After header. Honour it.
  • No API key is required. Partners can request an X-Agent-Key for higher limits.

Privacy

A booking request carries exactly one contact channel and nothing else. Contact values and IP addresses are never written to logs or analytics in the clear — only salted hashes, used to merge duplicate requests. There is no endpoint that returns a booking request, so no one can enumerate other people’s enquiries.

Discovery

Questions, or need higher rate limits for a partner integration? Write to support@treeple.kz.