An MCP (Model Context Protocol) server exposing the Luma (lu.ma) Events API to Claude Code, Claude Desktop, and any other MCP client. Written in TypeScript, runs on Bun, talks stdio.
Built and maintained by DEVx Network, a San Diego developer community — we built this to run our own event ops through Claude Code and figured other Luma organizers would want the same thing. Luma has no official MCP server; the community ones we found were all Python and covered a small slice of the API. This one covers the core event-operations surface (events, guests, ticket types, coupons, hosts) properly, with pagination, retries, and typed error handling.
Once installed, your MCP client gets 18 tools (prefixed luma_) for listing/creating/updating
events, managing guests and RSVPs, ticket types, coupons, and hosts — see the full tool
table below. Every tool's description and input schema is generated from a Zod schema, so
an agent can discover what it needs directly from the tool list without reading this file.
- The calendar the API key belongs to must have an active Luma Plus subscription — the API key will not work otherwise.
- Generate a key from your Luma calendar: Settings → Developer.
- Bun
>=1.0.0.
Clone the repo and install dependencies:
git clone https://github.com/DEVxNetwork/luma-mcp.git
cd luma-mcp
bun installclaude mcp add luma -e LUMA_API_KEY=<key> -- bun /absolute/path/to/luma-mcp/src/index.tsAdd to your client's MCP config (e.g. claude_desktop_config.json):
{
"mcpServers": {
"luma": {
"command": "bun",
"args": ["/absolute/path/to/luma-mcp/src/index.ts"],
"env": { "LUMA_API_KEY": "<key>" }
}
}
}| Env var | Required | Default | Meaning |
|---|---|---|---|
LUMA_API_KEY |
yes | — | Sent as the x-luma-api-key header on every request. Treat it as a secret — it grants full manage access to the calendar it belongs to. |
LUMA_API_BASE |
no | https://public-api.luma.com |
Override for tests/mocks. |
LUMA_READ_ONLY |
no | unset | If 1 or true, write tools are never registered — they won't even appear in the client's tool list. Recommended if you only want an agent reading calendar data. |
8 read tools, 10 write tools (18 total). All names are prefixed luma_.
| Tool | Endpoint | Notes |
|---|---|---|
luma_get_self |
GET /v1/users/get-self |
Connectivity/auth smoke tool. |
luma_list_events |
GET /v1/calendars/events/list |
Paginated, defaults pagination_limit to 50. |
luma_lookup_event |
GET /v1/calendars/events/lookup |
Look up by URL or event ID. |
luma_get_event |
GET /v1/events/get |
Full event details. |
luma_list_guests |
GET /v1/events/guests/list |
Paginated; strips noisy fields unless verbose: true. |
luma_get_guest |
GET /v1/events/guests/get |
Strips noisy fields unless verbose: true. |
luma_list_ticket_types |
GET /v1/events/ticket-types/list |
|
luma_list_coupons |
GET /v1/events/coupons/list |
Paginated. |
luma_create_event |
POST /v1/events/create |
|
luma_update_event |
POST /v1/events/update |
Partial update — only send fields to change. |
luma_cancel_event |
POST /v1/events/cancel/request + POST /v1/events/cancel |
Destructive. Two-step flow; requires confirm: true. |
luma_add_guests |
POST /v1/events/guests/add |
Registers guests immediately. |
luma_update_guest_status |
POST /v1/events/guests/update-status |
Approve/decline/waitlist/pending. |
luma_send_invites |
POST /v1/events/guests/send-invites |
Soft invites guests must accept. |
luma_create_ticket_type |
POST /v1/events/ticket-types/create |
|
luma_update_ticket_type |
POST /v1/events/ticket-types/update |
Partial update. |
luma_create_coupon |
POST /v1/events/coupons/create |
|
luma_add_host |
POST /v1/events/hosts/add |
The full Luma API has ~66 endpoints; this server covers 18. The following are intentionally out of
scope for v1 (see docs/implementation-plan.md for rationale):
- Contacts (
/v1/calendars/contacts/*) and contact tags - Event tags (
/v1/calendars/event-tags/*) - Memberships (
/v1/memberships/*) - Webhooks (
/v1/webhooks/*,/v2/webhooks/*) - Organization endpoints (
/v1/organizations/*,/v2/organizations/*) - Calendar-level coupons and calendar event add/approve/reject
- Image upload URLs (
/v1/images/create-upload-url)
Run bun run check:coverage for the full, current list of uncovered endpoints. PRs adding
coverage for any of these are welcome — see AGENTS.md for the conventions this
codebase follows.
bun install
bun run typecheck # tsc --noEmit
bun test # mocked unit tests, no API key needed
bun run check:coverage # verify every tool maps to a real spec endpoint
bun run smoke # live smoke test against the real API — skipped if LUMA_API_KEY is unsetbun run smoke creates a real private event on the calendar tied to your API key and immediately
cancels it, to verify the full request path end to end. It costs nothing and cleans up after
itself, but it does touch the live account — don't point LUMA_API_KEY at a calendar you don't
want test traffic on.
- Only
GETandPOSTare used. Updates arePOST .../update, deletes arePOST .../delete. - List responses are
{ entries: [...], has_more, next_cursor }. This server never auto-paginates — passpagination_cursorback in yourself. - Error response bodies are undocumented by Luma's OpenAPI spec (it only defines
200responses). This server surfaces the raw HTTP status and body text on any non-2xx response rather than guessing at a shape.
If you're an agent using this server (rather than developing it — see AGENTS.md
for that), a few things worth knowing beyond the tool schemas themselves:
- Nothing auto-paginates.
luma_list_eventsandluma_list_guestsreturn at mostpagination_limitentries (default 50) plus anext_cursor. Loop, passingpagination_cursorback in, untilhas_moreisfalse— don't assume the first page is the whole list. luma_cancel_eventis a two-step, destructive flow and requiresconfirm: true. Treat it like any other irreversible action: confirm with the user before calling it.- ID prefixes are meaningful: events are
evt-, guestsgst-, ticket typesttype-. If a tool call fails with a not-found error, check you didn't pass the wrong kind of ID. - If
LUMA_READ_ONLYis set, write tools (create/update/cancel/add/send) simply won't be in your tool list — that's a deliberate deployment choice by whoever configured the server, not a bug. - Rate limit is 200 req/min per calendar key (500/min for org keys); this server retries
429s with backoff automatically, so a slow response usually means it's already handling that for you.
MIT © 2026 DEVx Network