yt-mcp
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-mcpcreate 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
Search YouTube Music, fetch or mix song-radio recommendations, and create private playlists from a CLI or a local MCP server.
flowchart TD
U[User or agent] --> E[yt CLI or yt-mcp]
E --> O{Operation}
O -->|Search| S[Anonymous YouTube Music song search]
O -->|Single radio or playlist| Q[Find the first playable seed]
Q --> R[Fetch the ordered song-radio queue]
O -->|Radio mix or playlist| Q5[Resolve 2 to 10 playable seeds]
Q5 --> R5[Fetch one radio queue per seed]
R5 --> M[Round-robin and globally deduplicate]
S --> N[Filter and normalize track metadata]
R --> N
M --> N
N --> T[Structured CLI or MCP result]
N -->|Playlist creation only| W[Create private playlist]
A[Owner-only OAuth token] -. authorizes .-> W
W --> J[Save owner-only resume plan]
J --> I[Insert planned tracks]
O -->|Resume| L[Load plan and read existing items]
L --> I
I --> P[Private YouTube playlist]Requires Python 3.10+ and uv.
uv sync --locked
uv run yt search "Alan Sorrenti Figli delle stelle"
uv run yt radio "Alan Sorrenti Figli delle stelle" --limit 30
uv run yt radio-mix \
"Tourist LeMC Adem" \
"Brihang Steentje" \
"Yong Yello Luchtkasteel" \
"Zwangere Guy Beter Leven" \
"Bazart Goud" \
--limit 50The radio command uses the first playable search result and shows the selected
seed. To choose a specific recording, copy its 11-character ID from search:
uv run yt radio --video-id VIDEO_ID --limit 30
uv run yt radio "Alan Sorrenti Figli delle stelle" --limit 30 --json > radio.jsonSearch and radio run anonymously. They read no account credentials and make no account changes. Recommendations preserve YouTube's order, exclude the seed, skip unavailable tracks, and remove duplicate video IDs. Results can vary and can contain fewer songs than requested.
radio-mix accepts two to ten song queries. It resolves every query to the
first playable search result before fetching any radio queue and refuses seeds
that resolve to the same video. The mixer takes one new track from each radio in
seed order, repeats that round, removes all seed songs and cross-radio
duplicates, and stops at the total --limit (default 50, maximum 100). Its JSON
result includes the resolved seeds for review. A fixed set of queues always
mixes deterministically, but YouTube Music can return different queues between
runs. Exhausted queues produce a documented shortfall instead of filler tracks.
Structured CLI and MCP track results include videoId, title, artists,
album, duration, duration_seconds, and url. album and
duration_seconds are nullable because YouTube Music does not return them for
every item. The numeric duration is suitable for cross-catalog matching while
the original display duration remains available for compatibility.
Connect a Google account with OAuth
Playlist creation uses Google OAuth. It never asks for or stores the Gmail
password. The OAuth consent grants the broad youtube scope, which can manage
the connected YouTube account; use a Google Cloud project you control and revoke
the grant from the Google account when it is no longer needed. Radio discovery
stays anonymous; authenticated writes use the official YouTube Data API.
In Google Cloud, enable the YouTube Data API, configure the OAuth consent screen, and create an OAuth client of type TVs and Limited Input devices.
If the consent screen is in testing, add the intended Google account as a test user. Download the client JSON to this repository as
oauth-client.json.Restrict the client file and start the local device authorization flow. Google asks you to choose the account during OAuth:
chmod 600 oauth-client.json
uv run --locked yt auth oauthChoose the intended Google account in Google's browser page. The command writes
oauth.json with owner-only permissions. Both credential files are ignored by
Git. Do not paste their contents, the displayed device code, or tokens into chat.
On POSIX systems, playlist operations refuse either credential file when group
or other users have access; fix that with chmod 600 FILE.
With the default names, yt-mcp finds oauth-client.json beside oauth.json
and can refresh the token without .env. For custom paths, copy .env.example
to .env and use --env-file .env. Direct
YTMUSIC_OAUTH_CLIENT_ID/YTMUSIC_OAUTH_CLIENT_SECRET values remain supported.
Create a private playlist from a fresh radio queue:
uv run --locked yt playlist create "Italiaanse zomeravond" \
"Alan Sorrenti Figli delle stelle" \
--description "Warme Italiaanse avondmuziek" \
--limit 100Warning: If OAuth access expires during either playlist write and cannot be refreshed, the private playlist can remain only partially populated. Keep its saved resume state and run
yt playlist resume PLAYLIST_IDafter restoring access instead of creating a replacement playlist.
Create one private playlist from a fresh multi-seed radio mix:
uv run --locked yt playlist create-mix "S&S: Italiaans" \
"Vattene amore Mietta Amedeo Minghi" \
"L'italiano Toto Cutugno" \
"Fantastico Fai quello che sei Laura Pausini" \
"Diamante Zucchero" \
"Pastello Bianco Pinguini Tattici Nucleari" \
"Lascia ch'io pianga Joyce DiDonato" \
--description "Italiaanse radio mix" \
--limit 100Both commands print the new playlist URL. They fetch fresh radio results, so
their tracks may differ from an earlier read-only radio or radio-mix result.
All seed songs are excluded. Add --json for structured output.
Before inserting the first track, each create command stores its exact track
plan in an owner-only .yt-mcp-state/PLAYLIST_ID.json file beside oauth.json.
The plan is limited to 100 tracks and authenticated with the OAuth client
secret, so an edited plan is rejected before network access. If insertion is
interrupted, resume that same playlist without creating or recomputing anything:
uv run --locked yt playlist resume PLAYLIST_IDResume first verifies that the remote playlist is still private and that its current video IDs are an exact prefix of the saved plan. It then appends only the missing suffix. A completed sequential retry is a no-op; edits that change the saved video-ID prefix stop before any write. Do not run two resumes for the same playlist concurrently. Keep the resume file while the playlist may need repair.
See the upstream OAuth setup and Google's YouTube OAuth guide for the authorization model.
Related MCP server: yt-music-mcp
Local 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 in the connected account |
| Creates one private playlist from a two-to-ten-seed mix |
| Reconciles and completes an existing playlist from its saved plan |
Playlist creation and resume tools are marked non-read-only and non-idempotent.
Sequential resume retries reconcile one saved plan and are safe no-ops after
completion, but concurrent calls are not serialized. Compatible hosts can
request approval for either kind of write. The server has no generic method
that can invoke arbitrary ytmusicapi operations.
For local development with per-call write approval, register the checkout with the local Codex CLI:
PROJECT_DIR="$PWD"
UV_BIN="$(command -v uv)"
codex mcp add youtube-music \
-- "$UV_BIN" \
--directory "$PROJECT_DIR" \
run --locked yt-mcpThe token and OAuth client contents stay in their owner-readable files. The server uses stdio and does not open a network listening port.
For an existing MCP registration, remove --env-file and its .env path from
the configured args, leaving run --locked yt-mcp after the project path.
Do not permanently approve a write tool that runs from an agent-writable
checkout: approval is attached to the tool name, not a hash of its source. For
no-prompt writes under an effective approval_policy = "never", install a
reviewed, non-editable snapshot outside writable workspaces and keep its OAuth
files and generated resume state in an owner-only directory that is not an
agent workspace:
PROJECT_DIR="$PWD"
CREDENTIAL_DIR="$HOME/.config/yt-mcp"
STATE_DIR="$CREDENTIAL_DIR/.yt-mcp-state"
install -d -m 700 "$CREDENTIAL_DIR"
install -d -m 700 "$STATE_DIR"
install -m 600 \
"$PROJECT_DIR/oauth.json" \
"$PROJECT_DIR/oauth-client.json" \
"$CREDENTIAL_DIR/"
if [ -d "$PROJECT_DIR/.yt-mcp-state" ]; then
find "$PROJECT_DIR/.yt-mcp-state" -maxdepth 1 -type f -name '*.json' \
-exec install -m 600 {} "$STATE_DIR/" \;
fi
uv tool install --force --link-mode copy "$PROJECT_DIR"
TOOL_BIN="$(uv tool dir --bin)/yt-mcp"
case "$TOOL_BIN" in
"$PROJECT_DIR"/*) printf '%s\n' "Refusing a workspace tool path" >&2; exit 1 ;;
esac
printf '%s\n' "$TOOL_BIN"Do not add --editable. Reinstall the snapshot after reviewing an update. Set
the existing MCP registration to the printed executable and protected paths.
The copied state preserves unfinished playlists. After restarting and verifying
the installed server, remove the original credential and state copies from the
workspace; until then the migration is incomplete. For a new setup, create the
OAuth files directly in the protected directory instead of copying them.
[mcp_servers.youtube-music]
command = "/absolute/path/from-uv-tool-dir/yt-mcp"
args = []
env = { YTMUSIC_AUTH_FILE = "/protected/path/oauth.json", YTMUSIC_OAUTH_CLIENT_FILE = "/protected/path/oauth-client.json" }
default_tools_approval_mode = "writes"
[mcp_servers.youtube-music.tools.create_private_multi_seed_radio_playlist]
approval_mode = "approve"
[mcp_servers.youtube-music.tools.resume_private_playlist]
approval_mode = "approve"Write annotations can make a host request approval. If a Codex task runs with
an effective approval_policy = "never", the exact tool overrides above avoid
a prompt while default_tools_approval_mode = "writes" keeps future write tools
prompt-gated. Do not set the whole server to approve, because that would also
pre-approve future write tools. After changing MCP configuration, restart the
server in Codex via Settings → MCP servers → Restart. If an old task retains its
earlier tool catalog or policy, start a new task as a troubleshooting step. A
managed deny remains binding.
The project pins ytmusicapi to 1.12.2 and the official MCP Python SDK to major
version 2. ytmusicapi is used anonymously against YouTube Music's unofficial
internal API for search and radio, so upstream changes can interrupt discovery.
Private playlist creation and item insertion use Google's official YouTube Data
API with the local OAuth token.
Development
uv run --locked pytestTests use fake clients and make no network or account changes. A read-only live smoke check is:
uv run --locked yt radio "Alan Sorrenti Figli delle stelle" --limit 5See the implementation plan and the multi-seed plan, plus the resume plan, for scope and acceptance criteria.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| title | Yes | ||
| queries | Yes | ||
| description | No | Created by yt-mcp. |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | Yes | |
| seeds | Yes | |
| title | Yes | |
| tracks | Yes | |
| requested | Yes | |
| playlistId | Yes | |
| trackCount | Yes | |
| privacyStatus | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already communicate that this is a non-read-only, non-idempotent, non-destructive operation. The description adds useful context by specifying that the playlist is private and the mix is 'fresh,' but it does not go beyond that into auth requirements, rate limits, or side effects.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single sentence with no filler and puts the core purpose first. It is concise, though it is also somewhat under-specified rather than fully informative.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Even though an output schema exists and annotations cover basic safety, the description omits important constraints such as the lower/upper seed bounds, the limit default, and how this creation flow behaves after invocation. The tool could be called incorrectly because key behavioral details are left to inference.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the burden of explaining parameters. It only hints at the seed-count range for queries and does not address title, description, or limit. The 'two-to-ten-seed' constraint is useful but not tied explicitly to the queries parameter.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action and resource: 'Create one private playlist from a fresh two-to-ten-seed radio mix.' This clearly distinguishes it from sibling read-style tools like get_multi_seed_radio and search_songs, and from the likely single-seed variant create_private_radio_playlist.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'two-to-ten-seed radio mix' implies the tool is for creating a playlist from multiple seeds, but it never explicitly says when to use this tool versus create_private_radio_playlist or get_multi_seed_radio. No exclusions or alternative routing are provided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_private_radio_playlistCreate a private radio playlistB
Create a private playlist from a fresh song-radio queue in the connected account.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| query | Yes | ||
| title | Yes | ||
| description | No | Created by yt-mcp. |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | Yes | |
| seed | Yes | |
| title | Yes | |
| tracks | Yes | |
| requested | Yes | |
| playlistId | Yes | |
| trackCount | Yes | |
| privacyStatus | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint=false and destructiveHint=false, so the description adds little beyond confirming it creates a playlist. It does mention 'fresh song-radio queue,' which hints at creating a new queue, but it doesn't disclose other traits like whether the playlist is immediately visible or if it requires an existing radio queue. Since annotations cover the safety profile, the description meets the minimum but doesn't enrich behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, front-loaded sentence that states the action and the key context. It is efficient and free of filler. However, it could arguably be slightly more detailed without becoming verbose, but it does not waste words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has 4 parameters (2 required), no parameter descriptions, and an output schema, the description is far from complete. It doesn't explain how to construct the arguments, what the 'fresh song-radio queue' means in practice, or how it differs from the multi-seed variant. The presence of an output schema does not help with input construction. An agent would struggle to call this tool correctly without additional information.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, meaning none of the parameters (title, query, limit, description) are documented in the schema. The description provides no information about what these parameters mean or how to use them. An agent would have to guess that 'query' is the seed song and 'title' is the playlist name, which is not obvious. The description completely fails to compensate for the missing schema documentation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Create') and a specific resource ('private playlist') and adds a distinguishing context: 'from a fresh song-radio queue in the connected account.' This clearly separates it from sibling create_private_multi_seed_radio_playlist, which implies a multi-seed radio. The purpose is unambiguous and actionable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies a use case (creating a private playlist from a single song-radio queue) but does not explicitly state when to choose this tool over the multi-seed sibling or get_song_radio. There is no mention of alternatives or exclusions. The context is present but not formalized, so an agent might need to infer the distinction.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_multi_seed_radioMix multiple YouTube Music song radiosARead-only
Round-robin two to ten song radios into one deduplicated result.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| queries | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| seeds | Yes | |
| tracks | Yes | |
| returned | Yes | |
| requested | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, so the safety profile is covered. The description adds the round-robin and deduplication behavior, which are useful traits beyond the annotations. It does not contradict them, though it does not discuss edge cases like fewer than 2 or more than 10 inputs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The entire description is a single sentence that front-loads the core verb and outcome, then specifies the input range and a key behavior (deduplication). It is concise and every word adds value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema is present, so return values are covered. The description explains the core operation and constraints, but the parameter format ambiguity and lack of explicit mention of read-only behavior (though covered by annotations) leave gaps. For a 2-parameter tool, it is mostly complete but not fully self-sufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It only implies that 'queries' are song radio seeds, but it does not specify the expected format (e.g., song name, ID, URL) or what 'limit' controls beyond a default value. This leaves an agent guessing about input semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb 'Round-robin' and a resource 'song radios' with a clear outcome 'deduplicated result'. It also constrains the input to 'two to ten' seeds, which distinguishes it from get_song_radio (single radio) and playlist creation tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly implies usage when combining multiple song seeds into a single radio, but it does not explicitly name alternatives or state when not to use it. The context is clear but exclusions are left implicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_song_radioGet a YouTube Music song radioBRead-only
Get YouTube Music's ordered radio recommendations around the first song match.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| query | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| seed | Yes | |
| tracks | Yes | |
| returned | Yes | |
| requested | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, so the description only needs to add behavior beyond safety and openness. It does add useful detail: the radio is 'ordered' and centered on the 'first song match,' which clarifies how the query is resolved. It does not disclose edge cases like no-match behavior, but with the annotations and output schema present, this is acceptable.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is one sentence with no filler, and it front-loads the core purpose before the qualifying detail. Every word contributes either to what the tool does or to how it behaves ('ordered', 'first song match').
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the output schema, the readOnly/openWorld annotations, and a simple two-parameter interface, the description is nearly sufficient for selection. It is missing explicit semantics for 'limit' and does not cover failure/no-match behavior, so it is adequate but not complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must carry parameter meaning. It explains the role of 'query' only indirectly through 'first song match,' but it never explains 'limit' or that the limit controls how many radio recommendations to return. This leaves a meaningful part of the input interface undocumented in both schema and description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description specifies a concrete verb ('Get'), a resource ('YouTube Music radio recommendations'), and a distinguishing qualifier ('around the first song match'), which separates it from the multi-seed sibling. It is slightly less explicit than it could be because it does not name any sibling, but the single-seed emphasis is enough to orient an agent.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'around the first song match' implies this is for single-song-seeded radio as opposed to multi-seed radio, but it never states that tradeoff explicitly. It offers no guidance on when to prefer search_songs or when to use a private playlist tool. The usage context is implied rather than spelled out.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
resume_private_playlistResume a private yt-mcp playlistB
Resume one exact saved track plan; do not invoke concurrently.
| Name | Required | Description | Default |
|---|---|---|---|
| playlist_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | Yes | |
| title | Yes | |
| requested | Yes | |
| playlistId | Yes | |
| trackCount | Yes | |
| privacyStatus | Yes | |
| addedTrackCount | Yes | |
| previousTrackCount | Yes | |
| remainingTrackCount | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already signal a non-readOnly, non-idempotent, non-destructive action. The description adds a useful concurrency warning that goes beyond the annotations, but it does not explain what resuming entails in practice, such as whether it activates the plan, starts playback, or mutates saved state.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single sentence with no filler. It front-loads the core purpose and includes the important concurrency warning, so every word earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given only one parameter and an output schema, a short description is acceptable. However, the lack of any playlist_id guidance and any explicit sibling differentiation leaves the definition minimally complete for an agent deciding when and how to invoke it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% and the description never mentions playlist_id or how to obtain it. The parameter name and 'saved track plan' give minimal implicit meaning, but the description does not compensate for the missing schema documentation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Resume') and a concrete resource ('one exact saved track plan'), and the title clarifies it applies to a private playlist. This distinguishes it from siblings like search_songs or create_private_radio_playlist, though it does not explicitly contrast itself with them and 'exact' is slightly vague.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The only usage guidance is the negative constraint 'do not invoke concurrently.' There is no explicit statement about when to choose this tool over the search or create siblings, though the semantics imply it is for resuming an existing saved plan rather than creating or searching.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_songsSearch YouTube Music songsCRead-only
Find songs with IDs, artists, album titles, durations, and links.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| query | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| tracks | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare readOnlyHint=true and openWorldHint=true, so the safety profile is covered. The description adds no contradictions and hints at the output fields, but it does not disclose additional behavioral details such as query interpretation, result limits, or how the open-world nature affects results.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, front-loaded sentence with no filler or repetition. It is concise, though somewhat under-specified in substance.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is simple and has an output schema plus safety annotations, but the description omits parameter meaning and usage guidance. An agent would need to infer that query is a search term and that limit controls result count, which is not sufficiently explicit for confident invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the full burden for explaining query and limit, but it mentions neither parameter. It only lists output fields, leaving the required query parameter and optional limit semantically unexplained.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the action ('Find songs') and the resource ('YouTube Music songs' via the title), and lists the returned fields: IDs, artists, album titles, durations, and links. It is distinguishable from sibling tools like get_song_radio and resume_private_playlist, though it does not explicitly contrast itself with them.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is given about when to choose search_songs over the radio/playlist siblings, nor are any exclusions or prerequisites mentioned. The intended usage is only implied by the tool's name and title, not stated in the description.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
6 tool updates
v0.3.0- Added
create_private_multi_seed_radio_playlist - Changed
create_private_radio_playlist3 fields changed- added
Output schema / $defs / TrackResult / properties / albumAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Album" +} - added
Output schema / $defs / TrackResult / properties / duration_secondsAdded value: +{ + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Duration Seconds" +} - changed
Output schema / $defs / TrackResult / requiredPrevious value: -[ - "videoId", - "title", - "artists", - "duration", - "url" -]New value: +[ + "videoId", + "title", + "artists", + "album", + "duration", + "duration_seconds", + "url" +]
- Added
get_multi_seed_radio - Changed
get_song_radio3 fields changed- added
Output schema / $defs / TrackResult / properties / albumAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Album" +} - added
Output schema / $defs / TrackResult / properties / duration_secondsAdded value: +{ + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Duration Seconds" +} - changed
Output schema / $defs / TrackResult / requiredPrevious value: -[ - "videoId", - "title", - "artists", - "duration", - "url" -]New value: +[ + "videoId", + "title", + "artists", + "album", + "duration", + "duration_seconds", + "url" +]
- Added
resume_private_playlist - Changed
search_songs3 fields changed- added
Output schema / $defs / TrackResult / properties / albumAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Album" +} - added
Output schema / $defs / TrackResult / properties / duration_secondsAdded value: +{ + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Duration Seconds" +} - changed
Output schema / $defs / TrackResult / requiredPrevious value: -[ - "videoId", - "title", - "artists", - "duration", - "url" -]New value: +[ + "videoId", + "title", + "artists", + "album", + "duration", + "duration_seconds", + "url" +]
3 tool updates
v0.1.0- First observed
create_private_radio_playlist - First observed
get_song_radio - First observed
search_songs
TDQS
Scored across 6 tools
Each tool targets a distinct action: searching, generating a single-seed radio, creating a playlist from that radio, generating a multi-seed radio, creating a playlist from a multi-seed radio, and resuming an existing playlist. Though some tools pair as get/create for the same seed type, the names and intended step in the workflow are clear.
All tools follow a consistent snake_case verb_noun pattern: search_songs, get_song_radio, create_private_radio_playlist, get_multi_seed_radio, create_private_multi_seed_radio_playlist, resume_private_playlist. The prefix clearly distinguishes action and the noun hierarchy is logical.
Six tools are well-scoped for a YouTube Music radio playlist server. There are enough tools to cover the basic discovery and playlist creation flow without overwhelming the agent, and each tool contributes a meaningful operation.
The surface covers search, radio creation (single and multi-seed), playlist creation from both, and resuming a saved track plan, which supports the core workflow end-to-end. Minor gaps exist—such as no explicit update or delete playlist operations—but they are outside the apparent main purpose and can be worked around by re-creating.
Maintenance
Related MCP Connectors
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.
1YouTube MCP — wraps the YouTube Data API v3 (BYO API key)
Search YouTube, read video metadata, and fetch transcripts with language preferences
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to search for music and create/manage playlists on YouTube Music via OAuth 2.0 authentication.1MIT
- FlicenseNot gradedqualityDmaintenanceMCP server for YouTube Music that enables searching songs and artists, managing playlists, and authenticating via Google OAuth, using STDIO transport.-
- FlicenseNot gradedqualityCmaintenanceEnables searching YouTube Music and managing playlists: create/delete playlists, add/remove/reorder tracks, and more via natural language.-
- AlicenseBqualityBmaintenanceEnables AI assistants to search YouTube Music, manage playlists, and retrieve listening history using the ytmusicapi library.6MIT