YouTube MCP Server
Provides tools for searching YouTube videos, channels, and playlists, reading video and comment data, and managing playlists, including creating private playlists and previewing mutations before applying them.
Click on "Install 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., "@YouTube MCP ServerTurn these songs into a private YouTube playlist, showing me matches first."
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.
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:
Give an MCP client a list of songs.
Review ranked YouTube matches before anything is changed.
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.
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
stdiotransport 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 -vIf 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) |
|
macOS / Windows / Linux (no package manager) | Download the LTS installer from nodejs.org/en/download and run it |
Windows (winget) |
|
Debian / Ubuntu |
|
Fedora / RHEL |
|
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 22On 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 buildnpm 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 doctorStep 4 — create the Google credentials
Everything below comes from your own Google Cloud project. This project never ships shared Google credentials.
Create or select a project in the Google Cloud console.
Enable YouTube Data API v3 for that project.
Create an API key (Credentials → Create credentials → API key). This covers public reads.
Configure the OAuth consent screen. While the project is in Testing status, add your own Google account under Test users, or
loginwill be refused.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 |
| 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. |
| Any account action: reading your own playlists, creating playlists | Step 4.5 |
| Profile JSON in the data directory. It is not a secret. |
| The authorization-code exchange during | Step 4.5 |
| Operating-system keychain, per profile. Never written to the profile JSON. |
OAuth refresh token | Staying signed in across restarts | Produced by | — | 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 statusWindows 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_SECRETTo 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 setupsetup 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 logoutStep 7 — start the server
YOUTUBE_API_KEY="your-api-key" node dist/cli/index.js serveThe 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 |
|
Linux |
|
Windows |
|
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 serveClaude 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 serveCodex
codex mcp add youtube \
--env YOUTUBE_MCP_PROFILE=default -- \
npx -y @youtube-mcp/server@0.4.0 serveEquivalent 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 | 50 |
Selections per | 50 |
Video IDs per | 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 |
| 50 | 100 | 5,000 |
| 1–5 | 1 | 1–5 |
| 1 | 50 | 50 |
| 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.
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_KEYin the process environment.Account reads require OAuth with the
youtube.readonlyscope.Playlist creation requires
youtube.force-sslbecause 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 on127.0.0.1with 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 buildImplementation 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.listgeneral-unit accounting in the quota ledgerCross-client integration tests
First npm release
License
Licensed under the Apache License 2.0. The complete license text is in LICENSE.
References
This server cannot be installed
Maintenance
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.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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