yt-mcp
Server provides YouTube Music discovery and private playlist creation via six MCP tools.
Search YouTube Music songs and retrieve track metadata without authentication.
Fetch ordered song-radio recommendations from the first matching seed.
Mix two to ten song radios round-robin into one deduplicated result.
Create a private playlist from a fresh single-seed radio queue.
Create a private playlist from a fresh multi-seed radio mix.
Resume an interrupted private playlist using its saved exact track plan, verifying remote state before appending missing tracks.
Uses the official YouTube Data API with OAuth to create private playlists in the connected YouTube account and insert tracks from a fresh radio queue.
Provides tools to search YouTube Music songs and fetch song-radio recommendations anonymously, preserving YouTube's order and excluding the seed, unavailable tracks, and duplicate video IDs.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@yt-mcp create a private playlist called Italiaanse zomeravond from Alan Sorrenti radio"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
yt-mcp
A small Python CLI and MCP server I built to create YouTube Music radio mixes and private playlists from multiple seed songs.
I wanted something YouTube Music itself did not give me easily: start from several songs that define a mood, merge their radio queues, remove duplicates, and turn the result into a playlist I can actually keep.
What started as a recommendation problem quickly became an engineering problem around safe writes and recovery: OAuth, resumable playlist creation, deterministic mixing, validation, and explicit read/write boundaries.
How It Works
flowchart TD
U[User or agent] --> E[yt CLI or yt-mcp]
E --> O{Operation}
O -->|Search| S[Search YouTube Music]
O -->|Single-seed radio| R[Fetch song-radio queue]
O -->|Multi-seed radio| M[Fetch queues and round-robin mix]
S --> N[Normalize track metadata]
R --> N
M --> N
N --> T[Structured CLI or MCP result]
O -->|Create playlist| C[Build fresh radio or mix and exact track plan]
C --> P[Create private playlist and save resumable state]
P --> I[Insert planned tracks]
O -->|Resume| L[Load saved plan and verify remote prefix]
L --> I
A[Google OAuth] -. authorizes .-> P
A -. authorizes .-> L
A -. authorizes .-> IRelated MCP server: ytmusic-mcp
Features
Search YouTube Music without authentication
Build a radio queue from one song
Mix radio queues from two to ten seed songs
Create private playlists
Resume interrupted playlist creation
Use the same functionality through MCP
Quick Start
Requires Python 3.10+ and uv.
uv sync --lockeduv run --locked yt search "Alan Sorrenti Figli delle stelle"
uv run --locked yt radio "Alan Sorrenti Figli delle stelle" --limit 30
uv run --locked yt radio-mix \
"Tourist LeMC Adem" \
"Brihang Steentje" \
"Yong Yello Luchtkasteel" \
--limit 50radio uses the first playable search result and reports the selected seed.
Pass --video-id VIDEO_ID to select a specific recording, or --json for
structured output.
How Radio Mixing Works
radio-mix:
Resolves every query to a playable seed.
Fetches one ordered radio queue per seed.
Takes one new track from each queue in seed order, then repeats.
Removes all seed songs and duplicate video IDs across queues.
Stops at the total
--limit(default 50, maximum 100).
For fixed input queues, mixing is deterministic. YouTube Music can return different queues between calls, and exhausted queues produce a shortfall rather than filler tracks. Search and radio remain anonymous and never change an account.
Creating Playlists
Playlist writes use Google OAuth and the official YouTube Data API. Create a
Google OAuth client of type TVs and Limited Input devices, save it as
oauth-client.json, and authorize the account:
chmod 600 oauth-client.json
uv run --locked yt auth oauthThen create a private playlist from a fresh multi-seed mix:
uv run --locked yt playlist create-mix "Belgian evening" \
"Tourist LeMC Adem" \
"Brihang Steentje" \
--description "Warm Belgian mix" \
--limit 50Before inserting the first track, the command saves the exact write plan in an owner-only state file. If insertion is interrupted, resume the same playlist:
uv run --locked yt playlist resume PLAYLIST_IDResume verifies that the remote playlist is still private and matches the
expected prefix before appending only the missing tracks. Completed retries are
no-ops; concurrent resumes for the same playlist are not supported. If tracks
were added to the playlist by hand, --add-missing appends only the planned
tracks that are not in the playlist yet and keeps the other items.
Copying a Playlist
Copy a playlist, for example one from another account, into a new private playlist in the connected account. List the source account's playlists to find the ID, then copy with both tokens:
uv run --locked yt playlist list --auth-file source/oauth.json
uv run --locked yt playlist copy PLAYLIST_ID \
--source-auth-file source/oauth.json \
--auth-file oauth.jsonWith --source-auth-file, the source is read through the official API and may
stay private. Without it, the source is read anonymously and must be public or
unlisted. Without --title, the copy keeps the source title. Unavailable,
private, deleted and duplicate tracks are skipped with a warning.
Every inserted track costs 50 units of YouTube Data API quota. The default
quota of 10,000 units per day covers about 200 tracks. A longer copy stops with
quotaExceeded; run yt playlist resume with the new playlist ID after the
daily quota reset.
Changing Playlist Privacy
Set one or more of the connected account's playlists to private, unlisted
or public, for example to make a source readable without its token:
uv run --locked yt playlist privacy unlisted PLAYLIST_ID [PLAYLIST_ID ...]The command keeps each playlist's title and description, skips playlists that already have the requested privacy, and costs 50 quota units per change.
See OAuth and playlist recovery for complete setup, credential handling, and recovery details.
MCP Server
yt-mcp starts a local stdio MCP server with six focused tools:
Tool | Effect |
| Read-only song search |
| Read-only radio recommendations |
| Read-only round-robin mix from two to ten song radios |
| Creates one private playlist from a song radio |
| Creates one private playlist from a multi-seed mix |
| Reconciles and completes a playlist from its saved plan |
Read tools are anonymous and do not load account credentials. Write tools
require OAuth and are deliberately separated from read-only operations. The
server exposes no generic method for arbitrary ytmusicapi calls.
If you want to run write tools without per-call approval, install a reviewed snapshot outside agent-writable workspaces rather than trusting a mutable checkout.
See MCP setup and MCP security and approvals.
Design Decisions
Reads stay anonymous where possible. Search and radio discovery do not need access to a Google account.
Writes are explicit. Playlist creation is separated from read-only operations in both the CLI and MCP interface.
Write plans are saved before mutation. An interrupted playlist can be resumed without recomputing a different radio mix.
Resume verifies remote state. It continues only when the existing playlist matches the expected prefix.
Tests don't touch real accounts. External clients are replaced with fakes during automated tests.
Development
uv run --locked pytestTests use fake clients and make no network or account changes. The implementation plan, multi-seed plan, and resume plan document scope and acceptance criteria.
Limitations
Search and radio depend on YouTube Music's unofficial internal API.
Results may change between calls and contain fewer tracks than requested.
Playlist writes use the official YouTube Data API and require Google OAuth.
Concurrent resume operations for the same playlist are not supported.
License
MIT. See LICENSE.
Available Tools
6 toolscreate_private_multi_seed_radio_playlistCreate a private multi-seed radio playlistB
Create one private playlist from a fresh two-to-ten-seed radio mix.
Inputs: title (required), queries (required), limit, description. Returns: url, seeds, title, tracks, +4 more
create_private_radio_playlistCreate a private radio playlistB
Create a private playlist from a fresh song-radio queue in the connected account.
Inputs: query (required), title (required), limit, description. Returns: url, seed, title, tracks, +4 more
get_multi_seed_radioMix multiple YouTube Music song radiosARead-onlyIdempotent
Round-robin two to ten song radios into one deduplicated result.
Inputs: queries (required), limit. Returns: seeds, tracks, returned, requested
get_song_radioGet a YouTube Music song radioARead-onlyIdempotent
Get YouTube Music's ordered radio recommendations around the first song match.
Inputs: query (required), limit. Returns: seed, tracks, returned, requested
resume_private_playlistResume a private yt-mcp playlistB
Resume one exact saved track plan; do not invoke concurrently.
Inputs: playlist_id (required). Returns: url, title, requested, playlistId, +5 more
search_songsSearch YouTube Music songsARead-onlyIdempotent
Find songs with IDs, artists, album titles, durations, and links.
Inputs: query (required), limit. Returns: tracks
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 6 tools
The core actions are mostly distinct: search_songs is clearly separate from the radio and playlist tools. However, get_song_radio vs get_multi_seed_radio and the two create_private_*_playlist tools are easy to confuse without reading the descriptions closely.
All tool names follow a consistent snake_case verb_noun pattern, with descriptive prefixes like search_, get_, create_, and resume_. Even the longer playlist names remain predictable and readable.
Six tools is well-scoped for a YouTube Music radio/playlist helper. Each tool covers a meaningful part of the workflow without unnecessary bloat or duplication.
The core search, radio generation, and private playlist creation flows are covered, but the surface has gaps: there is no way to list, delete, or otherwise manage existing private playlists, and resume_private_playlist implies a saved-track-plan lifecycle that is not fully supported.
Maintenance
Related MCP Connectors
Real-time YouTube transcripts, comments, channels & video search MCP. Local npx or hosted OAuth.
Search YouTube and read video, channel and transcript data as JSON. No Google Cloud project.
YouTube discovery, transcripts, library search, and monitors with API keys or OAuth.
YouTube MCP — wraps the YouTube Data API v3 (BYO API key)
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceMCP server for YouTube Music that enables searching songs and artists, managing playlists, and authenticating via Google OAuth, using STDIO transport.MIT
- FlicenseNot gradedqualityCmaintenanceEnables searching YouTube Music and managing playlists: create/delete playlists, add/remove/reorder tracks, and more via natural language.-
- AlicenseNot gradedqualityCmaintenanceProvides a local stdio MCP server for controlling YouTube Music through the CLI, enabling playback, search, queue management, and library access via MCP-compatible clients.MIT
- AlicenseNot gradedqualityBmaintenanceEnables searching YouTube Music and managing playlists through read and confirmation-gated write tools over STDIO. Supports identity checks, song search, playlist listing/retrieval, and previewed playlist creation, track addition, and exact track removal.MIT