Skip to main content
Glama
CreatorGeetansh

YouTube MCP Server

YouTube MCP Server

An open-source Model Context Protocol (MCP) server for using YouTube from MCP clients such as Claude Desktop, Claude Code, and Codex.

The primary workflow is:

  1. Give an MCP client a list of songs.

  2. Review ranked YouTube matches before anything is changed.

  3. Create a private playlist from the selected videos.

The server will also provide quota-conscious tools for searching YouTube and reading videos, channels, playlists, and comments.

IMPORTANT

The TypeScript package, stdio server, public and authenticated reads, PKCE OAuth, music preparation, confirmed new-playlist creation, and full previewed playlist mutations are implemented and tested. Adding a prepared music draft directly to anexisting playlist remains planned: today, songs can only be inserted at playlist-creation time.

Design goals

  • Safe playlist writes with preview-before-commit semantics.

  • Official YouTube Data API v3 endpoints only.

  • Bring-your-own Google OAuth client; the project never ships shared Google credentials.

  • Secrets stored in the operating-system keychain whenever possible.

  • Predictable quota use, pagination, caching, retries, and normalized errors.

  • Local stdio transport for simple installation and a small attack surface.

  • Structured, bounded tool outputs that treat YouTube content as untrusted data.

  • Cross-platform TypeScript support on Node.js 20.17 or newer.

Planned v1 scope

Read tools

  • Search videos, channels, and playlists.

  • Read video, channel, playlist, and comment data.

  • Read the authenticated user's channel, uploads, and playlists.

  • Return provider page tokens for explicit, stateless pagination.

Music playlist workflow

  • Accept up to 50 structured tracks per preparation request.

  • Search and rank likely YouTube music-video matches.

  • Show ambiguity and alternatives instead of silently choosing weak matches.

  • Commit explicitly selected matches to a new playlist. An existing-playlist target is planned.

  • Default new playlists to private.

Playlist management

  • Create playlists and add videos.

  • Update playlist metadata or privacy.

  • Reorder or remove playlist items.

  • Delete playlists after a short-lived, one-time confirmation handle is issued.

Playlist updates, item removal/reordering, and deletion use two tools: youtube_prepare_playlist_mutation returns the exact diff and a 10-minute handle without writing; youtube_apply_playlist_mutation rechecks ownership and the playlist snapshot before consuming that handle once.

Writes outside playlist management—uploads, comments, ratings, subscriptions, and channel changes—are deliberately out of scope.

Setup

The npm package has not been published yet, so the server is built and run from a clone. Work through the steps in order.

Step 1 — check for Node.js and npm

node -v
npm -v

If node -v prints v20.17 or newer and npm -v prints a version, skip to Step 3. If either command reports "command not found", continue with Step 2.

Step 2 — install Node.js and npm (only if Step 1 failed)

npm ships with Node.js; installing Node installs both. Pick one row for your platform, then re-run Step 1 to confirm.

Platform

Command

macOS (Homebrew)

brew install node@22

macOS / Windows / Linux (no package manager)

Download the LTS installer from nodejs.org/en/download and run it

Windows (winget)

winget install OpenJS.NodeJS.LTS

Debian / Ubuntu

curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash - && sudo apt-get install -y nodejs

Fedora / RHEL

sudo dnf install nodejs npm

If you would rather not install Node system-wide, or you need several Node versions side by side, use a version manager:

# macOS and Linux
curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
nvm install 22
nvm use 22

On Windows the equivalent is nvm-windows: nvm install 22 then nvm use 22.

Close and reopen the terminal after installing, then re-run node -v and npm -v.

Step 3 — install dependencies and build

git clone <repository-url>
cd "Youtube MCP"
npm ci
npm run build

npm ci installs the exact versions in package-lock.json; use npm install only when you intend to change dependencies. The build writes the executable to dist/cli/index.js, which every command below invokes.

Verify the build and the local data directory:

node dist/cli/index.js doctor

Step 4 — create the Google credentials

Everything below comes from your own Google Cloud project. This project never ships shared Google credentials.

  1. Create or select a project in the Google Cloud console.

  2. Enable YouTube Data API v3 for that project.

  3. Create an API key (Credentials → Create credentials → API key). This covers public reads.

  4. Configure the OAuth consent screen. While the project is in Testing status, add your own Google account under Test users, or login will be refused.

  5. Create an OAuth client of type Desktop app, then copy both its client ID and its client secret.

Google requires client_secret in the authorization-code exchange even for installed applications, so PKCE supplements the secret here rather than replacing it.

Step 5 — the credentials the server needs

Four credentials exist in total. You supply the first three; the fourth is obtained for you by login.

Credential

Needed for

Where it comes from

How you supply it

Where it is kept

YOUTUBE_API_KEY

Public reads (search, videos, channels, public playlists, comments)

Step 4.3

Process environment only

Not persisted. It is read from the environment on every start, so an MCP client must pass it in each launch.

YOUTUBE_OAUTH_CLIENT_ID

Any account action: reading your own playlists, creating playlists

Step 4.5

YOUTUBE_OAUTH_CLIENT_ID env var, or the interactive setup prompt

Profile JSON in the data directory. It is not a secret.

YOUTUBE_OAUTH_CLIENT_SECRET

The authorization-code exchange during login

Step 4.5

YOUTUBE_OAUTH_CLIENT_SECRET env var, or the interactive setup prompt

Operating-system keychain, per profile. Never written to the profile JSON.

OAuth refresh token

Staying signed in across restarts

Produced by login

Operating-system keychain, per profile. Access tokens stay in memory only.

Optional environment variables: YOUTUBE_MCP_PROFILE (default default), YOUTUBE_MCP_DATA_DIR, and YOUTUBE_MCP_LOG_LEVEL (error, warn, info, debug). See .env.example.

Never paste any of these into a chat message, a shared MCP configuration file, or a command that will be committed. Prefer the interactive prompts or your client's environment/secret-injection field.

Step 6 — run setup, then log in

Run these in order. setup rewrites the profile's stored scopes and channel identity, so running it after login discards that state and requires logging in again.

macOS and Linux:

YOUTUBE_OAUTH_CLIENT_ID="YOUR_DESKTOP_CLIENT_ID" \
  YOUTUBE_OAUTH_CLIENT_SECRET="YOUR_DESKTOP_CLIENT_SECRET" \
  node dist/cli/index.js setup
node dist/cli/index.js login
node dist/cli/index.js status

Windows PowerShell:

$env:YOUTUBE_OAUTH_CLIENT_ID  = "YOUR_DESKTOP_CLIENT_ID"
$env:YOUTUBE_OAUTH_CLIENT_SECRET = "YOUR_DESKTOP_CLIENT_SECRET"
node dist\cli\index.js setup
node dist\cli\index.js login
node dist\cli\index.js status
Remove-Item Env:\YOUTUBE_OAUTH_CLIENT_SECRET

To avoid putting the secret in shell history or the process table at all, omit both variables and let setup prompt for them:

node dist/cli/index.js setup

setup prompts for each missing value when the terminal is interactive.

login opens Google's authorization page and returns through a random loopback port on 127.0.0.1, using PKCE S256 and a random state value. It fails immediately, before opening a browser, when no client secret is stored for the profile.

To revoke and remove the stored credential:

node dist/cli/index.js logout

Step 7 — start the server

YOUTUBE_API_KEY="your-api-key" node dist/cli/index.js serve

The server speaks MCP over stdio, so it is normally launched by a client rather than by hand. Available commands are serve, doctor, status, setup, login, and logout.

Local data location

Profiles, the quota ledger, drafts, and operation journals live in a 0700 directory:

Platform

Default path

macOS

~/Library/Application Support/youtube-mcp

Linux

$XDG_DATA_HOME/youtube-mcp, otherwise ~/.local/share/youtube-mcp

Windows

%LOCALAPPDATA%\youtube-mcp

Override with YOUTUBE_MCP_DATA_DIR. To remove all local state, run logout and then delete that directory. Keychain entries are removed by logout.

Connecting a client to the local build

Until the package is published, point clients at the absolute path of your built dist/cli/index.js.

Claude Code

claude mcp add youtube --scope user \
  --env YOUTUBE_MCP_PROFILE=default \
  --env YOUTUBE_API_KEY=your-api-key -- \
  node /absolute/path/to/Youtube\ MCP/dist/cli/index.js serve

Claude Desktop

{
  "mcpServers": {
    "youtube": {
      "command": "node",
      "args": ["/absolute/path/to/Youtube MCP/dist/cli/index.js", "serve"],
      "env": {
        "YOUTUBE_MCP_PROFILE": "default",
        "YOUTUBE_API_KEY": "your-api-key"
      }
    }
  }
}

Codex

[mcp_servers.youtube]
command = "node"
args = ["/absolute/path/to/Youtube MCP/dist/cli/index.js", "serve"]

[mcp_servers.youtube.env]
YOUTUBE_MCP_PROFILE = "default"
YOUTUBE_API_KEY = "your-api-key"

Re-run npm run build after pulling changes; clients execute the compiled dist output, not src.

Google authorization for this local server is performed by its own setup and login commands. Client-level MCP login commands do not replace the downstream Google OAuth flow.

Post-publication client configuration

Once the package is released, pin a released version instead of using latest so an MCP client cannot change behavior unexpectedly.

Claude Desktop

{
  "mcpServers": {
    "youtube": {
      "command": "npx",
      "args": ["-y", "@youtube-mcp/server@0.4.0", "serve"],
      "env": {
        "YOUTUBE_MCP_PROFILE": "default"
      }
    }
  }
}

On native Windows, use "command": "cmd" and prefix the arguments with "/c", "npx".

Claude Code

claude mcp add youtube --scope user \
  --env YOUTUBE_MCP_PROFILE=default -- \
  npx -y @youtube-mcp/server@0.4.0 serve

Codex

codex mcp add youtube \
  --env YOUTUBE_MCP_PROFILE=default -- \
  npx -y @youtube-mcp/server@0.4.0 serve

Equivalent Codex configuration:

[mcp_servers.youtube]
command = "npx"
args = ["-y", "@youtube-mcp/server@0.4.0", "serve"]

[mcp_servers.youtube.env]
YOUTUBE_MCP_PROFILE = "default"

How much can be added in one go

Hard schema limits per tool call:

Operation

Maximum per call

Tracks per youtube_prepare_music_playlist

50

Selections per youtube_commit_music_playlist

50

Video IDs per youtube_get_videos

50

Item removals per playlist mutation

50

Reorder moves per playlist mutation

50

Items per read page

50

So 50 songs is the ceiling for one playlist creation. Because a prepared draft cannot yet be committed into an existing playlist, a list longer than 50 songs must become more than one playlist.

The daily quota is the tighter constraint in practice. Against Google's default 10,000 units per project per day, one 50-song run costs roughly:

Step

Calls

Published unit cost

Subtotal

search.list, one per track

50

100

5,000

videos.list hydration, batched by 50

1–5

1

1–5

playlists.insert

1

50

50

playlistItems.insert

50

50

2,500

Total

≈ 7,550

That means roughly one 50-song playlist per project per day. A second full run the same day will exhaust the quota and fail partway through insertion. Preparing the same list twice is especially expensive: the searches are charged again even though the answers are unchanged.

Quota resets at midnight US Pacific time, which is the day boundary the local ledger uses.

Quota expectations

youtube_quota_status reports locally observed usage, not an authoritative Google balance. General units and search.list calls are tracked separately because Google applies a separate default daily search-call limit.

WARNING

Known limitation: the local ledger records eachsearch.list as 1 general unit plus 1 search call, while Google charges 100 units for it. After heavy searching, general_units therefore understates real consumption by 99 units per search, and a write can be rejected for quota while the reported figure still looks low. Treat the search_calls count as the meaningful signal until this is corrected. Previews still show an estimated_commit_units figure for the write portion of a commit.

Quota values can change. Implementation and release work must verify the current official cost table instead of treating values in this README as permanent constants.

Troubleshooting

A commit reports status: "partial" with empty completed and everything in pending. The playlist was created but the first insert was rejected — most often the daily quota. Nothing is retried blindly, so no duplicate items are written. Check youtube_quota_status, delete the empty playlist, and re-run after the Pacific-time reset. Because a draft is single-use, re-running requires a fresh youtube_prepare_music_playlist.

login fails before a browser opens. No client secret is stored for the profile. Run setup first, and confirm you are on the intended YOUTUBE_MCP_PROFILE.

Authorization succeeds, then stops working about a week later. Google OAuth projects left in Testing status issue refresh tokens that expire after seven days. Publish the consent screen or re-run login.

403 on a public read. YOUTUBE_API_KEY is missing from the server's environment. It is never persisted, so it must be present in every launch — including the env block of the MCP client configuration.

Authentication model

  • Public reads require YOUTUBE_API_KEY in the process environment.

  • Account reads require OAuth with the youtube.readonly scope.

  • Playlist creation requires youtube.force-ssl because Google does not provide a playlist-only scope.

  • The server counteracts that broad Google scope with a strict endpoint allowlist: only playlist and playlist-item write endpoints are callable.

  • Installed applications use Authorization Code + PKCE, a random state, and a loopback redirect on 127.0.0.1 with a random port.

  • Service accounts are not supported for ordinary YouTube accounts.

Never commit API keys, OAuth client data, access tokens, refresh tokens, local databases, debug logs, or .env files.

Captions and analytics

General public transcript retrieval is not part of v1. The official captions download endpoint is permission-gated and expensive, so unofficial scraping will not be used. Owner-authorized caption management may be considered later.

YouTube Analytics and Reporting APIs are also deferred. They require separate OAuth, data models, and operational behavior and should not complicate the initial playlist-focused server.

Development

The implemented stack is TypeScript, Node.js 20.17+, ESM, the official MCP TypeScript SDK, Zod validation, direct typed REST calls to approved Google endpoints, SQLite for local quota/draft/journal state, and an OS-keychain adapter for OAuth refresh tokens.

Current checks:

npm run format:check
npm run lint
npm run typecheck
npm test
npm run build

Implementation should follow the phases and acceptance gates in PLAN.md. Agent-specific constraints and definitions of done are in AGENTS.md. Claude Code should begin with CLAUDE.md.

Project status

  • Product and security architecture

  • Repository development instructions

  • TypeScript package scaffold

  • Public read tools

  • OAuth and profiles

  • Music matching and preview

  • Confirmed new-playlist creation

  • Previewed playlist update, reorder, removal, and deletion

  • Existing-playlist target for music draft commits

  • Correct search.list general-unit accounting in the quota ledger

  • Cross-client integration tests

  • First npm release

License

Licensed under the Apache License 2.0. The complete license text is in LICENSE.

References

-
license - not tested
Not graded
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

  • YouTube MCP — wraps the YouTube Data API v3 (BYO API key)

  • Search YouTube and read video, channel and transcript data as JSON. No Google Cloud project.

  • Manage SRG+ hubs, channels, content, assets, users, and workspaces from any MCP-aware AI agent.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/CreatorGeetansh/YouTube-MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server