Skip to main content
Glama
README.md
# spotix-mcp

Model Context Protocol (MCP) server for Spotix — lets AI chat models
(ChatGPT, Claude, Gemini, and any other MCP-speaking client) search
Spotix events, quote ticket pricing, place ticket orders, and verify
payment, entirely through natural conversation.

**v1 has no authentication** — every tool call is anonymous. Auth is
planned for a later version; see the version-routing section below for
how a v2 (auth-required or otherwise) would be added without breaking
v1 clients.

## Architecture

```
src/
  index.ts                 Express entrypoint, Streamable HTTP transport,
                            version routing (see below)
  manifest.ts               Aggregates every version's manifest -> GET /manifest.json
  lib/                       Version-agnostic: config, redis, logger, rate limiting,
                            version registry
  api/
    v1/
      server.ts              Builds an McpServer with v1's tools registered
      manifest.ts             v1's entry in the aggregate manifest
      config/                 v1-specific config (server name/title/version)
      data/                   v1-specific constants (limits, currency)
      models/                 zod schemas matching spotix-backend's /mcp/* responses
      lib/                    v1-wide shared logic: the ONE http client every
                            tool uses to call spotix-backend, and the shared
                            error type
      tools/
        search-events/        Each tool is fully self-contained: its MCP
          index.ts             registration + handler, plus a lib/ folder for
          lib/                 logic specific to that tool only.
        get-pricing/
          index.ts
          lib/
        create-ticket-order/
          index.ts
          lib/
        verify-payment/
          index.ts
          lib/
```

Every version gets its own `api/v{n}/` folder with the same shape
(`lib/`, `models/`, `data/`, `config/`, `tools/`). Nothing under
`api/v1/` is imported by any other version — a v2 either forks its own
copies or the pieces that don't change get promoted into `src/lib/`.

## Why the backend, not this server, is authoritative

Every tool is a thin client of `spotix-backend`'s `/v1/mcp/*` routes.
This server never computes a price, checks ticket inventory, or decides
virtual-queue eligibility itself — it calls the backend, which owns
that logic (see `spotix-backend/v1/lib/mcp/`), and formats the response
for a chat model to read. This keeps pricing/inventory/queue rules
defined in exactly one place across every Spotix surface (web, booker,
and now MCP), instead of duplicated and potentially drifting.

## Versioning

- `CURRENT_VERSION` (env var) sets which version this deployment serves
  by default.
- `GET /mcp` (no version in the path) always serves `CURRENT_VERSION`.
- `GET /v{n}/mcp` serves that exact version if it's registered in
  `src/lib/version-registry.ts`.
- `GET /v{n}/mcp` for an **unregistered** version (e.g. requesting
  `/v2/mcp` before v2 exists) falls back to `CURRENT_VERSION` rather
  than erroring — a response header (`X-Spotix-MCP-Version-Fallback`)
  notes when this happened.

To add v2: create `src/api/v2/` mirroring `src/api/v1/`'s shape, export
a `createV2Server()` + manifest, register both in
`src/lib/version-registry.ts`, and bump `CURRENT_VERSION` once it's
ready to become the default. v1 keeps working at `/v1/mcp` regardless.

### Git tags

```bash
npm version patch        # bumps package.json + commits
npm run version:tag      # creates an annotated git tag from that version
git push origin v1.0.1   # push the tag
```

## Tools (v1)

| Tool | What it does |
|---|---|
| `search_events` | Search events by name, date range, state/country, venue, or type. Returns up to 10 best matches with images. |
| `get_pricing` | Live per-ticket-type pricing (all fees included) and remaining availability for one event. |
| `create_ticket_order` | Places an order and returns a Paystack payment link. Refuses (with a website link) if the event's virtual queue is enabled. |
| `verify_payment` | Confirms a payment by reference and returns event details + ticket QR code URLs. |

## Running locally

```bash
cp .env.example .env      # fill in SPOTIX_BACKEND_URL, Upstash creds, etc.
npm install
npm run dev                # tsx watch
```

## Building / deploying

```bash
npm run build              # tsc -> dist/
npm start                  # node dist/index.js
```

## Environment variables

See `.env.example` for the full list. The two most important:

- `SPOTIX_BACKEND_URL` — base URL of spotix-backend's `/v1` API. This
  server calls `${SPOTIX_BACKEND_URL}/mcp/*` for events/pricing/orders
  and `${SPOTIX_BACKEND_URL}/verify-payment` for payment verification.
- `NEXT_PUBLIC_SPOTIX_URL` — the public buyer-facing Spotix site, used
  only to build the `/event/{eventId}` link `create_ticket_order`
  returns when a virtual queue blocks a purchase.