youtube-mcp
Fetches video transcripts, playlist contents, and metadata (title, channel, duration, publish date, views, likes, description, caption languages) from YouTube.
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-mcpGet the transcript of this YouTube video"
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
A small MCP server that lets a model read public YouTube data. Three tools, no API key, nothing clever:
tool | what you get |
| what is said in a video, as plain text, optionally trimmed to a time window, plus which language it came back in |
| the videos in a playlist, in order |
| title, channel, duration, publish date, views, likes, description, caption languages |
That is the entire surface. The server fetches, checks the link, trims by timestamp and returns. Summarising, searching and ranking are the calling model's job, not this server's.
Requirements
Python 3.12 or newer
uv for the short path, though plain pip is fine
Related MCP server: YouTube MCP
Install
git clone https://github.com/chiekh-a/youtube-mcp.git
cd youtube-mcp
uv venv
uv pip install -e ".[dev]"With pip instead:
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"Configuration
Copy the example file and fill in whatever you need:
cp .env.example .envAll of it is optional. With an empty .env the server still runs, it just talks
to YouTube directly from wherever it happens to be.
variable | default | what it does |
|
| the switch that turns the proxy on |
| unset | proxy endpoint, credentials included |
|
|
|
|
| bind address, http only |
|
| bind port, http only |
| unset | where the server is reachable, used for the icon URL |
PUBLIC_BASE_URL is only worth setting if you deploy somewhere that is not
Railway. Railway publishes the domain itself and the server picks it up. Leave
it unset over stdio, where the icon travels inline instead.
Why the proxy exists
YouTube is aggressive about blocking datacenter IP ranges. On your own machine you will usually be fine without a proxy. On a server (Railway, a VPS, CI) the transcript requests start coming back as bot checks fairly quickly, and pointing them at a residential proxy is the fix.
Both variables have to be set before anything is routed. A URL sitting in the
environment with YOUTUBE_USE_PROXY=false is ignored, which makes it easy to
flip on and off without editing config.
The proxy URL contains a password. It is never logged, and .env is gitignored.
Please keep it that way.
Run it
Over stdio, which is what a desktop MCP client expects:
uv run python -m youtube_mcpOver HTTP, for when the server lives somewhere else:
uv run python -m youtube_mcp --transport http --host 0.0.0.0 --port 8000The endpoint is /mcp, so a local server answers at
http://127.0.0.1:8000/mcp. Leave the trailing slash off. A URL ending in
/mcp/ gets redirected, and the redirect loses the session header, so the
client fails with a confusing 400.
Flags: --transport, --host, --port, --log-level. Logs always go to
stderr, because stdout belongs to the MCP protocol.
Connect a client
Local, over stdio
Drop this into claude_desktop_config.json, or .mcp.json for Claude Code, and
point the path at your checkout:
{
"mcpServers": {
"youtube": {
"command": "uv",
"args": [
"--directory",
"/absolute/path/to/youtube-mcp",
"run",
"python",
"-m",
"youtube_mcp"
],
"env": {
"YOUTUBE_USE_PROXY": "false"
}
}
}
}If you would rather not go through uv, call the venv's Python directly:
{
"mcpServers": {
"youtube": {
"command": "/absolute/path/to/youtube-mcp/.venv/bin/python",
"args": ["-m", "youtube_mcp"]
}
}
}Claude Code can skip the file editing entirely:
claude mcp add youtube -- uv --directory /absolute/path/to/youtube-mcp run python -m youtube_mcpRemote, over HTTP
Once it is deployed somewhere:
{
"mcpServers": {
"youtube": {
"type": "http",
"url": "https://your-app.up.railway.app/mcp"
}
}
}No trailing slash on that URL, for the reason above.
Deploy to Railway
There is a Dockerfile and a railway.json in the repo, so Railway needs very
little from you.
Push the repo to GitHub.
In Railway, create a project from the repo. It finds the Dockerfile by itself.
Under Settings, Variables, add:
MCP_TRANSPORT=httpMCP_HOST=0.0.0.0YOUTUBE_USE_PROXY=trueYOUTUBE_PROXY_URL= your proxy endpoint
Generate a domain under Settings, Networking.
PORT comes from Railway, so leave it alone.
From the CLI instead:
railway login
railway init
railway up
railway domainTwo things to keep in mind about a public deployment. The HTTP endpoint has no
auth on it, so anyone holding the URL can spend your proxy quota. And a hosted
IP will run into YouTube's bot checks without a residential proxy, which is the
whole reason YOUTUBE_USE_PROXY is there.
How it behaves
Small decisions that occasionally surprise people, all of them on purpose:
Only
https://links, and only onyoutube.com,m.youtube.comoryoutu.be.Shorts are turned away. Pass a regular video link.
Captions are tried in this order and the first hit wins: en, ar, fr, es, de, it, pt, ru, zh. If a video has none of those, you get whatever it does have rather than an error, since the model reading it can translate. The response says which language turned up, and whether a human wrote the captions or speech recognition did.
Trimming is an overlap test, not a containment test. A caption line that begins before
start_secondsbut is still being spoken at that moment is kept whole, because half a sentence is worth less than a slightly wider clip.start_secondshas to be strictly smaller thanend_seconds. Equal values are an error, and it is caught before any request goes out.A video with no captions in a supported language is an error. A time window that lands past the end of the video is simply an empty result.
Only text comes back, never timestamps. They are dead weight in a context window.
youtube_playlistalso accepts a watch link that happens to be playing inside a playlist, since it carries the samelist=id.
When something breaks
"Sign in to confirm you're not a bot", or "YouTube is blocking requests from
your IP". The host is on an IP range YouTube does not trust, which is normal
for any cloud provider. Set YOUTUBE_USE_PROXY=true with a working residential
proxy. Playlist listing often keeps working while transcripts and video facts
fail, so a partial outage like that is usually this.
Tunnel connection failed: 407 Proxy Authentication Required. The proxy is
reachable and it turned your credentials down. Check the username and password,
and check whether the provider expects the client IP to be allowlisted first.
The scheme on the proxy URL is not the problem, http:// and https:// behave
the same here.
A 400 from the HTTP endpoint straight after connecting. The client URL ends
in /mcp/. Drop the trailing slash.
Nothing at all over stdio. Something wrote to stdout. Only this server's own
logging is careful about that, so a stray print in your own changes is the
usual culprit.
Tests
uv run pytestNothing in the suite touches the network. An autouse fixture in
tests/conftest.py swaps both clients for tripwires that raise on contact, so a
forgotten stub fails loudly instead of quietly making live requests.
Layout
youtube_mcp/
__main__.py flags, transport choice, start
server.py the FastMCP instance and the three tools
links.py parsing YouTube URLs into ids
captions.py caption fetching and the time window
catalog.py yt-dlp: playlists and video facts
schemas.py what the tools return
settings.py the only module that reads the environment
errors.py the two ways a call can fail
branding.py the icon clients show, and the routes serving it
assets/ the icon itself, as PNG and SVGThe icon is a hand drawn play button rather than YouTube's official artwork, so there is nothing here that belongs to anyone else.
License
MIT
Available Tools
3 toolsyoutube_playlistA
List the videos in a YouTube playlist, in playlist order.
Returns watch URLs and the playlist title, nothing about the videos themselves. Use it to unpack a playlist, then call youtube_video_facts or youtube_transcript on the URLs you get back. A watch link that happens to be playing inside a playlist works here too.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | A youtube.com or youtu.be link |
Output Schema
| Name | Required | Description |
|---|---|---|
| count | Yes | How many videos were found |
| title | No | Playlist title |
| video_urls | Yes | Watch URLs, kept in playlist order |
| playlist_id | Yes | The playlist that was read |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full burden. It discloses what the tool returns (watch URLs and playlist title) and what it does not (video details), plus an edge case about watch links. While it doesn't explicitly state read-only semantics or error behavior, the verb 'List' and the outlined scope provide sufficient transparency for a simple operation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences, each with a distinct purpose: statement of core functionality, clarification of output scope, and usage guidance with an edge case. No redundant information, and the primary purpose is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter tool with an output schema, the description covers all necessary aspects: what it returns, what it excludes, how to use it in a workflow, and an edge case. The mention of sibling tools completes the integration picture, making it self-sufficient for an AI agent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema description for the single parameter is complete ('A youtube.com or youtu.be link'), but the tool description adds meaningful nuance: it clarifies that a watch link embedded in a playlist is also accepted. This goes beyond the schema and enriches the parameter semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool lists videos in a YouTube playlist in playlist order. It distinguishes itself from siblings by explicitly noting it returns only watch URLs and the playlist title, not video details, and directs users to call youtube_video_facts or youtube_transcript for that.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit usage guidance: use it to unpack a playlist, then call the sibling tools on the returned URLs. It also covers an edge case (watch links inside playlists), providing clear context on when and how to use the tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
youtube_transcriptA
Read what is said in a YouTube video, as plain text.
You get the whole thing by default. On a long video, narrow it with start_seconds and end_seconds so the response stays small. A caption line that straddles either edge of that window comes back whole rather than cut in half.
English is preferred, then a handful of widely spoken languages, and failing all of those whatever the video actually has. Check the language field on the way out and translate if you need to. The auto_generated field tells you whether a human wrote the captions or speech recognition did, which is worth knowing before you quote them.
The text has no timestamps in it. Shorts are not supported. If you only need the title, length or view count, youtube_video_facts is much cheaper.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | A youtube.com or youtu.be link | |
| end_seconds | No | Optional. Ignore everything after this point in the video | |
| start_seconds | No | Optional. Ignore everything before this point in the video |
Output Schema
| Name | Required | Description |
|---|---|---|
| text | Yes | Caption lines joined with newlines, no timestamps |
| language | Yes | Language code of the captions that were read, such as en or ko |
| video_id | Yes | The video the text came from |
| line_count | Yes | How many caption lines are in the text |
| auto_generated | Yes | True when YouTube produced the captions by speech recognition, which means more mistakes and no punctuation to speak of |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description fully discloses behavior: default returns whole transcript, window edges return whole caption lines, language fallback order, presence of language and auto_generated fields, absence of timestamps, and the Shorts limitation. This is rich, actionable behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well structured with a clear lead sentence followed by logically grouped details. Every sentence adds value—parameters, language behavior, output characteristics, and a pointer to an alternative—without unnecessary fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 3 parameters, an output schema, and no annotations, the description covers all critical aspects: input URL format, parameter semantics, edge cases, language handling, output limitations, and unsupported cases. It is fully complete for an agent to select and invoke correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, but the description adds semantic nuance beyond schema: it clarifies that start_seconds/end_seconds narrow the response, that 'the whole thing' is returned by default, and that caption lines straddling the window are returned whole. This goes beyond the schema's terse descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a clear, specific verb and resource: 'Read what is said in a YouTube video, as plain text.' It also differentiates from siblings by explicitly naming youtube_video_facts for metadata-only needs, making the tool's scope unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides explicit usage guidance: use start_seconds/end_seconds for long videos to keep responses small, warns that Shorts are unsupported, and directs users to youtube_video_facts when they only need title/length/view count. This covers when, when-not, and alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
youtube_video_factsA
Look up a YouTube video without reading its captions.
Gives you the title, channel, duration, publish date, view and like counts, the description, and which caption languages exist. Far cheaper than pulling a transcript, so start here when the question is about the video rather than its contents, or to check a video has captions before asking for them.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | A youtube.com or youtu.be link |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | Yes | Canonical watch URL |
| likes | No | Like count where public |
| title | No | Video title |
| views | No | View count |
| channel | No | Channel name |
| captions | No | Language codes with human written captions |
| video_id | Yes | YouTube video id |
| channel_url | No | Channel URL |
| description | No | Video description |
| published_on | No | Upload date, YYYY-MM-DD |
| auto_captions | No | Language codes with machine generated captions |
| duration_seconds | No | Length in seconds |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden. It discloses that the tool is cheaper than transcript retrieval, the exact data it returns, and that it does not read captions in the first sentence. It does not cover edge cases like unavailable videos, but for a simple read-only lookup, the transparency is solid.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded with the primary purpose. Every sentence adds value: the first sentence defines the action, the second enumerates return fields, and the third gives usage context. There is no redundancy or filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple one-parameter metadata lookup tool with an output schema, the description is complete. It covers what the tool does, what data it returns, and when to use it relative to sibling tools. The presence of an output schema means return format details need not be repeated here.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already provides a complete description for the single 'url' parameter (100% coverage). The description does not add extra meaning about the parameter beyond what the schema states, but it is not lacking since the schema is sufficient.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool looks up YouTube video metadata without reading captions. It lists specific data fields (title, channel, duration, publish date, counts, etc.) and differentiates from the sibling youtube_transcript by framing it as a metadata lookup rather than a transcript fetch.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit guidance is given: use this tool when the question is about the video itself, not its contents, and to check for captions before requesting a transcript. It also mentions the cost advantage over pulling a transcript, effectively saying when to prefer this tool over youtube_transcript.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
3 tool updates
v0.1.0- First observed
youtube_playlist - First observed
youtube_transcript - First observed
youtube_video_facts
TDQS
Each tool has a clearly distinct purpose: transcript extracts spoken content, playlist lists videos in a playlist, and video_facts provides metadata. There is no overlap or ambiguity between them.
All tool names follow the same pattern: 'youtube_' prefix followed by a descriptive noun or noun phrase. The naming is consistent and predictable, using lowercase with underscores throughout.
Three tools is a reasonable and well-scoped count for a YouTube-focused MCP server. Each tool covers a core, distinct capability without unnecessary bloat, falling within the typical 3-15 range.
The tool set covers the main YouTube interaction needs: reading transcripts, fetching video metadata, and enumerating playlists. Minor gaps exist (e.g., no search or comment retrieval), but the core workflows are complete and work well together.
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
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.
An MCP server that provides tools to discover and retrieve podcast episodes transcripts.
MCP server for RiverScript, an AI transcription platform - fetches transcripts shared via a link.
YouTube MCP — wraps the YouTube Data API v3 (BYO API key)
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceAn MCP server that enables interaction with the YouTube Data API, allowing users to search videos, get video and channel details, analyze trends, and fetch video transcripts.-
- AlicenseAqualityDmaintenanceAn MCP server that enables users to retrieve YouTube transcripts and perform video or channel searches without requiring Google API keys. It supports transcript chunking and provides tools for detailed video content analysis and channel metadata extraction.5584MIT
- AlicenseAqualityCmaintenanceAn MCP server that enables the extraction of transcripts and detailed metadata from YouTube videos. It allows users to retrieve video information like titles and descriptions, as well as transcripts with optional timestamps and language selection.2MIT
- FlicenseNot gradedqualityBmaintenanceMCP server for YouTube that provides tools to fetch video metadata and transcripts, enabling natural language queries about YouTube videos.2-
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/chiekh-a/youtube-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server