A Model Context Protocol server that lets AI agents search and book Lakpura® tours, transfers and stays — ending in a hosted Stripe checkout URL the customer pays.
https://mcp.lakpura.comPOST (single JSON response; no SSE)com.lakpura/mcp v1.0.12025-06-18application/json on request and responseOpen by default — no credentials required. search_* and get_service return public catalogue data, and start_booking only returns a hosted Stripe URL (no payment credentials cross the wire).
The operator can require a bearer token by setting MCP_BEARER_TOKEN server-side; when set, every request must send Authorization: Bearer <token> or receive 401 (JSON-RPC error -32001).
Standard MCP lifecycle. All real calls are POST. A GET to the endpoint with Accept: application/json returns a plain server descriptor (name, version, protocol, transport); a browser GET returns this page.
| Method | Purpose |
|---|---|
initialize | Handshake — negotiates protocol version, returns serverInfo, capabilities and usage instructions. |
notifications/initialized | Client → server notification after init. No response (202). |
tools/list | Returns the tool catalogue with inputSchema for each tool. |
tools/call | Invokes a tool by name with arguments. Result is content: [{ type:"text", text:"<JSON>" }] plus an isError flag. |
ping | Liveness check — returns {}. |
JSON-RPC batches (an array of request objects) are supported. Requests without an id are notifications and get no response.
Search Lakpura accommodation (hotels, villas, lodges) by name or city. Returns matching stays with their public page URL, city, country and star rating. Use get_service with a returned slug for room details and price.
| Param | Type | Description | |
|---|---|---|---|
query | required | string | Hotel/villa name or city (e.g. "Galle", "Cinnamon", "Ella tree house"). |
limit | optional | integer | Max results (default 12). |
Search Lakpura tours, day-trips and experiences by keyword. Returns each match with a slug, title, rating and public page URL. Call get_service with a slug to see bookable options and price, then start_booking.
| Param | Type | Description | |
|---|---|---|---|
query | optional | string | Keyword(s) matched against the tour title (e.g. "whale watching", "sigiriya", "safari"). |
kind | optional | enum | all · multi_day · single_day. Default all. |
page | optional | integer | Page number (default 1). |
per_page | optional | integer | Results per page (default 20). |
Get full details of one tour/experience by slug: title, description, bookable options (each with a price and option_id) and whether it can be booked via start_booking.
| Param | Type | Description | |
|---|---|---|---|
slug | required | string | The service slug from search_tours (the last path segment of /products/{slug}). |
Create a booking and get a secure Stripe checkout URL for the customer to pay. Price is calculated server-side and returned with the checkout_url; payment confirms the booking.
product_type = tour product_type = transfer
| Param | Type | Description | |
|---|---|---|---|
product_type | required | enum | tour · transfer — what is being booked. |
lead_first_name | required | string | Customer first name. |
lead_surname | required | string | Customer surname. |
lead_email | required | string | Customer email (booking confirmation is sent here). |
lead_phone | optional | string | Customer phone (E.164 preferred). |
pax | optional | integer | Number of guests/passengers (default 1). |
slug | optional | string | tour: service slug from search_tours/get_service. |
option_id | optional | string | tour: chosen option_id from get_service (omit for the "from" price). |
selected_date | optional | string | tour: travel date, YYYY-MM-DD (today or later). |
selected_start_time | optional | string | tour: start time, e.g. "09:00". |
pickup_text | optional | string | tour: pickup location / hotel. |
from | optional | string | transfer: pickup location (airport / city / hotel). |
to | optional | string | transfer: drop-off location. |
vehicle | optional | string | transfer: vehicle class (default "Standard Car"). |
category | optional | string | transfer: e.g. "Arrival Transfers", "Departure Transfers" (default Arrival). |
pickup_at | optional | string | transfer: pickup datetime (free text or ISO). |
airline | optional | string | transfer: airline (airport transfers). |
flight_number | optional | string | transfer: flight number. |
notes | optional | string | transfer: free-text notes. |
Tours: search_tours → get_service (pick an option_id) → start_booking → open the returned checkout_url.
Transfers: start_booking with product_type="transfer", from/to and lead details → open checkout_url.
Stays: search_stays → get_service for room details. (Stay booking is a page handoff, not an in-protocol start_booking today.)
Handshake, then list tools:
# initialize
curl -s https://mcp.lakpura.com \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize",
"params":{"protocolVersion":"2025-06-18",
"clientInfo":{"name":"my-agent","version":"1.0"}}}'
# list tools
curl -s https://mcp.lakpura.com \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}'
Call a tool (search_tours):
curl -s https://mcp.lakpura.com \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":3,"method":"tools/call",
"params":{"name":"search_tours",
"arguments":{"query":"whale watching"}}}'
Transport failures use JSON-RPC error objects; tool-level failures come back as a normal result with isError: true and an { "error": "…" } payload in the text content.
| Code | Meaning |
|---|---|
-32700 | Parse error (malformed JSON) |
-32600 | Invalid Request |
-32601 | Method not found |
-32602 | Invalid params / unknown tool |
-32001 | Auth required / invalid bearer token (401) |
-32603 | Internal error / service unavailable |