youtube-mcp

youtube-mcp

A lightweight MCP server for reading public YouTube data, offering tools to fetch video transcripts, playlist contents, and video metadata without requiring an API key.

Category
访问服务器

README

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
youtube_transcript what is said in a video, as plain text, optionally trimmed to a time window, plus which language it came back in
youtube_playlist the videos in a playlist, in order
youtube_video_facts 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

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 .env

All 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
YOUTUBE_USE_PROXY false the switch that turns the proxy on
YOUTUBE_PROXY_URL unset proxy endpoint, credentials included
MCP_TRANSPORT stdio stdio or http
MCP_HOST 127.0.0.1 bind address, http only
PORT 8000 bind port, http only
PUBLIC_BASE_URL 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_mcp

Over HTTP, for when the server lives somewhere else:

uv run python -m youtube_mcp --transport http --host 0.0.0.0 --port 8000

The 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_mcp

Remote, 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.

  1. Push the repo to GitHub.
  2. In Railway, create a project from the repo. It finds the Dockerfile by itself.
  3. Under Settings, Variables, add:
    • MCP_TRANSPORT = http
    • MCP_HOST = 0.0.0.0
    • YOUTUBE_USE_PROXY = true
    • YOUTUBE_PROXY_URL = your proxy endpoint
  4. 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 domain

Two 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 on youtube.com, m.youtube.com or youtu.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_seconds but is still being spoken at that moment is kept whole, because half a sentence is worth less than a slightly wider clip.
  • start_seconds has to be strictly smaller than end_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_playlist also accepts a watch link that happens to be playing inside a playlist, since it carries the same list= 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 pytest

Nothing 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 SVG

The 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

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选