MCP

The Model Context Protocol lets an AI assistant call tools on your Mac. choruspop mcp is an MCP server, so Claude and other clients can make songs, versions and exports for you.

Set up

First install the command-line tool: the server is part of it.

Claude Code

claude mcp add choruspop -- choruspop mcp

Add --scope user to have it in every project. If choruspop isn't on your PATH, use the full path: /Applications/ChorusPop.app/Contents/Helpers/choruspop.

Claude Desktop

Settings ▸ Developer ▸ Edit Config opens ~/Library/Application Support/Claude/claude_desktop_config.json. Add ChorusPop under mcpServers, then quit and reopen Claude. Claude Desktop doesn't read your shell's PATH, so give the full path:

{
  "mcpServers": {
    "choruspop": {
      "command": "/Applications/ChorusPop.app/Contents/Helpers/choruspop",
      "args": ["mcp"]
    }
  }
}

Other clients

Any client that starts stdio servers takes the same two things: the command and the argument mcp. No environment variables or network ports are needed.

{
  "name": "choruspop",
  "transport": "stdio",
  "command": "/Applications/ChorusPop.app/Contents/Helpers/choruspop",
  "args": ["mcp"]
}

With the Python package installed, python3 -m choruspop.mcp (or choruspop-mcp) starts the same server.

Try it

  • “Write a 30-second synthwave song about the harbor at night and make it with ChorusPop.”
  • “Make three short lo-fi songs for my study playlist, one at a time, and put them in an album called Focus.”
  • “Take the newest ChorusPop song, remove the vocals, and save the instrumental as FLAC on my Desktop.”
  • “List my ChorusPop songs from this week and make stems of the one called Neon River.”
  • “Make that last song again with the same seed, but with a male voice.”

The server hands every client the guide for AI agents when it connects, so the assistant knows songs take minutes, asks before long batches and reports where the files went.

How long jobs work

A song takes minutes, so the tools don't hold the call open by default:

  1. make_song (or remove_vocals, vocals_only, stems) queues the job and returns its id at once.
  2. get_job with wait_seconds (up to 600) holds until the job ends or that time passes. If the client sent a progressToken, the server sends notifications/progress (0–100, with the stage and time left) while it waits.
  3. When the job is done, the result has song_id and files: absolute paths in ~/Music/ChorusPop/<album or Singles>/, or in the destination you gave make_song.

make_song also takes wait: true to hold the call itself, up to timeout_seconds. If the client cancels a call (notifications/cancelled), the job keeps going in ChorusPop; cancel_job stops it. Jobs run one at a time, in the order they were queued.

→ {"method":"tools/call","params":{"name":"make_song","arguments":{"lyrics":"[verse]\nNeon on the river\n[chorus]\nTurn it up","genre":"synthwave","moods":["dreamy"],"length_seconds":30}}}
← {"structuredContent":{"job":{"id":"8f3c…","kind":"song","status":"queued","progress":0,"stage":"waiting","title":"Neon on the river"}}}

→ {"method":"tools/call","params":{"name":"get_job","arguments":{"job_id":"8f3c…","wait_seconds":300},"_meta":{"progressToken":7}}}
← {"method":"notifications/progress","params":{"progressToken":7,"progress":42,"total":100,"message":"Neon on the river: running 42% · performing · about 0:48 left"}}
← {"structuredContent":{"job":{…,"status":"done"},"song_id":"8f3c…","files":["/Users/me/Music/ChorusPop/Singles/Neon on the river.m4a"]}}

Every result is also plain text in content (a one-line summary and the same JSON), for clients that don't read structuredContent. A tool that fails returns isError: true and {"error": {"code": …, "message": …}} with one of the error codes.

Server

Server namechoruspop (ChorusPop 1.1)
Transportstdio, one JSON-RPC message per line
Protocol versions2025-06-18, 2025-03-26, 2024-11-05
Capabilities{"tools":{"listChanged":false}}
InstructionsThe guide for AI agents, 9,509 characters

Tools

ToolWhat it does
make_songMake a song
get_jobGet a job
list_songsList songs
get_songGet a song
remove_vocalsRemove vocals
vocals_onlyVocals only
stemsStems
export_songExport a song
cancel_jobCancel a job

make_song Make a song

Queue a new song — music and singing — from lyrics and a style, in ChorusPop on this Mac. Returns a job id at once (or, with wait, holds until it's done). Songs are made on this Mac by an on-device model and take minutes, not seconds: roughly 1–3 minutes for 0:30 and 10+ minutes for 4:50 on an Apple-silicon Mac, one at a time in ChorusPop's queue. Follow the job with get_job; when it's done the result has song_id and the file path.

Lyrics: plain lines under section tags like [verse], [chorus], [bridge], [outro]; about 2 sung words per second of length fit. Style: pick genre/moods/voice/instruments, or give a free-form style line instead (it wins over the chips).

InputTypeValuesWhat it is
albumstringup to 80 charactersAdd the finished song to the album with this title (made if there isn't one).
destinationstringOptional absolute path for the file(s): an existing folder, a path ending in /, or a file path. Default: the user's Music folder (~/Music/ChorusPop/<album or Singles>/).
formatstringone of m4a, alac, flac; default "m4a"File format: m4a (AAC, small), alac (Apple Lossless) or flac. Every file carries title, album, cover art, lyrics and the model credit.
genrestringone of pop, rock, hipHop, rnb, electronic, dance, indie, folk, country, jazz, blues, soul, metal, punk, reggae, lofi, synthwave; default "pop"Genre chip.
instrumentalbooleandefault falseNo singing: the plan's Vocal line is silenced and the tune moves to the band. Leave lyrics out. Experimental: on some seeds it still sings, which is why the app doesn't offer it yet.
instrumentsarray of stringone of piano, acousticGuitar, electricGuitar, synth, strings, bass, drums, 808s, brass; up to 3Up to 3 featured instruments.
keystringThe song's key, e.g. "D minor", "F# major", "Bb", "Ebm". Exact: the model writes its plan, the plan is transposed to this key (the nearest way), then sung. Naming a key in `style` does nothing reliable. A major plan asked for a minor key (or the reverse) goes to the key with that signature (D minor → F major).
length_secondsinteger30–290; steps of 10; default 60Upper bound on the song's length, 30–290 s (0:30–4:50) in 10 s steps. The song may end a little sooner on its own. Longer takes proportionally longer to make.
lyricsstringup to 3000 charactersThe words to sing, with section tags: "[verse]\nline\nline\n\n[chorus]\nline". Up to 3000 characters. Required, except with instrumental (leave it out) or plan_file (optional: sung to the plan's Vocal line).
midi_rolesstringWith a MIDI plan_file: which tracks play what, as track numbers, e.g. "voice=1,lead=5,harmony=2+3" (voice is sung, lead is the instrument line, harmony gives the chords). Default: the app's own picks.
moodsarray of stringone of upbeat, happy, chill, dreamy, romantic, sad, dark, energetic, angry, epic; up to 2Up to 2 moods, in order of weight.
plan_filestringOptional absolute path to a plan to sing from instead of the model writing one: an .abc file in YuE2's ABC dialect, or a .mid/.midi file (turned into a plan as the app's Import MIDI does).
seedinteger0–4294967295Same seed and inputs make the same song. Default: random.
stylestringup to 400 charactersA free-form style line fed to the model as is, e.g. "synthwave dreamy synth female vocal". Overrides genre/moods/voice/instruments.
timeout_secondsinteger1–3600; default 900With wait: the longest to hold the call, in seconds. The job keeps going after it.
titlestringup to 80 charactersThe song's title. Default: the first lyric line.
voicestringone of female, male; default "female"Singer.
waitbooleandefault falseHold this call until the job is done (sending progress notifications if you passed a progressToken), up to timeout_seconds. Default false: return the job id at once and poll get_job.

get_job Get a job

The state of a job: queued, running, paused, done, failed or cancelled, with progress (0–1), the stage and an estimate of the seconds left. When a song job is done it has song_id and files (saved in the format asked for at make_song, to its destination or the Music folder). Pass wait_seconds to hold the call until the job ends or that time passes, with progress notifications. Poll every 30–60 s rather than faster; a song takes minutes.

read-only · idempotent

InputTypeValuesWhat it is
job_id requiredstringA job id returned by make_song, remove_vocals, vocals_only or stems.
wait_secondsinteger0–600; default 0Hold the call up to this long for the job to finish (0 = answer now).

list_songs List songs

The user's ChorusPop songs, newest first: id, title, style, length, seed, albums and the versions made (instrumental, vocals, stems).

read-only · idempotent

InputTypeValuesWhat it is
albumstringOnly songs in the album with this title.
limitinteger1–200; default 20At most this many songs.
querystringMatches titles, lyrics and style words.

get_song Get a song

One song's details and lyrics, the key, tempo and metre from its plan (null without one), and the path of its audio file in the Music folder (saved there as M4A first if it isn't yet), plus any versions saved there.

idempotent

InputTypeValuesWhat it is
song requiredstringThe song: its id (from make_song, get_job or list_songs), the first 6+ characters of one, its exact title, or "latest".

remove_vocals Remove vocals

Queue the instrumental of a song (the singing taken out). Returns a job id; with wait, holds until done. It waits for any song being made, then takes seconds to about a minute. The finished file is saved like make_song's.

InputTypeValuesWhat it is
song requiredstringThe song: its id (from make_song, get_job or list_songs), the first 6+ characters of one, its exact title, or "latest".
destinationstringOptional absolute path for the file(s): an existing folder, a path ending in /, or a file path. Default: the user's Music folder (~/Music/ChorusPop/<album or Singles>/).
formatstringone of m4a, alac, flac; default "m4a"File format: m4a (AAC, small), alac (Apple Lossless) or flac. Every file carries title, album, cover art, lyrics and the model credit.
timeout_secondsinteger1–3600; default 900With wait: the longest to hold the call, in seconds. The job keeps going after it.
waitbooleandefault falseHold this call until the job is done (sending progress notifications if you passed a progressToken), up to timeout_seconds. Default false: return the job id at once and poll get_job.

vocals_only Vocals only

Queue a version of a song with only the singing. Returns a job id; with wait, holds until done. Seconds to about a minute, after any song being made.

InputTypeValuesWhat it is
song requiredstringThe song: its id (from make_song, get_job or list_songs), the first 6+ characters of one, its exact title, or "latest".
destinationstringOptional absolute path for the file(s): an existing folder, a path ending in /, or a file path. Default: the user's Music folder (~/Music/ChorusPop/<album or Singles>/).
formatstringone of m4a, alac, flac; default "m4a"File format: m4a (AAC, small), alac (Apple Lossless) or flac. Every file carries title, album, cover art, lyrics and the model credit.
timeout_secondsinteger1–3600; default 900With wait: the longest to hold the call, in seconds. The job keeps going after it.
waitbooleandefault falseHold this call until the job is done (sending progress notifications if you passed a progressToken), up to timeout_seconds. Default false: return the job id at once and poll get_job.

stems Stems

Queue a song's stems: four files — drums, bass, other and vocals — in a folder. Returns a job id; with wait, holds until done. Seconds to about a minute, after any song being made.

InputTypeValuesWhat it is
song requiredstringThe song: its id (from make_song, get_job or list_songs), the first 6+ characters of one, its exact title, or "latest".
destinationstringOptional absolute path for the file(s): an existing folder, a path ending in /, or a file path. Default: the user's Music folder (~/Music/ChorusPop/<album or Singles>/).
formatstringone of m4a, alac, flac; default "m4a"File format: m4a (AAC, small), alac (Apple Lossless) or flac. Every file carries title, album, cover art, lyrics and the model credit.
timeout_secondsinteger1–3600; default 900With wait: the longest to hold the call, in seconds. The job keeps going after it.
waitbooleandefault falseHold this call until the job is done (sending progress notifications if you passed a progressToken), up to timeout_seconds. Default false: return the job id at once and poll get_job.

export_song Export a song

Write a song, or a version already made from it, as an audio file with its tags (title, album, cover, lyrics, model credit and license). To the Music folder by default, or to destination. Returns the file paths.

idempotent

InputTypeValuesWhat it is
song requiredstringThe song: its id (from make_song, get_job or list_songs), the first 6+ characters of one, its exact title, or "latest".
destinationstringOptional absolute path for the file(s): an existing folder, a path ending in /, or a file path. Default: the user's Music folder (~/Music/ChorusPop/<album or Singles>/).
formatstringone of m4a, alac, flac; default "m4a"File format: m4a (AAC, small), alac (Apple Lossless) or flac. Every file carries title, album, cover art, lyrics and the model credit.
lyrics_filebooleandefault falseAlso write the synced lyrics as an .lrc beside the audio.
versionstringone of original, instrumental, vocals, stems; default "original"original (the song), or a version made with remove_vocals (instrumental), vocals_only (vocals) or stems.

cancel_job Cancel a job

Stop a running job or take a queued one out of the queue. Nothing is saved for it.

destructive · idempotent

InputTypeValuesWhat it is
job_id requiredstringA job id returned by make_song, remove_vocals, vocals_only or stems.

Result objects

job in a result is the same object the command line prints:

Job

KeyTypeWhat it is
idstringThe job id. A song job's id becomes the song's id; a version job is <song id>#<kind>.
kindstringOne of song, instrumental, vocals, stems.
statusstringOne of queued, running, paused, done, failed, cancelled.
progressnumber0…1.
stagestring (optional)A song's stage, in order: preparing, writing (the plan: tempo, key, chords, melody), composing, performing, mixing, saving. A version's: separating. Either, while queued or held: waiting.
titlestringThe song's title.
song_idstring (optional)The finished song (a song job, once done), or the song a version is of.
eta_secondsinteger (optional)Seconds until it's done, when the app can tell.
length_secinteger (optional)The length asked for, in seconds.
messagestring (optional)Why it failed or was cancelled.

Song

KeyTypeWhat it is
idstringThe song's id.
titlestringThe song's title.
stylestring"Synthwave · Dreamy"
genrestringGenre id.
moodsarray of stringMood ids.
voicestringfemale or male.
instrumentsarray of stringInstrument ids.
style_fedstringThe style line the model was given.
length_secintegerThe length asked for, in seconds.
audio_secnumberThe audio's actual length, in seconds.
seedintegerMake it again with this seed and the same inputs.
created_atstringWhen it was made (ISO 8601).
albumsarray of stringTitles of the albums it's in.
versionsarray of stringThe versions made so far: instrumental, vocals, stems.

App

KeyTypeWhat it is
namestringChorusPop.
versionstringThe app's version.
buildstringThe app's build number.
bundle_idstringThe app's bundle id.
protocolintegerThe version of the tool-to-app protocol.
model_readybooleanWhether the song model is installed. Songs queued before it is wait.
songsintegerHow many songs the library has.
active_jobsintegerJobs queued or running.
featuresarray of string (optional)What the app can do beyond the first commands: plan, midi, key, instrumental, deliver, plan_info, midi_tracks. Missing from apps before build 16.

If it doesn't connect

  • Run choruspop version in Terminal. It opens ChorusPop and prints both versions; scripting needs ChorusPop 1.0 (6) or later, the direct download.
  • Claude Desktop: check the path in the config, then Settings ▸ Developer shows the server's state and log.
  • The server writes its own notes to stderr, which clients keep in their MCP logs.