YouTube MCP Server
This MCP server lets clients inspect YouTube videos and search YouTube without requiring an API key by default, with an optional official API provider.
Get video metadata: title, channel, description, duration in text/seconds, views, likes, comment count, upload date, tags, thumbnail.
Fetch video comments with author, likes, date, replies, sorting by relevance/time, and pagination.
Fetch transcripts/captions with timestamps and plain text, choose language, paginate long transcripts; list available caption languages.
Search YouTube videos with filters for upload date and duration, sorting by relevance/date/views/rating, up to 50 results.
Report server version, active provider, whether authenticated, exact-search support, and backend per tool.
Return human-readable
contentplus structured JSON data, with coded errors in_meta; supports stdio and Streamable HTTP transports.
Enables GitHub Copilot to access YouTube data, including video search, details, comments, and transcripts.
Provides tools to search YouTube videos, retrieve video metadata, comments, transcripts, and available caption languages.
Click on "Deploy 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 Server search for recent Python tutorials"
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
YouTube MCP lets an MCP client read YouTube video metadata, caption transcripts, comments, and search results. By default it needs no YouTube API key or account; an optional official YouTube Data API provider serves metadata, comments, and search with an API key.
Supports both stdio (local) and Streamable HTTP (VPS/remote) transports.
Access model
This is an independent, unofficial open-source project. It is not affiliated with, endorsed by, or sponsored by YouTube or Google.
The default
innertubeprovider serves metadata, comments, and search throughyoutubei.js, using an unofficial/internal YouTube interface without a YouTube Data API key. Unofficial access may change, break, be restricted, or be blocked.Select
YT_PROVIDER=apiand supply your ownYOUTUBE_API_KEYto use the official YouTube Data API v3 for those three tools.Transcript tools always use
youtube-transcript-plus, regardless ofYT_PROVIDER. Transcript retrieval remains unofficial and does not use the official Data API path or your API key.
Users are responsible for deciding whether an access method suits their use and for complying with applicable service terms and law. See access methods and service terms for the tool/backend mapping, BYOK setup, limitations, and software licenses.
Related MCP server: yt
Features
Tool | Description |
| Search videos with filters for upload date and popularity |
| Video metadata: title, channel, description, duration, views, likes, upload date, tags |
| Comment threads with author info, likes, and the replies YouTube includes |
| Transcripts (manual + auto-generated captions) with timestamps |
| Lists available manual and auto-generated caption languages |
| Server version, active provider, and the backend serving each tool |
Requirements
Node.js 22 or newer. CI checks Node 22.21.0 and Node 24.
No YouTube API key required by default. The default
innertubeprovider usesyoutubei.js(an unofficial/internal YouTube interface) for video info, comments, and search. Transcripts always useyoutube-transcript-plus. Neither needs an API key or authentication. See Providers for the optional official API.
Quick start
Your MCP client can run the published package without a clone:
npx -y @granitebps/youtube-mcpThe server uses stdio. Keep stdout reserved for MCP traffic.
Run from a cloned repository
To develop the server or use a clone directly:
git clone https://github.com/granitebps/youtube-mcp.git
cd youtube-mcp
npm ci
npm run buildPoint your MCP client at the compiled entry point:
node /absolute/path/to/youtube-mcp/dist/index.jsRun npm run build after each source change. Do not use src or npm run dev as the client's stdio command; build output on stdout can corrupt MCP messages.
Client configuration
Each example starts with the npm package, followed by the local equivalent. Replace /absolute/path/to/youtube-mcp with your clone's path. Settings from Configuration can be added as environment variables.
Claude
Add the npm package to Claude Code:
claude mcp add youtube -- npx -y @granitebps/youtube-mcpFor a local build:
claude mcp add youtube -- node /absolute/path/to/youtube-mcp/dist/index.jsClaude Code uses local scope by default. Add --scope user before youtube to make the server available across projects.
Claude Desktop reads the same server from claude_desktop_config.json (on macOS, ~/Library/Application Support/Claude/claude_desktop_config.json). Restart the app after editing the file.
{
"mcpServers": {
"youtube": {
"command": "npx",
"args": ["-y", "@granitebps/youtube-mcp"]
}
}
}For a local build, replace command and args with:
{
"command": "node",
"args": ["/absolute/path/to/youtube-mcp/dist/index.js"]
}Codex
Add the npm package to ~/.codex/config.toml, or to .codex/config.toml in a trusted project:
[mcp_servers.youtube]
command = "npx"
args = ["-y", "@granitebps/youtube-mcp"]For a local build:
[mcp_servers.youtube]
command = "node"
args = ["/absolute/path/to/youtube-mcp/dist/index.js"]Restart Codex after editing the file.
OpenCode
Add the npm package to opencode.json or opencode.jsonc:
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"youtube": {
"type": "local",
"command": ["npx", "-y", "@granitebps/youtube-mcp"],
"enabled": true
}
}
}For a local build, replace the command array with:
{
"command": ["node", "/absolute/path/to/youtube-mcp/dist/index.js"]
}Cursor
Add the npm package to .cursor/mcp.json in a project, or to ~/.cursor/mcp.json for global use:
{
"mcpServers": {
"youtube": {
"command": "npx",
"args": ["-y", "@granitebps/youtube-mcp"]
}
}
}For a local build, replace command and args with:
{
"command": "node",
"args": ["/absolute/path/to/youtube-mcp/dist/index.js"]
}GitHub Copilot (VS Code)
Add to your VS Code settings.json:
{
"mcp": {
"servers": {
"youtube": {
"command": "npx",
"args": ["-y", "@granitebps/youtube-mcp"]
}
}
}
}VPS deployment (Streamable HTTP)
For remote deployment, the server runs as a persistent HTTP service using the Streamable HTTP transport (the current MCP standard, replacing the deprecated SSE transport).
1. Deploy to your VPS
# On your VPS
git clone https://github.com/granitebps/youtube-mcp.git
cd youtube-mcp
npm ci
npm run build
# Create .env (optional, for HTTP mode)
cp .env.example .env
# Uncomment TRANSPORT=http, PORT, HOST as neededYouTube often blocks datacenter IPs. If get_video_info returns ACCESS_BLOCKED with "Sign in to confirm you're not a bot", set YT_PROVIDER=api and YOUTUBE_API_KEY to serve metadata, comments, and search through the official API. See Providers.
2. Run with HTTP transport
# Using --http flag
node dist/index.js --http
# Or using environment variable
TRANSPORT=http PORT=3000 node dist/index.js
# Or using npm script
npm run start:httpThe server will listen on http://0.0.0.0:3000/mcp.
3. Set up Nginx reverse proxy with TLS
server {
listen 443 ssl;
server_name mcp.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/mcp.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mcp.yourdomain.com/privkey.pem;
location /mcp {
proxy_pass http://127.0.0.1:3000/mcp;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Required for SSE streaming
proxy_set_header Connection '';
proxy_buffering off;
proxy_cache off;
chunked_transfer_encoding on;
}
}Get a free TLS certificate:
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d mcp.yourdomain.com4. Keep it running with systemd
Create /etc/systemd/system/youtube-mcp.service:
[Unit]
Description=YouTube MCP Server
After=network.target
[Service]
Type=simple
User=your_user
WorkingDirectory=/path/to/youtube-mcp
ExecStart=/usr/bin/node dist/index.js --http
Restart=always
RestartSec=5
Environment=TRANSPORT=http
Environment=PORT=3000
Environment=HOST=127.0.0.1
[Install]
WantedBy=multi-user.targetsudo systemctl daemon-reload
sudo systemctl enable youtube-mcp
sudo systemctl start youtube-mcp
sudo systemctl status youtube-mcp5. Connect MCP clients to your VPS
GitHub Copilot (VS Code) — Remote
{
"mcp": {
"servers": {
"youtube": {
"type": "http",
"url": "https://mcp.yourdomain.com/mcp"
}
}
}
}Claude Desktop — Remote
{
"mcpServers": {
"youtube": {
"type": "streamable-http",
"url": "https://mcp.yourdomain.com/mcp"
}
}
}Usage Examples
Once connected, you can ask your AI agent things like:
"Get info about this YouTube video: https://www.youtube.com/watch?v=dQw4w9WgXcQ"
"Show me the top comments on video ID abc123"
"Get the transcript of this video in English"
"Summarize the transcript of https://youtu.be/xyz789"
"Search for Node.js tutorials uploaded this week, sorted by views"
"Find the most popular React videos from the last month"
Tool Response Format
All tools return:
content: short human-readable text for chat-style MCP clientsstructuredContent: JSON-shaped data for agents that need reliable fields
The server is intentionally JSON-first, text-second. Agents should prefer structuredContent when they need to filter, transform, or chain tool results.
Example shape from get_video_info:
{
"content": [
{
"type": "text",
"text": "📹 Example title\n\nChannel: Example channel\n..."
}
],
"structuredContent": {
"videoId": "dQw4w9WgXcQ",
"title": "Example title",
"description": "Example description",
"channelName": "Example channel",
"channelId": "UC123",
"uploadedAt": "Sep 14, 2017",
"duration": "3m 33s",
"durationSeconds": 213,
"viewCount": "123456",
"likeCount": "7890",
"commentCount": null,
"tags": ["music", "pop"],
"thumbnailUrl": "https://..."
}
}Values YouTube did not provide are null, never placeholders such as "0", "N/A" or "Unknown".
Errors
Failures return isError: true. The text starts with a code (❌ [ACCESS_BLOCKED] ...) and _meta["youtube-mcp/error"] carries the details:
{
"isError": true,
"content": [{ "type": "text", "text": "❌ [ACCESS_BLOCKED] YouTube requires sign-in to access video C7OQHIpDlvA: Sign in to confirm you’re not a bot" }],
"_meta": {
"youtube-mcp/error": {
"code": "ACCESS_BLOCKED",
"message": "...",
"retryable": false,
"upstream": { "playabilityStatus": "LOGIN_REQUIRED", "reason": "Sign in to confirm you’re not a bot", "accessKind": "login_required" }
}
}
}The error is in _meta, not structuredContent, because MCP SDK clients validate any structuredContent against the tool's output schema, even on error results.
Code | Meaning |
| Not a YouTube URL or 11-character video ID, or an invalid language code |
| YouTube refused this client: HTTP 429/403, CAPTCHA, consent page, sign-in or bot check. |
| YouTube reports the video as |
| Used internally; transcript tools return these as |
| Comments are disabled or YouTube returned no comments section |
| YouTube answered but the response could not be interpreted (layout change, wrong video ID returned) |
| A configured size limit was hit |
| A configured deadline expired; the underlying requests were aborted |
| The MCP client cancelled the request, or the server is shutting down |
| Other HTTP or network failure ( |
The server never retries on its own.
Providers
YT_PROVIDER selects the backend for get_video_info, get_video_comments, and search_youtube. get_video_transcript and get_transcript_languages always use youtube-transcript-plus, whichever provider is active. get_server_info reports the active provider.
Provider | Select with | Needs | Notes |
InnerTube | Default, or | Nothing | Uses an unofficial/internal interface through |
Official API |
|
| Uses the YouTube Data API v3. Subject to your Google Cloud project's quota, key restrictions, and applicable service terms |
This server does not use the Data API for captions. Google's caption-download endpoint requires OAuth authorization and permission to edit the video; an API key alone is insufficient. Transcript tools use the unofficial youtube-transcript-plus path and can return ACCESS_BLOCKED with either provider.
Using the official API
Bring your own key (BYOK). The key belongs to you; the project does not distribute or host a shared YouTube API key. Supply these settings through the process or MCP client environment; the server does not automatically load .env files.
In the Google Cloud console, create a project, enable YouTube Data API v3, and create an API key. Restricting the key to that API is recommended.
Start the server with:
YT_PROVIDER=api YOUTUBE_API_KEY=your_api_key npx -y @granitebps/youtube-mcpQuota (costs): the default allocation is 10,000 units per day, plus a separate allowance of 100 search.list calls per day.
Tool | API calls |
|
|
|
|
|
|
Results are cached as with the default provider (video info 30 min, comments 10 min, search 15 min), so repeated calls cost nothing. A used-up quota returns ACCESS_BLOCKED with upstream.accessKind: "quota_exceeded"; an invalid key or disabled API returns ACCESS_BLOCKED with accessKind: "forbidden".
Differences from the default provider:
uploadedAt(get_video_info) andpublishedAt(comments, search) are ISO 8601 timestamps instead of display text such as "Sep 14, 2017" or "2 days ago"Search
viewCountis a plain number such as"1234"instead of "1.2K views", anddurationuses the same format asget_video_info("3m 5s")search_youtubeapplies allsortByanduploadDatevalues exactly and never returnswarnings.videoDuration: "short"means under 4 minutes andmedium4 to 20 minutes (YouTube's API definitions)get_video_commentsreturns only the replies the API includes with each thread (a subset);replyCountis the full count
Configuration
All settings are optional environment variables, except YOUTUBE_API_KEY when YT_PROVIDER=api. Invalid values stop the server at startup with a message on stderr.
Variable | Default | Effect |
|
| Provider for video info, comments, and search: |
| none | Your own YouTube Data API v3 key. Required when |
|
| Deadline for creating the shared YouTube client |
|
| Deadline for one tool call's upstream work, including waiting for client init |
|
| Maximum bytes read from each response fetched for captions |
|
| Maximum caption segments processed from one track |
|
| Maximum segments returned in one |
When a deadline expires or the client cancels, the in-flight HTTP requests are aborted, not just abandoned.
Tool Details
search_youtube
Input:
query(search text),maxResults(1-50, default 10),sortBy(relevance|date|viewCount|rating),uploadDate(any|hour|today|week|month|year),videoDuration(any|short|medium|long)Returns: Human-readable summary in
contentplus structured JSON results instructuredContentNote: With the default
innertubeprovider, YouTube search only orders by relevance or popularity and only filters uploads fromtodayup.sortBy: "date"keeps relevance order,sortBy: "rating"sorts by popularity, anduploadDate: "hour"is applied astoday. Each case adds an entry to the optionalwarningsarray (code,message). Theapiprovider applies every option exactly
get_video_info
Input:
video(YouTube URL or video ID)Returns: Human-readable summary in
contentplus structured JSON metadata instructuredContent, includingdurationSeconds. Metadata is returned even when YouTube refuses playback, as long as it provides the video details
get_video_comments
Input:
video(URL or ID),maxResults(1-20, default 20),sortBy(relevanceortime),page(default 1)Returns: Human-readable summary in
contentplus structured JSON comment threads, pagination fields, andhasMoreinstructuredContentNote:
repliescontains only replies YouTube includes with the thread;replyCountis the full count. Fetching the rest would cost one request per thread
get_video_transcript
Input:
video(URL or ID),lang(optional language code; omitted means the first manual track, or the first auto-generated one if there is none),maxSegments(default0: as many asYT_TRANSCRIPT_PAGE_MAX_SEGMENTSallows),startSegment(default0)Returns: Human-readable transcript in
contentplus structured JSON segments, plain text, and pagination metadata instructuredContent. Continue withstartSegment = nextStartSegmentand the returnedlanguageCodeaslangwhilehasMoreis true.isAutoGeneratedtells whether the track is YouTube's automatic captionsNo captions:
available: falsewithreason: "NO_CAPTIONS", orreason: "LANGUAGE_UNAVAILABLE"plusavailableLanguages. Access problems are errors, neveravailable: falseNote: When a language has both manual and automatic tracks, the manual track is returned
Note: Does NOT require an API key — works via YouTube's internal caption system. A transcript is caption text only; it is not an analysis of the video's picture
get_transcript_languages
Input:
video(YouTube URL or video ID)Returns: Human-readable language list in
contentplus structured JSON language metadata instructuredContent.available: falsemeans the video is playable and has no caption tracks; access problems are errors
get_server_info
Input: none
Returns:
name,version,provider(innertubeorapi),authenticated,exactSearchFilters, andtools, a map from each tool to the backend serving it
Development
npm test # builds, then runs the offline test suite (no network access)
npm run check # tests plus release metadata, package contents, and tarball install checksSee CONTRIBUTING.md.
Release verification
The automated suite covers input parsing, configuration, error classification, cancellation, the compiled stdio entry point, release metadata, and installation from an npm tarball. It never calls YouTube. Live YouTube checks are manual and separate from CI.
Maintainers follow the release guide for the approved-tag npm, MCP Registry, and GitHub release process.
Rate Limits
The default innertube provider and transcript tools use unofficial YouTube interfaces. They do not use the Data API quota system, but this does not imply unrestricted access:
Heavy automated usage may trigger CAPTCHAs or temporary blocks
Requests from datacenter IPs (VPS, cloud) are often blocked outright
Request pacing does not guarantee access or establish permission under service terms
The api provider is limited by your Google Cloud project's YouTube Data API quota instead. See Providers.
License
ISC. The software license is separate from YouTube/Google service terms and rights in retrieved content. See the access guide.
Available Tools
6 toolsget_server_infoA
Report the server version, the active provider (innertube or api) for video info, comments, and search, and which backend serves each tool. Transcript tools always use youtube-transcript-plus.
Inputs: no named parameters. Returns: name, tools, version, provider, +2 more
get_transcript_languagesA
List all available caption/transcript languages for a YouTube video. Returns language codes and names for both manual and auto-generated captions. Call this first to discover available languages before fetching a transcript.
Inputs: video (required). Returns: message, videoId, available, languages, +3 more
get_video_commentsA
Get YouTube video comments with replies. Returns comment text, author, likes, and date. Supports sorting by 'relevance' (top comments) or 'time' (newest). Returns error if comments are disabled. Served by the provider selected with YT_PROVIDER.
Inputs: video (required), page, sortBy, maxResults. Returns: page, sortBy, hasMore, threads, +3 more
get_video_infoA
Get YouTube video metadata: title, channel, description, duration (text and seconds), views, likes, comment count, upload date, and tags. Unknown values are null. Served by the provider selected with YT_PROVIDER (see get_server_info). Input: YouTube URL or video ID. Errors carry a code (e.g. ACCESS_BLOCKED, VIDEO_UNAVAILABLE, TIMEOUT) in _meta["youtube-mcp/error"] and as a [CODE] text prefix.
Inputs: video (required). Returns: tags, title, videoId, duration, +9 more
get_video_transcriptA
Get YouTube video transcript/captions (manual or auto-generated) with timestamps. Use 'lang' to pick a language code (e.g. 'en', 'id'), or omit it to get the first manual track (else the first auto-generated one); get_transcript_languages lists the codes. Returns both timestamped and plain text versions, paginated with startSegment/nextStartSegment. available=false with reason NO_CAPTIONS or LANGUAGE_UNAVAILABLE when captions are absent; access problems (ACCESS_BLOCKED etc.) are errors.
Inputs: video (required), lang, maxSegments, startSegment. Returns: reason, hasMore, message, videoId, +10 more
search_youtubeA
Search YouTube videos by query. Returns up to 50 results with title, channel, views, duration, and URL. Supports filtering by uploadDate (today/week/month/year) and videoDuration (short/medium/long), and sorting by relevance, date, viewCount, or rating. Served by the provider selected with YT_PROVIDER; with the default innertube provider some options are approximated and reported in warnings.
Inputs: query (required), sortBy, maxResults, uploadDate, +1 more. Returns: query, sortBy, results, warnings, +3 more
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 6 tools
Each tool targets a clearly distinct resource and action: video metadata, comments, transcript content, language discovery, search, and server info. There is no overlap in purpose, and the transcript/language split is explicitly signposted (call get_transcript_languages first).
Most tools follow a get_<resource> pattern (get_video_info, get_video_comments, get_video_transcript, get_server_info), which is highly readable. Minor deviations exist: search_youtube uses a different verb form and get_transcript_languages breaks the get_video_ prefix used by its sibling transcript tool.
Six tools is well-scoped for a read-oriented YouTube data server, with each tool earning its place and no redundant operations. It sits comfortably in the ideal 3-15 range.
The surface covers the core read workflows well: video metadata, comments, transcripts, language discovery, and search. Gaps exist around channel-level and playlist operations, but these are workable omissions for a video-centric read-only server.
Maintenance
Related MCP Connectors
YouTube transcripts, search, channel browsing, and playlists for AI agents via MCP.
An MCP server that gives any LLM or agent clean YouTube transcripts on demand: a single video, a whole channel, or a playlist, plus AI cleanup of auto-generated captions. API-key auth, credit-based, same backend as the public v1 API. Get a free API key with 25 free credits at youtubetranscriptdownload.com/account.
Your agent needs to find video — which channels own a topic, which videos rank for a phrase, what exists in a given country and language. **What you can ask for** • "Which videos rank for 'rag pipeline tutorial' in the US this month?" • "Find channels publishing about MCP, sorted by relevance." • "What playlists cover this subject in Japanese?" • "Search videos uploaded this week only." **How to use it** Point any MCP client at https://mcp.aisa.one/youtube-search/mcp and sign in with OAuth — there is no key to create or paste. One search tool covering videos, channels and playlists, narrowed by country, language, upload date, duration and sort order. **It is also a door to the rest** The same login reaches 26 sources and 580+ operations. Find the video here, then ask the same agent what the channel's site traffic is or what the same phrase does in Google — without adding a second server. **What it costs** Finding and inspecting an operation is free. Running one is billed per call at API prices, with no seat and no monthly minimum, and every call takes max_price_usd so an agent cannot overspend by accident. **Where else it reaches** https://mcp.aisa.one/social/mcp for X plus Instagram, Reddit, Pinterest and YouTube; https://mcp.aisa.one/gtm/mcp for those plus Similarweb and Apollo.
YouTube transcripts, search, channel/playlist listings and upload tracking for AI agents.
Related MCP Servers
- AlicenseBqualityDmaintenanceAn MCP server that provides AI assistants with powerful tools to interact with YouTube, including video searching, transcript extraction, comment retrieval, and more.819Apache 2.0
- AlicenseNot gradedqualityNot gradedmaintenanceAn MCP server that provides YouTube data access without API keys or quotas. It enables agents to search videos, retrieve transcripts and metadata, and perform full-text search across cached content for AI context retrieval.3 npm-
- AlicenseAqualityDmaintenanceMCP server that lets AI agents search YouTube and fetch transcripts.23MIT
- FlicenseNot gradedqualityDmaintenanceMCP server for YouTube that provides tools to fetch video metadata and transcripts, enabling natural language queries about YouTube videos.2-