Skip to main content
Glama
kvechkanov

youtube-playlists-mcp

by kvechkanov

youtube-playlists-mcp

CI License: MIT Node.js 22+

A small Model Context Protocol (MCP) server that wraps the YouTube Data API v3, so an AI assistant can manage your YouTube playlists (for example a "learning watch list") and search for videos.

  • Transport: stdio

  • Language: TypeScript (Node.js 22+)

  • Auth: OAuth 2.0 with PKCE, scope https://www.googleapis.com/auth/youtube. Tokens refresh automatically, and a rejected token is refreshed and the call retried once.

  • Quota-aware: every tool description states its quota cost, and search results are cached.

Tools

Tool

What it does

Quota cost

list_my_playlists

Lists your playlists (id, title, item count, privacy)

1

list_playlist_items

Lists videos in a playlist, with playlistItemId and videoId

1 per page (50 items)

add_to_playlist

Adds a video (ID or URL) to a playlist

50

remove_playlist_item

Removes an entry by playlistItemId

50

create_playlist

Creates a playlist (private by default)

50

search_videos

Searches videos, up to 10 results

100 (0 when served from cache)

Quota

The default quota is 10,000 units per day per Google Cloud project and resets at midnight Pacific time. search_videos is the expensive one: about 100 uncached searches a day would use it all. Identical searches (same query, page size, page token) are cached on disk for 24 hours (YOUTUBE_SEARCH_CACHE_TTL_HOURS) and cost nothing. If you hit the limit, tools return a quotaExceeded error. See the quota calculator for costs.

Related MCP server: YouTube MCP Server

Setup

1. Google Cloud (one time, about 10 minutes)

  1. Open the Google Cloud Console and create a project.

  2. APIs & Services → Library: enable YouTube Data API v3.

  3. APIs & Services → OAuth consent screen (Google Auth Platform): choose External, fill in the app name and your email, and add your Google account under Test users (Google Auth Platform → Audience → Add users). If you skip this, sign-in fails with "Access blocked: … has not completed the Google verification process".

  4. Credentials → Create credentials → OAuth client ID, application type Desktop app. Leave "Use this client for an AI-powered agent" unticked (it is for clients that use Google's own MCP tools; this server calls the YouTube Data API directly). Copy the client ID and client secret.

  5. Optional but recommended: once everything works, set the consent screen's publishing status to In production. For personal use you don't need Google verification (you'll see an "unverified app" warning that you can click through). While the app is in Testing, Google expires refresh tokens after 7 days, and you'd have to re-run the auth step weekly.

2. Install and build

git clone https://github.com/kvechkanov/youtube-playlists-mcp.git
cd youtube-playlists-mcp
npm install   # also builds dist/

Or skip the clone and run it straight from GitHub with npx github:kvechkanov/youtube-playlists-mcp (npm builds it on first use). Everywhere below, node dist/index.js and npx github:kvechkanov/youtube-playlists-mcp are interchangeable. The package is not published to the npm registry.

3. Authorize (one time)

Set your credentials in the environment (don't commit them):

export YOUTUBE_CLIENT_ID="...apps.googleusercontent.com"
export YOUTUBE_CLIENT_SECRET="..."

The script works on machines where you can't open a browser to localhost (a remote box, for example). It prints a sign-in URL; after you sign in, your browser is redirected to http://localhost:8085/?code=..., which fails to load. That's expected. Copy the full URL from the address bar and give it back to the script.

Interactive:

node dist/index.js auth

Or in two non-interactive steps (useful when someone else relays the URL):

node dist/index.js auth url        # prints the sign-in URL and saves PKCE state
node dist/index.js auth finish "http://localhost:8085/?code=...&state=..."

Paste the whole URL, not just the code: its state value is checked against the one saved by url.

The refresh token is written to ~/.config/youtube-playlists-mcp/token.json with mode 600. The PKCE state from url is valid for 30 minutes and must be used on the same machine and user.

4. Run the server

YOUTUBE_CLIENT_ID=... YOUTUBE_CLIENT_SECRET=... node dist/index.js

Register it in any MCP client (Claude Desktop, Cursor, Grok Bot, ...) as a stdio server:

{
  "mcpServers": {
    "youtube": {
      "command": "node",
      "args": ["/absolute/path/to/youtube-playlists-mcp/dist/index.js"],
      "env": {
        "YOUTUBE_CLIENT_ID": "...apps.googleusercontent.com",
        "YOUTUBE_CLIENT_SECRET": "..."
      }
    }
  }
}

To run it from GitHub instead of a local clone, use "command": "npx" with "args": ["-y", "github:kvechkanov/youtube-playlists-mcp"] and the same env.

Without credentials or a token, the server still starts and lists its tools. Calling a tool returns an error beginning with NOT AUTHORIZED: that says what to do.

Configuration

Variable

Default

Purpose

YOUTUBE_CLIENT_ID

(required)

OAuth client ID

YOUTUBE_CLIENT_SECRET

(required)

OAuth client secret

YOUTUBE_TOKEN_PATH

~/.config/youtube-playlists-mcp/token.json

Where the token is stored

YOUTUBE_CONFIG_DIR

~/.config/youtube-playlists-mcp

Token and pending-auth directory. A token in the old ~/.config/youtube-grok-bot-connector is used if the new directory has none

YOUTUBE_CACHE_DIR

~/.cache/youtube-playlists-mcp

Search cache directory

YOUTUBE_SEARCH_CACHE_TTL_HOURS

24

Search cache lifetime in hours (0 or more)

YOUTUBE_REDIRECT_PORT

8085

Port in the redirect URI (nothing listens on it; Desktop-app clients accept any loopback port)

Invalid numeric values (YOUTUBE_REDIRECT_PORT, YOUTUBE_SEARCH_CACHE_TTL_HOURS) stop startup with an error naming the variable.

Troubleshooting

Symptom

Fix

Access blocked: … has not completed the Google verification process

Add your Google account under Test users (Audience page), or publish the app.

Google hasn't verified this app warning

Expected for personal apps. Click Advanced → Go to … (unsafe).

localhost:8085 page fails to load after sign-in

Expected. Copy the full URL from the address bar and paste it into auth / auth finish.

authorization code … expired or was already used

Run auth url again and sign in with the new link.

refresh token rejected every ~7 days

The app is in Testing. Set publishing status to In production, then re-run auth.

Google did not return a refresh token

Revoke the app at https://myaccount.google.com/permissions and run auth again.

token file … is corrupt

Delete that file and run auth again.

quotaExceeded

The 10,000 daily units are used up. It resets at midnight Pacific time.

Security notes

  • Secrets live only in environment variables and the 600-mode token file, outside the repository. .gitignore also excludes token.json, .env, and credentials files.

  • The scope youtube grants full management of your YouTube account (playlists, and more). Treat the token like a password. Revoke it any time at https://myaccount.google.com/permissions.

  • The server only calls Google endpoints (accounts.google.com, oauth2.googleapis.com, www.googleapis.com).

Development

npm run build      # compile to dist/
npm run lint       # Biome; `npm run format` fixes
npm run typecheck
npm test           # builds, then runs the tests

The tests start the server and the auth CLI in an empty home directory against a local mock of Google's endpoints, so they make no network calls. See CONTRIBUTING.md and the CHANGELOG.

License

MIT © 2026 Kostya Vechkanov

Related MCP Connectors

Related MCP Servers