YouTube视频管理工具

yt-studio-mcp是一个通过YouTube Data API管理YouTube视频的MCP服务器,支持视频上传、缩略图设置、字幕上传、播放列表管理和直播调度,适用于内容创作者和视频工作流自动化。

  • by JamesTeague
  • TypeScript
  • 本地部署
  • 更新于
在 GitHub 查看 JamesTeague/yt-studio-mcp

使用说明

yt-studio-mcp

MCP server for YouTube video management -- upload, thumbnails, captions, playlists, and livestream scheduling via the YouTube Data API.

Installation

Run directly with npx:

npx yt-studio-mcp

Or install globally:

npm install -g yt-studio-mcp
yt-studio-mcp

Configuration

Google Cloud OAuth Setup

This server uses OAuth 2.0 to access the YouTube Data API on your behalf.

  1. Go to Google Cloud Console
  2. Create a new project (or select an existing one)
  3. Enable the YouTube Data API v3:
    • Navigate to APIs & Services > Library
    • Search for "YouTube Data API v3"
    • Click Enable
  4. Create OAuth 2.0 credentials:
    • Navigate to APIs & Services > Credentials
    • Click "Create Credentials" > "OAuth client ID"
    • Application type: Desktop application
    • Download or copy the Client ID and Client Secret
  5. Set environment variables:
export GOOGLE_CLIENT_ID="your-client-id"
export GOOGLE_CLIENT_SECRET="your-client-secret"
  1. Run the auth flow:
npx yt-studio-mcp auth

This opens a browser window for Google sign-in. After granting access, tokens are saved locally.

  1. Check auth status anytime:
npx yt-studio-mcp auth --status

Optional Configuration

Variable Description Default
YT_STUDIO_MCP_TOKEN_PATH Custom path for OAuth token storage ~/.config/yt-studio-mcp/tokens.json
YT_ALLOWED_UPLOAD_DIR Allowlist root for all local file uploads -- video, thumbnail, and captions. Absolute path to the directory holding those files. Unset means every file-path upload is refused, so despite the section heading this is not optional in practice. Example: /Users/you/podcast/video unset (all file uploads refused)
export YT_ALLOWED_UPLOAD_DIR="/Users/you/podcast/video"

MCP Client Setup

Add to your Claude Desktop configuration (claude_desktop_config.json):

{
  "mcpServers": {
    "youtube": {
      "command": "npx",
      "args": ["-y", "yt-studio-mcp"],
      "env": {
        "GOOGLE_CLIENT_ID": "your-client-id",
        "GOOGLE_CLIENT_SECRET": "your-client-secret",
        "YT_ALLOWED_UPLOAD_DIR": "/Users/you/podcast/video"
      }
    }
  }
}

Note: You must complete the OAuth auth flow (step 6 above) before the MCP server can make API calls. Tokens persist across sessions once authenticated.

Available Tools

Tool Description
youtube_upload Upload a video to YouTube with metadata. Returns the video ID and URL. Set privacy to 'private' (default) for review before publishing. The file must resolve inside YT_ALLOWED_UPLOAD_DIR.
youtube_set_thumbnail Set a custom thumbnail on a YouTube video. Image must be PNG or JPEG (by magic bytes), at least 1280x720, and under 2MB. The file must resolve inside YT_ALLOWED_UPLOAD_DIR.
youtube_upload_captions Upload SubRip (SRT) or WebVTT caption tracks to a YouTube video. Format is detected from content. Supports multiple languages in a single call. At least one English track is required. Every file must resolve inside YT_ALLOWED_UPLOAD_DIR, and a refusal on any one entry means nothing is uploaded.
youtube_list_playlists List all playlists on the authenticated YouTube channel. Returns playlist IDs, titles, descriptions, and video counts.
youtube_add_to_playlist Add a YouTube video to one or more playlists. Handles partial failures: returns per-playlist success/error status.
youtube_create_playlist Create a new playlist on the authenticated YouTube channel. Returns playlist ID and URL.
youtube_schedule_livestream Schedule a YouTube livestream with all metadata and defaults. Binds to a reusable stream (OBS stream key stays the same). Sets Sports category, optional thumbnail/playlist, and attempts monetization with mid-rolls.

Security

Local file uploads are confined to YT_ALLOWED_UPLOAD_DIR. Containment -- not caller honesty -- decides which bytes leave your machine:

  • Both the configured root and the candidate path are resolved with realpath before a separator-aware containment check, so a symlink inside the root that points out of it is refused, and a sibling directory sharing a name prefix (/allowed-evil against root /allowed) is refused too.
  • Files are opened O_RDONLY | O_NOFOLLOW with a device/inode re-check against the pre-open lstat, closing the TOCTOU window between validation and read. Every uploaded byte comes off that one validated descriptor; the path is never reopened.
  • Content is validated by bytes, not by extension: video by container magic (MP4/MOV, MKV/WebM, AVI), thumbnails by PNG/JPEG signature, captions by WebVTT or SubRip structure. A text file named .mp4 or a binary blob named .srt is refused.
  • Refusals are deliberately uniform. Missing file, outside the root, not a regular file, and symlink escape all produce one identical message that never echoes a resolved path, so the server cannot be used as a filesystem existence oracle.

Breaking change from 0.2.0: file uploads require an allowlist root

Through 0.2.0, youtube_upload, youtube_set_thumbnail, and youtube_upload_captions accepted any path and streamed those bytes to YouTube under your OAuth credentials -- and youtube_upload accepts privacy: "public". An AI agent steered by prompt injection could name ~/.ssh/id_rsa or a project .env and publish it.

File uploads are now refused unless YT_ALLOWED_UPLOAD_DIR is set, and a path is only accepted when it resolves inside that directory. If uploads started failing after upgrading, set YT_ALLOWED_UPLOAD_DIR to your media directory.

Resources

The server exposes a Publish Workflow resource (resource:///publish-workflow) that provides a step-by-step guide for publishing a complete YouTube video via MCP tools -- covering upload, thumbnail, captions, and playlist attachment.

License

MIT