Background
vrc.tl ("Timeline") is a public, unauthenticated site that aggregates VRChat club events (timeline view, club pages, event detail pages). Since it works without VRChat auth, we can likely integrate it as an optional, read-only data source in this MCP server.
I did a quick Playwright/network pass and confirmed it uses a small set of JSON endpoints under https://vrc.tl/api/v1/.
API endpoints observed (no auth)
-
GET https://vrc.tl/api/v1/events
- Response shape:
{ lastUpdates, eventData, live, range }
range: { firstLoadedDay: "YYYY-MM-DD", lastLoadedDay: "YYYY-MM-DD" } (seems to default to a small window around “now”; query params like from/to and start/end were ignored in my tests)
eventData: { events, organizers, performers }
events[] item keys (sample): id, name, description, category, tags, organizers, hostOrganizer, start, end, duration, urls, poster, isHighlighted, extensions, promoted, eventSlots, showSlots
- Important:
category is numeric; tags is an array of numeric IDs; event organizers are referenced by numeric IDs.
-
GET https://vrc.tl/api/v1/events/{eventId}
- Response shape:
{ events, organizers, performers }
events is an array (observed events.length === 1) and includes the detailed event object.
- Event object includes
eventSlots[] with per-slot start/duration/performers/flag.
-
GET https://vrc.tl/api/v1/organizers
- Returns an array of organizer/club objects (observed ~852).
- Keys (sample):
id, name, shortCode, slug, vrcGroup, discordInv, twitter, blueSky, instagram, twitch, mixcloud, logo, banner, isSupporter, providesInstances, ...
-
GET https://vrc.tl/api/v1/organizer/{organizerId}/events?page={n}
- Response shape:
{ page, hasMorePages, data }
data: { organizers, events, performers } (dataset pattern again)
-
GET https://vrc.tl/api/v1/organizer/{organizerId}/collaborators
- Response shape:
{ organizers: [...] }
Proposed MCP tools
Name bikeshed, but roughly:
vrctl_events_current
- Calls
/api/v1/events
- Returns compact list of events in the returned
range window, with resolved organizer names + key links.
vrctl_event_get
- Calls
/api/v1/events/{eventId}
- Returns event details + resolved organizers/performers + slot schedule.
vrctl_organizers_search
- Calls
/api/v1/organizers (cached), filters by name/slug/shortCode.
- Returns small summaries + IDs for follow-ups.
vrctl_organizer_get
- Uses cached organizers list (or a future
/api/v1/organizer/{id} if it exists) and returns details.
vrctl_organizer_events
- Calls
/api/v1/organizer/{id}/events?page={n}.
vrctl_organizer_collaborators
- Calls
/api/v1/organizer/{id}/collaborators.
Notes / open questions
- Category + tag ID mapping: API exposes numeric IDs; the website has human labels (Music/Podcast/etc and tags like Windows/Android/flashing lights). We need a mapping strategy:
- Option A: ship a mapping table (derived from vrc.tl frontend) and keep it updated.
- Option B: return numeric IDs + “best-effort” labels only for a small stable subset.
- Events range expansion:
/api/v1/events appears to return a limited window; need to determine how the site loads more days (if it does) and whether there’s an undocumented endpoint/param for requesting arbitrary ranges.
- Caching: organizers list is large; should be cached with TTL and invalidation.
Acceptance criteria
- New read-only tools added behind a clear namespace/prefix (e.g.
vrctl_*).
- Tool outputs are curated (compact lists by default, include IDs for follow-ups).
- Add basic tests (mock responses) to lock response parsing + tool output shape.
Background
vrc.tl ("Timeline") is a public, unauthenticated site that aggregates VRChat club events (timeline view, club pages, event detail pages). Since it works without VRChat auth, we can likely integrate it as an optional, read-only data source in this MCP server.
I did a quick Playwright/network pass and confirmed it uses a small set of JSON endpoints under
https://vrc.tl/api/v1/.API endpoints observed (no auth)
GET https://vrc.tl/api/v1/events{ lastUpdates, eventData, live, range }range:{ firstLoadedDay: "YYYY-MM-DD", lastLoadedDay: "YYYY-MM-DD" }(seems to default to a small window around “now”; query params likefrom/toandstart/endwere ignored in my tests)eventData:{ events, organizers, performers }events[]item keys (sample):id, name, description, category, tags, organizers, hostOrganizer, start, end, duration, urls, poster, isHighlighted, extensions, promoted, eventSlots, showSlotscategoryis numeric;tagsis an array of numeric IDs; event organizers are referenced by numeric IDs.GET https://vrc.tl/api/v1/events/{eventId}{ events, organizers, performers }eventsis an array (observedevents.length === 1) and includes the detailed event object.eventSlots[]with per-slotstart/duration/performers/flag.GET https://vrc.tl/api/v1/organizersid, name, shortCode, slug, vrcGroup, discordInv, twitter, blueSky, instagram, twitch, mixcloud, logo, banner, isSupporter, providesInstances, ...GET https://vrc.tl/api/v1/organizer/{organizerId}/events?page={n}{ page, hasMorePages, data }data:{ organizers, events, performers }(dataset pattern again)GET https://vrc.tl/api/v1/organizer/{organizerId}/collaborators{ organizers: [...] }Proposed MCP tools
Name bikeshed, but roughly:
vrctl_events_current/api/v1/eventsrangewindow, with resolved organizer names + key links.vrctl_event_get/api/v1/events/{eventId}vrctl_organizers_search/api/v1/organizers(cached), filters byname/slug/shortCode.vrctl_organizer_get/api/v1/organizer/{id}if it exists) and returns details.vrctl_organizer_events/api/v1/organizer/{id}/events?page={n}.vrctl_organizer_collaborators/api/v1/organizer/{id}/collaborators.Notes / open questions
/api/v1/eventsappears to return a limited window; need to determine how the site loads more days (if it does) and whether there’s an undocumented endpoint/param for requesting arbitrary ranges.Acceptance criteria
vrctl_*).