Music tools for agents
Connect an MCP client to http://localhost:8087/mcp using Streamable HTTP.
It runs inside Studio’s container and shares its single generation queue.
No extra service, model download or parallel GPU worker is needed.
For clients with a remote HTTP server configuration:
{
"mcpServers": {
"yue2": {
"type": "http",
"url": "http://localhost:8087/mcp"
}
}
}
Client configuration names vary; select Streamable HTTP, not the older
HTTP+SSE transport. If the operator sets YUE2_API_KEY, configure
Authorization: Bearer YOUR_KEY on the MCP connection. This uses the same key
as the music API; it is not OpenAI authentication or OAuth.
Four tools
| Tool | Input | Result |
|---|---|---|
skill |
None | Current Markdown skill, version, one-hour guide_token |
generate_song |
Guide token, lyrics, direction; optional duration, tempo, format | Opaque job handle, queued status, poll interval |
get_song |
job_id |
Progress or an HTTP download link and audio metadata |
cancel_song |
job_id |
Cancellation for that job only; completed files remain available |
All tool descriptions direct agents to retrieve skill first if they have
not already read it in the current conversation. Agents then copy its token into
generation calls. The server checks retrieval, not whether an agent understood
the text. Reference copies are the MCP resource yue2://skills/songwriting and
GET /skills/songwriting/SKILL.md.
Only skill issues the acknowledgement token.
The maintained source is SKILL.md.
The guide teaches agents to write original lyrics from an idea, develop partial
lyrics, or arrange supplied words with section labels. It covers hooks, singable
phrasing, rhyme and pacing across a complete two-to-four-minute song. It explains
instrument and genre possibilities, uses direction for musical style and
lyric section labels for song form, and covers
returning a real completed link. A lyrics-only request should not trigger audio
generation. Prompting advice remains guidance rather than a fidelity guarantee.
Example generate_song arguments, after reading the guide:
{
"guide_token": "ACTUAL_TOKEN_RETURNED_BY_SKILL",
"lyrics": "[Verse 1]\nNeon on the handlebars\nWe ride beneath electric stars\nBoots are dusty, wheels are bright\nWe bring the country to the night\n[Pre-Chorus]\nHear the city call our names\nWatch the sparks become a flame\n[Chorus]\nRide on, ride on! (hey!)\nWe will find another way\nSing it loud and carry on\nWe keep rolling till the dawn\n[Verse 2]\nSteel strings ring above the street\nOld-time hearts and future beats\nEvery corner, every bend\nBrings us closer to a friend\n[Pre-Chorus]\nHear the city call our names\nWatch the sparks become a flame\n[Chorus]\nRide on, ride on! (hey!)\nWe will find another way\nSing it loud and carry on\nWe keep rolling till the dawn\n[Bridge]\nWhen the towers fade to gold\nWe have stories to be told\nTake the long road, take my hand\nThere is room for us to land\n[Final Chorus]\nRide on, ride on! (hey!)\nWe will find another way\nSing it loud and carry on\nWe keep rolling till the dawn",
"direction": "country pop, cyberpunk pop, futuristic, upbeat, male vocals, harmonies, acoustic guitar strumming, electric guitar twang, pedal steel, synth leads, punchy drums, sidechained bass, glossy modern production, neon atmosphere",
"tempo_bpm": 112,
"format": "opus"
}
Only these arguments are accepted. Duration is a 10–360-second ceiling
(MCP default 300 seconds / five minutes), not a target. Normally omit
duration_seconds; override it only for an explicit user duration constraint or
range. Do not write extra material to fill five minutes. A smaller ceiling may
truncate a song; this control cannot enforce an exact length or minimum.
Raising it alone does not extend a short song: lyric length, phrasing,
written-out repetitions, tempo and arrangement
affect the actual length; short lyrics can still yield repetitions or extended
instrumental passages. For a longer vocal song, provide enough lyrics and
sections to support it. Exact length is not guaranteed. Tempo is an optional
30–300 BPM prompt hint, not a timing guarantee or playback-speed adjustment.
Lyrics are passed verbatim; an empty
string allows an instrumental with suitable direction. New compositions use
fresh random seeds, the normal eight-step default and no inherited score.
Format is opus (compact default) or flac (lossless), both 48 kHz stereo.
There are no model, voice-cloning, adapter, seed, sampling, quality, server
settings or model-residency tools. Unknown arguments are rejected.
Generation returns immediately. Wait for the returned poll_after_seconds before
the first get_song call and between later checks. Responses recommend
30 seconds to avoid unnecessary API calls. Three polls are not a timeout:
long songs and queued work can need more checks. Keep the existing handle and
continue polling pending work instead of failing or resubmitting it.
Use the returned handle. States are queued, generating, complete, failed and
cancelled. A disconnect leaves the song running; cancel explicitly if needed.
Cancellation is best effort if a song is already finishing. Completed status
includes url, expires_at, ttl_seconds: 3600, format, MIME type, duration,
size, sample rate and channel count. No audio bytes or base64 are returned
through MCP. Save the handle if the agent connection closes.
One-hour downloads and persistence
Each download URL expires one hour after its export completes, independently
of queue time or the guide token. Download or share that URL directly. It works
without an Authorization header: the unpredictable 256-bit URL is the download
capability. Anyone holding it can fetch the song until expiry. GET, HEAD and
byte ranges are supported; responses use Cache-Control: no-store. Expired,
missing and invalid capabilities return 404. This controls server access;
it cannot revoke copies someone has already downloaded.
Only the selected export is stored, under /output/agent-artifacts in Docker.
Mount /output to keep completed links across container replacement:
docker run -d --name yue2 --gpus all \
-p 127.0.0.1:8087:8087 \
--mount "type=bind,source=$(pwd)/data/models,target=/models,readonly" \
--mount type=volume,source=yue2-output,target=/output \
hangrylabs/yue2:latest
The image runs as UID 10001; a custom bind mount must be writable by that user.
task start uses ignored data/results/studio/ for persistent output. On Linux,
prepare that bind directory for UID 10001 before starting. Native/Studio results
use disk-backed server result storage; the browser library remains separate.
See queue limits and storage. In-flight jobs and guide tokens are
process-local and disappear on restart; completed metadata and capability URLs
survive in persisted storage, with their original expiry.
Expired owned files are swept on startup, on submissions and every 30 seconds.
Every download checks expiry even before the sweep. Storage is bounded to 128
files / 2 GiB, with a 512 MiB per-file limit. Unexpired exports are never evicted
to make room; a full store fails the new export. Up to eight MCP songs may be
queued/generating; they still run serially. All compute routes also share the
configurable global eight-job limit. When full, tools return isError: true,
structuredContent.code: queue_full and retry_after_seconds: 5, with a
Retry-After: 5 header. Wait with exponential backoff and jitter before retrying
a refused submission; poll accepted handles instead of resubmitting.
For clients on another machine or a forwarded port, set the operator environment
variable YUE2_MCP_PUBLIC_URL to their reachable HTTP(S) origin, for example
https://music.example.org. The default is http://localhost:8087. Links use
this configured origin, never an untrusted Host or forwarded header. Paths,
queries, fragments and embedded credentials are rejected. Configure a proxy to
forward /mcp, /artifacts/ and /skills/ with the configured Host/Origin.
Set the API key when enabling intentional remote access. This MCP policy does
not secure older native/Studio routes; keep those within their local scope.
YUE2_MCP_OUTPUT_DIR optionally selects an operator-owned export directory;
the default agent-artifacts is relative to the server working directory
(/output in Docker). Neither environment variable is an agent argument.
Preserve the output directory and public origin to keep URLs usable.
Transport and development
The native adapter implements JSON-response Streamable HTTP: modern
2026-07-28 requests and legacy 2025-11-25 / 2025-06-18 initialization.
Modern clients supply per-request metadata and matching protocol/method/name
headers. It has no sessions, subscriptions, server callbacks or SSE stream;
GET and DELETE /mcp return 405. The tool catalog is invariant. Known legacy
notifications receive 202; song cancellation uses its explicit tool.
Host and Origin are checked on the MCP transport. Loopback, Docker’s local host
alias and the configured public origin are allowed; arbitrary browser origins
are rejected. No wildcard CORS is enabled.
task check:cpu exercises the native transport with a model-free fixture:
restricted arguments, guide gating, both protocol eras, exact expiry boundary,
persistence, capability lookups, downloads and ranges. The fixture is excluded
from the runtime image. The explicit
official SDK client check generates one real
song and downloads its link; it is a manual GPU check, not routine CI.
The separate songwriting agent check
tests an actual language model using full-song briefs. By default it retrieves
the real skill and validates proposed calls against the live tool schema,
stopping before generation is submitted. It records the model’s choices without
repairing its arguments. Explicit --generate-audio enables the optional
end-to-end generation workflow. Audio or ASR quality is not an acceptance check.
The transport follows the official MCP specification. Temporary links follow the pattern used in Hangry Labs’ Faster Qwen TTS; audio inference remains entirely local here.