Skip to main content
Glama
william-weber

yt-playlist-mcp

README.md
# yt-playlist-mcp

Local MCP server for Claude Desktop that searches YouTube and creates
playlists on your own account.

**Tools**

- `search_youtube(query, max_results)` — video search with title, channel,
  duration, URL
- `create_playlist(title, video_ids[], description?)` — creates a **private**
  playlist and adds the videos in order
- `search_playlists(query?)` — lists your own playlists (optionally filtered
  by title substring) so later sessions can find one by ID
- `add_to_playlist(playlist_id, video_ids[])` — appends videos to an existing
  playlist
- `list_playlist_items(playlist_id)` — lists a playlist's videos in order
- `remove_video(playlist_id, video_id)` — removes all occurrences of a video
  from a playlist
- `reorder_playlist(playlist_id, video_ids[])` — puts the given videos first,
  in order; pass the full list to sort a whole playlist
- `delete_playlist(playlist_id)` — permanently deletes a whole playlist

Auth is OAuth 2.0 (Desktop-app client): a one-time browser consent flow stores
a refresh token at `~/.config/yt-playlist-mcp/token.json` (mode 600); after
that the server refreshes access tokens silently.

## 1. Google Cloud setup (one time, in the browser)

1. Go to <https://console.cloud.google.com/> and create a new project
   (e.g. `yt-playlist-mcp`).
2. **Enable the API**: APIs & Services → Library → search "YouTube Data API v3"
   → Enable.
3. **OAuth consent screen**: APIs & Services → OAuth consent screen
   (Google may call this "Google Auth Platform → Branding/Audience").
   - User type: **External**
   - App name / support email / developer email: anything (only you will see it)
   - Scopes: you can skip adding scopes here; the app requests
     `https://www.googleapis.com/auth/youtube` at runtime
   - **Publish the app** (Audience → "Publish app" → confirm "In production").
     Leaving it in *Testing* status makes Google expire the refresh token
     every 7 days, forcing you to re-run the auth flow weekly. Published but
     unverified is fine for personal use — you'll click through one
     "Google hasn't verified this app" warning during consent
     (Advanced → "Go to yt-playlist-mcp (unsafe)").
4. **Create credentials**: APIs & Services → Credentials → Create credentials
   → OAuth client ID → Application type: **Desktop app**. Copy the
   **Client ID** and **Client secret**.

## 2. Build and authorize

```sh
npm install
npm run build
YOUTUBE_CLIENT_ID=xxx.apps.googleusercontent.com \
YOUTUBE_CLIENT_SECRET=yyy \
npm run auth
```

`npm run auth` opens your browser; sign in with the Google account whose
YouTube you want to manage, click through the unverified-app warning, and
approve. Tokens land in `~/.config/yt-playlist-mcp/token.json`.

Re-run `npm run auth` any time to re-authorize (e.g. if you revoke access at
<https://myaccount.google.com/permissions>).

## 3. Hook up Claude Desktop

Edit `~/Library/Application Support/Claude/claude_desktop_config.json`
(create it if missing) — use **absolute paths**, since Claude Desktop does not
launch servers from this directory:

```json
{
  "mcpServers": {
    "youtube": {
      "command": "/absolute/path/to/node",
      "args": ["/Users/will/Projects/youtube-mcp/dist/index.js"],
      "env": {
        "YOUTUBE_CLIENT_ID": "xxx.apps.googleusercontent.com",
        "YOUTUBE_CLIENT_SECRET": "yyy"
      }
    }
  }
}
```

(`which node` prints the node path.) Restart Claude Desktop; the two tools
appear under the `youtube` server.

## Quota

The YouTube Data API grants 10,000 units/day by default:

- `search_youtube`: ~101 units per call (search 100 + videos.list 1)
- `create_playlist`: 50 units + 50 per video added
- `add_to_playlist`: 50 units per video
- `remove_video`: ~51 units (lookup 1 + delete 50 per occurrence)
- `search_playlists`: 1 unit per 50 playlists
- `list_playlist_items`: 1 unit per 50 videos
- `delete_playlist`: ~51 units
- `reorder_playlist`: 50 units per video actually moved (already-in-place
  videos cost nothing)

So roughly 90 searches/day, or fewer if you create large playlists. Quota
errors come back as tool errors mentioning `quotaExceeded`.

## Development

```sh
npm run build   # tsc → dist/
npm start       # run the stdio server directly (for inspector/debugging)
npx @modelcontextprotocol/inspector node dist/index.js   # interactive test UI
```

Secrets never live in the repo: client ID/secret come from env vars
(`.env.example` documents them), tokens live under `~/.config/yt-playlist-mcp/`.