Content
# nightlife-mcp
<a href="https://glama.ai/mcp/servers/alcylu/nightlife-mcp">
<img alt="nightlife-mcp MCP server" src="https://glama.ai/mcp/servers/alcylu/nightlife-mcp/badge" />
</a>
MCP server for nightlife event discovery backed by Supabase.
## Quick Start
**Production endpoint:** `https://api.nightlife.dev/mcp`
1. Get a free API key at [nightlife.dev](https://nightlife.dev)
2. Add to Claude Desktop config (`claude_desktop_config.json`):
```json
{
"mcpServers": {
"nightlife": {
"url": "https://api.nightlife.dev/mcp",
"headers": {
"x-api-key": "YOUR_API_KEY"
}
}
}
}
```
For curl, TypeScript SDK, and other clients, see [`CLIENT_SETUP.md`](CLIENT_SETUP.md).
## Implemented (v0.3)
- `search_events`
- `get_tonight`
- `get_event_details`
- `search_venues`
- `get_venue_info`
- `search_performers`
- `get_performer_info`
- `log_unmet_request`
- `create_vip_booking_request`
- `get_vip_booking_status`
- `get_vip_table_availability`
- `get_vip_table_chart`
- `get_recommendations` (v0.2, behind `MCP_ENABLE_RECOMMENDATIONS=true`)
- Streamable HTTP endpoint with API-key middleware
- Structured tool output schemas (`outputSchema`)
- Deterministic tool error payloads with stable error codes
- Runtime request/tool metrics exposed at `/health`
## Prerequisites
- Node.js 18+
- Supabase project URL + service role key
## Setup
```bash
cp .env.example .env
npm install
```
Set env vars in `.env`:
- `SUPABASE_URL`
- `SUPABASE_SERVICE_ROLE_KEY`
Optional:
- `DEFAULT_CITY` (default: `tokyo`)
- `MCP_TOP_LEVEL_CITIES` (default example: `tokyo,san-francisco`; controls `available_cities` in unsupported-city responses)
- `DEFAULT_COUNTRY_CODE` (default: `JP`)
- `NIGHTLIFE_BASE_URL` (default: `https://nightlifetokyo.com`)
- `MCP_HTTP_REQUIRE_API_KEY` (default: `true`)
- `MCP_HTTP_USE_DB_KEYS` (default: `true`)
- `MCP_HTTP_ALLOW_ENV_KEY_FALLBACK` (default: `true`)
- `MCP_HTTP_API_KEYS` (comma-separated legacy fallback keys)
- `MCP_ENABLE_RECOMMENDATIONS` (default: `false`; enables `get_recommendations`)
## DB API Key Mode (Recommended)
HTTP authentication can use persistent API keys from Supabase plus quota tracking.
1) Run SQL migration in your Supabase SQL editor:
```sql
-- copy file contents from:
-- supabase/migrations/20260219094000_mcp_api_keys.sql
```
2) Ensure DB auth flags are enabled in `.env`:
```bash
MCP_HTTP_REQUIRE_API_KEY=true
MCP_HTTP_USE_DB_KEYS=true
MCP_HTTP_ALLOW_ENV_KEY_FALLBACK=true
```
3) Create an API key record:
```bash
npm run key:create -- --name claude-desktop --tier starter --daily-quota 1000 --minute-quota 60
```
This prints the raw `api_key` once. Save it securely and use it in MCP HTTP calls.
If the DB RPC is unavailable, fallback to `MCP_HTTP_API_KEYS` works only when `MCP_HTTP_ALLOW_ENV_KEY_FALLBACK=true`.
## Concierge Unmet Request Backlog
Public concierge flows can log unsupported user intents to Supabase.
Run migration:
```sql
-- copy file contents from:
-- supabase/migrations/20260226_concierge_unmet_requests.sql
```
Then call MCP tool `log_unmet_request` when no good answer exists from available nightlife data.
## VIP Booking Phase 1
VIP table booking submission and status tracking are backed by Supabase.
Run migration:
```sql
-- copy file contents from:
-- supabase/migrations/20260227143000_vip_phase1_requests_and_queue.sql
-- supabase/migrations/20260228124500_add_vip_booking_enabled_to_venues.sql
-- and if already deployed before 2026-02-28:
-- supabase/migrations/20260228111000_vip_outward_language_defaults.sql
-- supabase/migrations/20260301010000_vip_table_availability_chart.sql
-- supabase/migrations/20260301114000_vip_table_chart_storage_bucket.sql
-- supabase/migrations/20260303093000_vip_dashboard_admin_edits.sql
```
Then call MCP tools:
- `create_vip_booking_request`
- `get_vip_booking_status`
- `get_vip_table_availability` (read per-day table availability by venue/date range)
- `get_vip_table_chart` (read structured table chart with optional per-date status overlay and optional `layout_image_url`)
Conversation policy for `create_vip_booking_request`:
- Confirm booking date/time in venue local time before submitting.
- Use dual-date confirmation wording, especially for late-night arrivals (`00:00`-`05:59`).
- Required confirmation template:
- `Just to confirm: you want a table for [Night Day] night ([Night Date]), arriving around [Time] on [Arrival Day], [Arrival Date] ([Timezone]). I'll submit that as [Night Day] night with [Time] arrival. Is that correct?`
- If the user gives a time like `2am` without a day, ask:
- `Do you mean 2:00 AM after Thursday night (Friday morning), or after Friday night (Saturday morning)?`
- If the user changes day, regenerate confirmation before submission.
Ops-tier sessions also have internal queue tools:
- `list_vip_reservations` (all outstanding reservations; default statuses: `submitted`, `in_review`, `confirmed`)
- `list_vip_requests_for_alerting` (due alerts only)
- `mark_vip_request_alert_sent`
- `claim_vip_request_after_ack`
- `update_vip_booking_status` (set `confirmed`/`rejected`/`cancelled` with audit event)
- `upsert_vip_venue_tables` (write venue table definitions + chart coordinates + optional table notes + optional `layout_image_url`)
- `upsert_vip_table_availability` (write per-date table statuses)
- `upload_vip_table_chart_image` (upload chart image to storage and attach `layout_image_url` to venue table metadata)
To discover bookable venues first, use:
- `search_venues` with `vip_booking_supported_only=true`
- or `get_venue_info` and check `vip_booking_supported`
For internal venue-booking workers, claim queue tasks via DB function:
- `public.claim_next_vip_agent_task(p_agent_id text)`
### VIP Ops Dashboard
Internal dashboard routes:
- `GET /ops/login`
- `POST /ops/login`
- `POST /ops/logout`
- `GET /ops/vip-dashboard`
Internal admin API routes (cookie-session protected):
- `GET /api/v1/admin/vip-bookings`
- `GET /api/v1/admin/vip-bookings/:id`
- `PATCH /api/v1/admin/vip-bookings/:id`
Required env vars:
- `VIP_DASHBOARD_ADMINS` (comma-separated `username:password` pairs)
Optional env vars:
- `VIP_DASHBOARD_SESSION_TTL_MINUTES` (default: `720`)
- `VIP_DASHBOARD_SESSION_COOKIE_NAME` (default: `vip_dashboard_session`)
## Run
Stdio (local desktop clients):
```bash
npm run dev
```
Streamable HTTP:
```bash
npm run dev:http
```
For production build:
```bash
npm run build
npm start
```
For HTTP in production:
```bash
npm run start:http
```
Authenticated production smoke check:
```bash
NLT_API_KEY=... npm run smoke:prod:auth
```
Optional env overrides:
- `NLT_MCP_URL` (default: `https://api.nightlife.dev/mcp`)
- `NLT_REST_BASE_URL` (default: `https://api.nightlife.dev/api/v1`)
- `NLT_SMOKE_CITY` (default: `tokyo`)
Debug web UI for recommendations:
```bash
MCP_ENABLE_RECOMMENDATIONS=true npm run dev:http
# open http://127.0.0.1:3000/debug/recommendations
```
## Notes
- Date handling supports `tonight`, `this_weekend`, `YYYY-MM-DD`, and `YYYY-MM-DD/YYYY-MM-DD`.
- `get_recommendations` returns up to 10 diverse modal slots with dynamic city-aware fallback.
- Venue and performer tools include upcoming events snapshots.
- `log_unmet_request` writes unresolved user asks to `public.concierge_unmet_requests`.
- VIP phase 1 writes booking submissions to `public.vip_booking_requests` and worker queue tasks to `public.vip_agent_tasks`.
- VIP inventory writes table definitions to `public.vip_venue_tables` and date-specific statuses to `public.vip_table_availability`.
- `search_venues` and `get_venue_info` include `vip_booking_supported` so clients can show exactly which venues accept VIP booking submissions.
- `vip_booking_supported` is sourced from `public.venues.vip_booking_enabled` (separate from `guest_list_enabled`).
- `create_vip_booking_request` only accepts venues where `vip_booking_supported=true`.
- City handling is backed by `public.cities` (`slug`, timezone, and service-day cutoff).
- Supported top-level cities are environment-configurable (for example `tokyo` and `san-francisco`) while Tokyo can remain the default.
- Stdio transport: no API key check.
- HTTP transport (`/mcp`): API key required by default (`MCP_HTTP_REQUIRE_API_KEY=true`).
- API key headers:
- `Authorization: Bearer <key>`
- `x-api-key: <key>`
- HTTP responses include key tier/source and rate-limit headers when DB-backed auth is active:
- `X-API-Key-Tier`
- `X-API-Key-Source`
- `X-RateLimit-Daily-Limit`
- `X-RateLimit-Daily-Remaining`
- `X-RateLimit-Minute-Limit`
- `X-RateLimit-Minute-Remaining`
- Health endpoint: `/health`.
- Debug page for manual tool testing: `/debug/recommendations`.
- Tool errors are returned as JSON text payloads in `result.content[0].text`:
- `INVALID_DATE_FILTER`
- `INVALID_EVENT_ID`
- `UNSUPPORTED_EVENT_ID`
- `EVENT_NOT_FOUND`
- `INVALID_VENUE_ID`
- `VENUE_NOT_FOUND`
- `INVALID_PERFORMER_ID`
- `PERFORMER_NOT_FOUND`
- `INVALID_BOOKING_REQUEST`
- `BOOKING_REQUEST_NOT_FOUND`
- `BOOKING_STATUS_UPDATE_FAILED`
- `VIP_TASK_NOT_AVAILABLE`
- `VIP_ALERT_UPDATE_FAILED`
- `VIP_CLAIM_FAILED`
- `INVALID_REQUEST`
- `REQUEST_WRITE_FAILED`
- `DB_QUERY_FAILED`
- `INTERNAL_ERROR`
## Contributing & CI
See [`CONTRIBUTING.md`](./CONTRIBUTING.md) for the workflow and rules. AI agents read [`AGENTS.md`](./AGENTS.md). `CLAUDE.md` is the architecture source of truth.
MCP Config
Below is the configuration for this MCP Server. You can copy it directly to Cursor or other MCP clients.
mcp.json
Connection Info
You Might Also Like
Filesystem
Node.js MCP Server for filesystem operations with dynamic access control.
Fetch
Retrieve and process content from web pages by converting HTML into markdown format.
Agent-Reach
Give your AI agent eyes to see the entire internet. Read & search Twitter,...
Context 7
Context7 MCP provides up-to-date code documentation for any prompt.
context7-mcp
Context7 MCP Server provides natural language access to documentation for...
mempalace
The highest-scoring AI memory system ever benchmarked. And it's free.