Skip to main content
Glama

ytmusic-control

Let a script, an AI agent or an MCP-capable app play and control the YouTube Music you are already signed in to, in your normal browser. No API keys, no paid credits, no separate browser profile, no screenshots.

$ ytm-control play "Continuum by SLVM Lord"
Playing Continuum by SLVMLORD (a song) in YouTube Music.

$ ytm-control playlist "early morning"
Playing your playlist 'Early Morning', starting with Dance With Me by Sam Smith.

$ ytm-control play "Continuum by Metallica"
Could not find 'Continuum by Metallica'. Nothing played. The closest results were: Continuum by Lemaitre; Continuum by SLVMLORD.

It comes in four small parts, all in this repository and all readable:

Part

What it is

extension/

A Chrome / Edge extension (plain JavaScript, about 250 lines). It works inside your own YouTube Music tab: types into the page's search box, reads the visible results, presses play, reads the player.

ytm_control/

A small Python helper that talks to the extension over 127.0.0.1 and offers a CLI and an MCP server.

skills/youtube-music/SKILL.md

A skill file that teaches an AI agent (Claude Code or any agent that loads skills) to use the CLI well.

ytm-control mcp

An MCP server (stdio) with the same abilities as tools, for any MCP-capable app.

Any app that can run a shell command or speak MCP can use it.

Why a browser extension

YouTube Music has no public API for controlling playback. This works the way you would: through the page itself, in your already signed-in session. That is also why it needs no login from the tool and why your account details never leave your browser.

Related MCP server: huashu-chrome

Install

You need Python 3.10+, Chrome or Edge, and YouTube Music open in a tab or installed as an app window.

pip install git+https://github.com/VirtualyMichael/ytmusic-control
  1. Run ytm-control extension-path and note the folder it prints.

  2. In Chrome or Edge open chrome://extensions (or edge://extensions), turn on Developer mode, press Load unpacked and pick that folder.

  3. Keep the browser open, then run ytm-control status. It should say the extension is connected (it can take up to about 30 seconds after the helper first starts).

  4. ytm-control play "Maps by Maroon 5".

The helper starts itself in the background the first time you run a command; ytm-control serve runs it in the foreground.

As an agent skill

Copy skills/youtube-music into your agent's skills folder (for Claude Code: ~/.claude/skills/youtube-music). The agent then runs the CLI for requests like "play something by Stellardrone" or "skip this song".

As an MCP server

Add this to your MCP client's configuration:

{ "mcpServers": { "youtube-music": { "command": "python", "args": ["-m", "ytm_control", "mcp"] } } }

Tools: play_music, play_playlist, music_action (like, unlike, shuffle, radio), search_music, play_result, music_control, now_playing, library_find, library_refresh. search_music followed by play_result lets the model read the whole result list and choose, instead of trusting one guess.

What makes it dependable

  • Names are compared with spaces ignored, so a speech recogniser's "SLVM Lord" finds "SLVMLORD".

  • It never plays a different artist's song with the right title. If nothing matches it says so and lists the closest results, so an agent can look at them and decide.

  • Real songs beat lyric videos, karaoke and covers, and "Eternity" beats "Eternity (Reprise)".

  • It checks that the right song actually started instead of reporting success after a click.

  • Names that cannot be read aloud: stylised spellings are matched by how they sound, so "Slum Lord" finds SLVMLORD (V stands in for U), "Kr3w" finds Krew, and spelling the first letters ("S L V M lord") works too. A sound-alike is never allowed to beat an exact spelling, and a different artist with the right title is still refused.

  • Your library: ytm-control library refresh reads all your playlists and the title and artist of every song in them (from your signed-in page, saved on your PC in ~/.ytm-control/ytm-library.json). Spoken or typed names are then put into your own spelling before searching.

Security and privacy

  • The extension is allowed on https://music.youtube.com/* only, with the permissions tabs, scripting and alarms. It talks only to ws://127.0.0.1:47821-47825, never the internet. See extension/README.md.

  • The helper accepts a WebSocket connection only from an extension (the browser reports the origin, so a web page is refused), and only from the first extension that connects, which it then remembers.

  • The command-line / MCP side talks to the helper over a local HTTP API on 127.0.0.1:47830-47832 that requires a secret token stored in ~/.ytm-control/token, refuses any request a browser makes cross-site (an Origin header), and refuses unexpected Host names (DNS rebinding).

  • Nothing is sent anywhere. There is no telemetry.

Limits, honestly

  • Unofficial. It drives YouTube Music's web page, which Google can change; if it stops finding results, the selectors in extension/content.js need updating. Using it is your decision under YouTube's terms of service.

  • Needs the browser open with a YouTube Music tab (it opens one for you if none is open).

  • A browser can block a page from starting audio when you have never interacted with that tab; the tool then says the song is loaded and you need to press play.

  • Playlists: only your saved playlists can be played by name (run ytm-control library refresh once). A name that is not in your library is refused, with the closest names listed, rather than guessed.

  • Tested with fake browsers and a fake page, plus live checks in Chrome on Windows. Not yet tested on macOS or Linux.

Development

pip install -e ".[dev]"
pytest
node tests/extension_test.mjs

Origin

Extracted from the YouTube Music control in Voice Assistant, a hands-free Windows voice assistant.

License

MIT, see LICENSE.

Available Tools

8 tools
library_findB

Check whether a song is in the user's saved YouTube Music playlists and how it is spelled there.

Inputs: query (required).

library_refreshA

Re-read all the user's playlists and songs from their signed-in YouTube Music (can take a minute).

Inputs: no named parameters.

music_controlC

pause, play (resume), toggle, next or previous.

Inputs: action (required).

now_playingA

What is playing in YouTube Music right now, and whether it is paused.

Inputs: no named parameters.

play_musicA

Search YouTube Music and play the best match, e.g. 'Maps by Maroon 5'. Never plays a different artist's song with the same title: says it could not find it instead (then use search_music and look at the results).

Inputs: query (required).

play_playlistB

Play one of the user's saved YouTube Music playlists by name (needs the library; says so when no saved playlist is called that and lists the closest names).

Inputs: name (required).

play_resultA

Press play on a result from the latest search_music (use its kind and number).

Inputs: kind (required), number (required).

search_musicA

List YouTube Music search results (kind, number, title, artist), best guess first, without playing. Pick one and call play_result.

Inputs: query (required).

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    B3.3/5.0

    Scored across 8 tools

    Disambiguation4/5

    Tools are mostly distinct: play_music auto-plays, search_music lists, play_result plays a selected result, and music_control handles playback state. Some overlap between play_music and search_music+play_result, but descriptions clarify the intended flows.

    Naming Consistency3/5

    Names use snake_case consistently, but patterns are mixed: four verb_noun (play_music, search_music), three noun_verb (music_control, library_find, library_refresh), and one state phrase (now_playing). Readable but not a single predictable pattern.

    Tool Count5/5

    8 tools is well-scoped for a music control server, covering playback, search, control, and library inspection without obvious redundancy.

    Completeness4/5

    Core lifecycle is covered: search, play, control, now playing, and library inspection. Missing write operations (add/remove songs to library, playlist creation/editing) and advanced controls (volume, seek, shuffle) are minor gaps for a playback-focused server.

    Maintenance

    ActivityMaintained
    ResponsivenessOutdated data

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      B
      maintenance
      Enables MCP clients to drive your already-open Chrome browser like a human, using 45 tools for navigation, perception, capture, and trusted input that pages receive as genuinely user-generated.
      MIT
    • A
      license
      Not graded
      quality
      B
      maintenance
      Enables any MCP-compatible AI agent to drive your own Chrome browser with your existing login state, filling forms, clicking elements, fetching data, and handling captchas without API keys or re-authentication.
      1,119 npm
      587
      MIT
    • A
      license
      Not graded
      quality
      C
      maintenance
      Enables MCP clients to directly operate your existing logged-in Chrome profiles, including cookies and extensions, without re-authentication or a headless browser. It provides tools for managing tabs, navigating, reading pages, clicking, typing, and launching profiles.
      4 npm
      MIT
    • F
      license
      Not graded
      quality
      C
      maintenance
      Enables a local MCP server to control an authenticated Chrome browser for interacting with Google Search, Gemini, ChatGPT, Claude, and DeepSeek, including web search and image generation without per-provider API keys.
      -