Toots Jazz Club · API & MCP

Programmatic access to the agenda and ticketing of Toots, the jazz club in Brussels. Read the agenda over plain JSON; reserve tickets through the Model Context Protocol. Amounts are euro cents. Content is available in French, English and Dutch (?locale=fr|en|nl, default fr).

No tool ever accepts card details. An agent can hold seats and attach the buyer, and payment ends with a payment_url that the human buyer opens in their own browser (card or Bancontact, via Stripe), unless the buyer's agent pays with a Link Shared Payment Token the buyer approved for that exact amount (see below). Venue-issued codes are different: a Toots Pass or gift card the buyer provides can be redeemed directly, since no money moves.

MCP server

Endpoint: https://toots.brussels/mcp — Streamable HTTP, stateless, no authentication required. Also advertised at /.well-known/mcp.json.

Connect from Claude Code:

claude mcp add --transport http toots-tickets https://toots.brussels/mcp

Or add it as a custom connector in claude.ai / any MCP-capable client using the endpoint URL above.

Tools

ToolWhat it does
list_eventsUpcoming concerts with date, line-up, genres, prices and availability.
get_eventFull detail of one concert, including the other dates of the same run.
get_availabilityLive seats per session: the stock_id / category_id / price_id lines a hold needs.
hold_ticketsReserves seats and returns a booking_uuid. The hold expires after 15 minutes if unpaid.
set_contactAttaches the buyer (name, email, accepted terms) and returns the payment_url.
redeem_pass / redeem_gift_cardApplies a Toots Pass or gift card code the buyer provided. A fully covered order completes with no payment step; otherwise the balance stays on the payment_url.
pay_with_shared_payment_tokenPays the balance with a Stripe Shared Payment Token from the buyer's Link agent wallet. Charges the buyer; the payment is confirmed by the same webhook as a web payment.
release_bookingGives an unpaid hold's seats back early, when the buyer changes their mind.
get_venue_infoAddress, contact and the venue FAQ — so agents answer house questions from facts.
wait_for_paymentLong-polls a booking (≤25 s) and returns the moment it is paid.
recover_ticketsRe-sends a buyer's ticket links to their email. Links go to the inbox only — the inbox is the proof of ownership.
get_booking_statusPolls the order: awaiting_payment, paid (with the ticket PDF URL and, when configured, Apple/Google Wallet links) or expired.

Tools declare annotations (read-only tools can be auto-approved by clients) and outputSchema; tool errors carry a stable error_code in structuredContent. The concert pages are also exposed as MCP resources (their Markdown twins). One honesty note for developers: holds are real — hold_tickets reserves actual inventory (released after 15 minutes or via release_booking), so test gently.

Flow

  1. list_events → get_availability to find the concert and its price lines.
  2. hold_tickets once the buyer has chosen — never speculatively.
  3. set_contact with the buyer's details; the tickets will be emailed to that address.
  4. Hand the returned payment_url to the buyer; they pay in their browser. Or, with a Link agent wallet, call pay_with_shared_payment_token (see below).
  5. get_booking_status until paid; the response then carries the ticket PDF URL.

Rate limits: 60 requests/minute per IP overall, 5 holds per 15 minutes per IP.

Read-only JSON API

EndpointReturns
GET /api/events.jsonUpcoming concerts with prices, availability and page URLs. Cached 2 min.
GET /api/events/{id}.jsonOne concert in full: bio, line-up, other dates, offer.
GET /api/events/{id}/availability.jsonLive seats per session — same shape as the MCP get_availability tool. Cached 1 min.
GET /agenda.jsonThe original agenda feed (bios in the three languages), kept for existing consumers, now with prices, URLs, badge, ticketingInstructions, booking and originalPicture (the unresized source image). Add ?from=YYYY-MM-DD to look further back than today, or ?id=<craft entry id> to fetch one event — past or upcoming — as a one-element array (id wins if both are given). An unknown or malformed id returns [].
POST /api/tickets/recoverBody {"email": "…"}. Re-sends the ticket links of that address's paid orders — to that address. Always answers a neutral 202; rate limited.

Agent-side payment

Agents with a Link agent wallet can settle an order without the browser handoff. After set_contact (and any pass or gift card), request a Shared Payment Token for exactly amount_to_pay_cents in EUR, scoped to our Stripe network profile profile_61VNUTvZyhaQmxLgqA6VNUTv7A9CUusxmQZ0xC5doSoy; the buyer approves that spend in Link. Then call pay_with_shared_payment_token with the booking_uuid and the spt_… token. We never see card data. Declines, expired tokens and 3-D Secure requests come back as a tool error or a non-paid status, and the payment_url handoff remains the fallback. Charge attempts share the hold rate limit.

Agentic commerce (Stripe)

Besides the MCP server, our concert tickets are published to Stripe's Agentic Commerce Suite: a product catalog with one item per ticket line (a price of a category of a concert date), with live price and availability, that agents connected through Stripe can search, compare and cite. The catalog is refreshed every night and its availability and prices every 15 minutes; a concert that is gone from the site is gone from the catalog. Tickets are priced in EUR, taxes included, with no promotions.

In-agent checkout is on: an agent that Stripe connects to us can complete the purchase inside the conversation. Every order is checked against the current Sapiti price and seats before it is approved, one order covers one concert, and the tickets are sent to the buyer's e-mail address once the payment has gone through.

Whatever the agent does, buyers can always buy the same tickets on the concert page itself, and the MCP server above remains available to agents that speak it directly.

Markdown & discovery