{
  "markdown": "# luma-mcp\n\n\n<!-- mycelium-badges:start -->\n\n<p>\n  <a href=\"https://github.com/adelaidasofia/luma-mcp/blob/main/LICENSE\"><img alt=\"License\" src=\"https://img.shields.io/github/license/adelaidasofia/luma-mcp?color=blue\"></a>\n  <a href=\"https://github.com/adelaidasofia/luma-mcp/stargazers\"><img alt=\"GitHub stars\" src=\"https://img.shields.io/github/stars/adelaidasofia/luma-mcp?color=eab308\"></a>\n  <a href=\"https://github.com/adelaidasofia/luma-mcp/commits/main\"><img alt=\"Last commit\" src=\"https://img.shields.io/github/last-commit/adelaidasofia/luma-mcp\"></a>\n  <a href=\"https://github.com/adelaidasofia/luma-mcp/issues\"><img alt=\"Open issues\" src=\"https://img.shields.io/github/issues/adelaidasofia/luma-mcp\"></a>\n  <a href=\"https://pypi.org/project/adelaidasofia-luma-mcp/\"><img alt=\"PyPI version\" src=\"https://img.shields.io/pypi/v/adelaidasofia-luma-mcp?color=blue&label=pypi\"></a>\n  <a href=\"https://pypi.org/project/adelaidasofia-luma-mcp/\"><img alt=\"PyPI downloads\" src=\"https://img.shields.io/pypi/dm/adelaidasofia-luma-mcp?color=blue&label=downloads\"></a>\n  <a href=\"https://myceliumai.co\"><img alt=\"Built by Mycelium AI\" src=\"https://img.shields.io/badge/built_by-Mycelium_AI-15B89A\"></a>\n</p>\n\n<!-- mycelium-badges:end -->\n\nlu.ma events MCP server. Create events, set ticket prices, issue coupon codes, list RSVPs, and email attendees. All writes go through draft+confirm so nothing posts to Luma until you explicitly approve. Built on the official Luma public API.\n\n## What it does\n\n- Create + update lu.ma events (name, date, timezone, capacity, meeting URL, visibility, cover image)\n- Set ticket types and pricing\n- Issue coupon codes (calendar-scoped or event-scoped, percentage or fixed-cents discounts, redemption caps)\n- List event guests / RSVPs\n- Send markdown emails to attendees (pre-work, day-of, follow-up)\n- Audit log of every API call (JSONL with key/token redaction)\n- Prompt-injection scrubber on user-supplied free-text fields\n\n## Tools (v0.1.0)\n\nReads (call API directly):\n\n- `luma_health` — auth check + draft store size\n- `luma_get_event` — fetch one event by ID\n- `luma_list_events` — paginated calendar listing\n- `luma_list_event_guests` — RSVPs filtered by status\n- `luma_list_coupons` — calendar or event-scoped\n\nWrites (draft+confirm pairs):\n\n- `luma_create_event_draft` / `luma_create_event_confirm`\n- `luma_update_event_draft` / `luma_update_event_confirm`\n- `luma_create_ticket_type_draft` / `luma_create_ticket_type_confirm`\n- `luma_create_coupon_draft` / `luma_create_coupon_confirm`\n- `luma_send_event_email_draft` / `luma_send_event_email_confirm`\n\nPlus:\n\n- `luma_cancel_draft` — cancel an unconfirmed draft (idempotent)\n\n14 tools total.\n\n## Architecture\n\n```\nluma-mcp/\n├── pyproject.toml\n├── README.md\n├── SETUP.md\n├── LICENSE\n├── .env.example\n├── luma_mcp/\n│   ├── __init__.py\n│   ├── server.py             FastMCP entry point + .env loader\n│   ├── client.py             HTTP wrapper around api.lu.ma/public/v1\n│   ├── drafts.py             Thread-safe draft store with TTL\n│   ├── audit.py              JSONL audit log with redaction\n│   ├── scrubber.py           Prompt-injection neutralizer\n│   ├── _shared/              Day-1 shared utilities\n│   │   ├── normalize.py      Timezone alias + datetime helpers\n│   │   └── types.py          Permissive typed shapes for API responses\n│   └── tools/\n│       ├── health.py         luma_health, luma_cancel_draft\n│       ├── events.py         create / update / get / list events\n│       ├── tickets.py        create ticket types\n│       ├── coupons.py        create / list coupons\n│       ├── guests.py         list event guests\n│       └── emails.py         send email to attendees\n└── tests/integration/\n    └── test_full_pipeline.py 10-step bare-runnable verification\n```\n\n## Safety patterns\n\n1. **Draft + confirm on every write.** The draft tool returns a `draft_id`; nothing hits Luma until the matching confirm tool is called. Drafts expire after 1 hour and can only be confirmed once.\n2. **Audit log.** Every API call is logged JSONL with `ts`, `tool`, `action`, args (redacted), `status`, `latency_ms`. Path: `~/.claude/luma-mcp/audit.log`.\n3. **Token redaction.** Strings matching long-key heuristics, or values under keys like `api_key`, `token`, `cookie`, `secret`, are masked before logging.\n4. **Prompt-injection scrubber.** User-supplied free-text fields (event name, description, email subject, email body) are passed through `unicodedata.normalize(\"NFKC\")`, stripped of zero-width characters, and have role-spoof prefixes / fake fences wrapped in backticks (preserving operator visibility, neutralizing model effect on downstream reads).\n5. **Zero LLM in the tool path.** Every routing decision is rule-based.\n\n## Use cases\n\n- **Workshops + paid events** — set sticker price, issue community-specific 100%-off coupons, pull guest list, blast pre-work email.\n- **Multi-event programs** — one cohorte announcement, sub-events on Luma, pull RSVPs across sessions.\n- **Recurring meetups** — duplicate event template via update_event_draft, change date, ship.\n\n## Install\n\nOpen Claude Code, paste:\n\n    /plugin marketplace add adelaidasofia/luma-mcp\n    /plugin install luma-mcp@luma-mcp\n\nTwo prerequisites for the server to authenticate:\n\n1. **Luma Plus subscription** on the calendar you'll use (the public API is gated behind Plus).\n2. **API key** generated from `https://lu.ma/settings/api`, dropped into `~/.claude/luma-mcp/.env` as `LUMA_API_KEY=...`.\n\nAfter both steps, restart Claude Code. Tools appear under `mcp__luma__*`.\n\n<details>\n<summary>Legacy install</summary>\n\nSee `SETUP.md` for the manual `.mcp.json` registration path. The plugin install above replaces it.\n\n</details>\n\n## Verification\n\n```bash\ncd ~/.claude/luma-mcp && python3 tests/integration/test_full_pipeline.py\n# expected: PASSED — luma-mcp v0.1.0 integration test (10 steps green)\n```\n\nThen in a Claude Code session: `mcp__luma__luma_health()` → `{ok: true, user: {...}}`.\n\n## Rate limit\n\nLuma's public API caps at 200 requests / minute / calendar. The client does not auto-retry on 429; it surfaces the error and lets the operator pace.\n\n## Related MCPs\n\nSame author, same architecture pattern (FastMCP, draft+confirm on writes, vault auto-export where applicable):\n\n- [slack-mcp](https://github.com/adelaidasofia/slack-mcp) — multi-workspace Slack\n- [imessage-mcp](https://github.com/adelaidasofia/imessage-mcp) — macOS iMessage\n- [whatsapp-mcp](https://github.com/adelaidasofia/whatsapp-mcp) — WhatsApp via whatsmeow\n- [apollo-mcp](https://github.com/adelaidasofia/apollo-mcp) — Apollo.io CRM + sequences\n- [google-workspace-mcp](https://github.com/adelaidasofia/google-workspace-mcp) — Gmail / Calendar / Drive / Docs / Sheets\n- [substack-mcp](https://github.com/adelaidasofia/substack-mcp) — Substack writing + analytics\n- [parse-mcp](https://github.com/adelaidasofia/parse-mcp) — markitdown / Docling / LlamaParse router\n\n\n## Telemetry\n\nThis plugin sends a single anonymous install signal to `myceliumai.co` the first time it loads in a Claude Code session on a given machine.\n\n**What is sent:**\n- Plugin name (e.g. `slack-mcp`)\n- Plugin version (e.g. `0.1.0`)\n\n**What is NOT sent:**\n- No user identifiers, names, emails, tokens, or API keys\n- No file paths, message content, or anything from your work\n- No IP address is stored after dedup processing\n\n**Why:** Helps the maintainer know which plugins people actually install, so attention goes to the ones that get used.\n\n**Opt out:** Set the environment variable `MYCELIUM_NO_PING=1` before launching Claude Code. The hook will skip the network call entirely. Already-pinged installs leave a sentinel at `~/.mycelium/onboarded-<plugin>` — delete it if you want to reset state.\n\n## License\n\nMIT. See `LICENSE`.\n",
  "bytes": 7751,
  "sha": "a3cacce514fd2f54887c4363b0ed5c3c14795d5de0eed655765f0fbc8b95985e",
  "repo_slug": "adelaidasofia/luma-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/plg_adelaidasofia_luma_mcp_luma_mcp_c01add9b/readme"
}