MCP server for Vibo — plan your event music as a host/couple: events, timeline sections, song requests, playlists, and exports, via natural language.
Add to .mcp.json in your project or ~/.claude/mcp.json:
json
{
"mcpServers": {
"vibo": {
"command": "npx",
"args": ["-y", "vibo-mcp"],
"env": {
"VIBO_EMAIL": "you@example.com",
"VIBO_PASSWORD": "your_password"
}
}
}
}
Pick one:
VIBO_EMAIL and VIBO_PASSWORD. The
server signs in server-side and manages the token (refreshing as needed).VIBO_ACCESS_TOKEN (and VIBO_REFRESH_TOKEN) with values captured from a
signed-in web.vibodj.com session — no password needed.vibo_capture_session once — it grabs the token from your tab (approve the
pair code), saves it to ~/.vibo-mcp/session.json, and reuses it thereafter.The server boots without credentials (so it can be installed and probed); the config error only appears on the first tool call.
vibo_get_me — your profile (and whether Spotify/Apple Music are connected).vibo_list_events — your upcoming (or past:true) events.vibo_get_event — full details for one event.vibo_list_sections — an event's timeline (Ceremony, First Dance, Dinner, …).vibo_get_section_songs — songs requested in a section, with likes/flags/comments.vibo_list_section_questions — the DJ's planning questions for a section (type, options, current answer).vibo_search_songs — find songs to add (Vibo catalog or connected Spotify).vibo_list_section_song_ideas / vibo_list_song_ideas_songs — browse the DJ's suggested song collections per section.vibo_get_playlists / vibo_get_playlist_songs — your connected-service playlists.vibo_list_event_users — the hosts and guests on an event.vibo_list_notifications / vibo_get_notifications_count.vibo_healthcheck — confirm connectivity + auth.Each mutating tool asks the user to confirm before anything is sent. Where the
client can show a confirmation prompt, it does (unless the server sets
MCP_CONFIRM_ELICITATION=off, which sends every client down the token path
below). Otherwise the first call makes
no network call and returns status: "confirmation-required" with a preview
of exactly what would be sent ( preview.action + preview.willSend) and a
confirmToken. Show that preview to the user, and only after they approve in
chat call the tool again with the same arguments plus confirmToken. A
token works once; changing any argument is refused as DRAFT_CHANGED (with a
fresh preview and token to re-approve), and a reused one as TOKEN_REUSED.
MCP_CONFIRM_MODE ( ask-user default / auto / refuse) controls this flow.
vibo_add_song_to_section — add a searched song to a section.vibo_remove_song_from_section — every id is checked against the section first; unknown ids are listed and nothing is sent.vibo_move_song / vibo_reorder_songs — reorder places sourceSongIds directly after targetSongId (omit it for the top). A host needs the section's "hosts can order songs" setting on — Vibo turns it off for sections a host creates, and only the DJ can turn it on.vibo_update_song — mark must-play / do-not-play, or set a comment (at most 90 characters; an emoji counts as 2).vibo_add_song_to_section re-reads the section after adding and errors if the song isn't actually there.vibo_toggle_song_like — like/unlike a song.vibo_comment_on_song / vibo_comment_on_section (+ delete) — leave the DJ notes.vibo_import_playlist_to_section — pull tracks from a connected Spotify/Apple playlist.vibo_join_event — join via a share link/hash (e.g. a vibodj.app.link/... URL).vibo_leave_event.vibo_create_event_contact — add a host/guest contact.vibo_invite_users / vibo_change_user_role / vibo_remove_user — manage who's on the event.vibo_update_section — edit a section's name, time, or note.vibo_create_section — add a section (name ≤ 45 characters; visibility host/public; optional time and note — Vibo drops a host's description) and place it with afterSectionId or position. Returns the new _id.vibo_delete_section — delete a section; the preview shows its name, song count and answered questions. dontPlay/ headline sections need force: true.vibo_reorder_sections — move sections to directly after targetSectionId (omit for the start).vibo_answer_question — answer a planning question (text / option ids / link / image+file uploads).vibo_set_profile_photo — set your profile photo from a local image in the upload directory ( VIBO_UPLOAD_DIR, default ~/Downloads/vibo-mcp).vibo_capture_session — capture your login from a signed-in browser tab (SSO accounts).vibo_mark_notifications_read.vibo_export_event_to_spotify / vibo_export_event_to_apple_music.view)#Eight of this server's 42 tools take view: "compact" | "full", and on every
one of them compact is the DEFAULT. You get the slim rung without asking.
They are exactly the eight reads whose GraphQL document asks Vibo for media:
ToolWhat compact dropsvibo_search_songs``thumbnails { s180x180 original } per trackvibo_get_section_songs``thumbnails { s180x180 original } per songvibo_list_song_ideas_songs``thumbnails { s180x180 original } per songvibo_list_event_users``email + imageUrl per person — projected to _id/ firstName/ lastName/ role on both exits (merged and filtered); view: "full" for emailsvibo_list_notifications``imageUrl per notificationvibo_get_me``imageUrl``vibo_get_playlists``images { url width height } (cover art) per playlistvibo_get_playlist_songs``images { url width height } (artwork) per track — songUrl survives
That correspondence is not a coincidence to be maintained by hand: a test in
tests/view.test.ts counts the media selections in src/gql.ts and asserts
the roster of view-taking tools matches. Add a ninth selection and it fails.
Compact here is media stripping, not a field projection. src/view.ts
writes no field list, because this repo holds no captured Vibo payload to
derive one from honestly; instead it removes keys whose value is a picture,
which is subtractive and so cannot drop a field nobody knew about.
The one exception is vibo_list_event_users: its query fixes the member field
list, so compact projects each member to _id/ firstName/ lastName/ role
and keeps other people's email addresses out of the default answer (fleet-audit
#1136). Ask for view: "full" only when an email is actually needed.
What compact does not touch is the point of these tools: songUrl, the
links block ( spotify / youtube / appleMusic) and the quality verdict
all survive. A streaming link is this server's product, not decoration —
vibo_add_song_to_section cannot add anything without songUrl, and the
quality verdict is computed from how many services carry a track. A null link
survives too: an absent key and a null one are the same to JSON.parse but not
to a reader deciding whether a service was checked.
view: "full" returns Vibo's payload untouched, cover art included. There is
deliberately no raw rung: nothing here re-serialises or normalises the
GraphQL response, so full already IS the upstream payload and a third value
would silently alias one that exists.
view#vibo_capture_session) answer with a confirmation preview or a receipt — an id,
a count, a status. Nothing in a receipt is decoration, and slimming one is
how you lose the field that says what actually happened.vibo_healthcheck answers with a connectivity/auth diagnostic. It runs
the same GET_ME document as vibo_get_me and still takes no rung, because
it never returns Vibo's user object — it builds {ok, userId, email} here.
A view on it would be a parameter that changes nothing.vibo_list_events, vibo_get_event,
vibo_list_sections, vibo_list_section_questions,
vibo_list_section_song_ideas, vibo_get_notifications_count) hand back
Vibo's GraphQL payload as it arrived, and their documents select no media,
so there is nothing for a rung to remove.A view passed to a tool that does not declare one is dropped by zod without a
warning, so a successful call is never evidence the rung was honoured. Check
the table above rather than assuming.
vibo_list_events → pick an event id.vibo_list_sections → pick a section id.vibo_search_songs → get a song's songUrl/ viboSongId.vibo_add_song_to_section — show the user the preview it returns, then call
again with the confirmToken once they approve.