ytmcp
Provides tools for controlling a YouTube channel end-to-end, including uploading videos, editing metadata, setting visibility, managing playlists, moderating comments, updating channel branding, reading analytics, and searching videos.
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., "@ytmcp upload my new video from ~/Videos/demo.mp4 with title 'Demo'"
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.
ytmcp
Unofficial YouTube API + MCP server — let AI agents control a YouTube channel end-to-end.
ytmcp is a Python library, REST API, CLI, and Model Context Protocol server that wraps an unofficial YouTube client. It lets AI agents (Claude Desktop, Cursor, custom agents…) upload videos, edit metadata, manage playlists, moderate comments, and read analytics — all through MCP tools.
⚠️ Disclaimer
This project is provided for educational and research purposes only.
It uses reverse-engineered, undocumented YouTube endpoints that may change or break at any time.
Automating YouTube may violate YouTube's Terms of Service.
Using this software can result in account suspension or termination.
The authors accept no liability for any consequences arising from its use.
Use at your own risk, ideally with a test account. You are solely responsible for complying with all applicable terms and laws.
Related MCP server: youtube-live-mcp
✨ Features
Domain | Capabilities |
Video | upload (resumable), update metadata, set visibility, set thumbnail, delete, get info |
Playlist | create, list, add/remove videos, delete |
Comments | list, reply, moderate (approve/hold/reject) |
Channel | get info, subscriber count, update branding/links |
Analytics | views, watch-time, subscriber growth, top videos |
Search | search videos, list channel uploads |
Three interfaces share one core:
🐍 Python library —
from ytmcp.core import YouTubeClient🤖 MCP server —
ytmcp serve(stdio / HTTP)🌐 REST API —
ytmcp api(FastAPI, auto docs at/docs)
🔐 Authentication (hybrid)
ytmcp supports two auth methods and picks automatically (auth_mode = auto):
Option A — Browser cookies (fastest)
Export cookies for
youtube.comwith a browser extension (e.g. Get cookies.txt) oryt-dlp --cookies-from-browser chrome --cookies cookies.txt.Point ytmcp at the file:
export YTMCP_AUTH_MODE=cookie
export YTMCP_COOKIE_FILE=/path/to/cookies.txt
uv run ytmcp auth verify-cookies /path/to/cookies.txtSupports Netscape cookies.txt and JSON exports (including Playwright storage_state).
Option B — OAuth 2.0 (device flow)
Create an OAuth client (type TVs and Limited Input devices) in Google Cloud Console.
Configure and log in:
export YTMCP_AUTH_MODE=oauth
export YTMCP_OAUTH_CLIENT_ID=...
export YTMCP_OAUTH_CLIENT_SECRET=...
uv run ytmcp auth loginTokens are cached in ~/.ytmcp/oauth_token.json and refreshed automatically.
Check status any time:
uv run ytmcp auth status🚀 Quick start
# 1. Install
git clone https://github.com/Lightforce325/ytmcp.git
cd ytmcp
uv venv && source .venv/bin/activate
uv pip install -e ".[dev]"
# 2. Configure auth (see above)
cp .env.example .env # then edit
# 3. Run the MCP server
uv run ytmcp serve
# or the REST API
uv run ytmcp api # http://127.0.0.1:8765/docs🤖 Connect to Claude Desktop (MCP)
Add this to claude_desktop_config.json:
{
"mcpServers": {
"ytmcp": {
"command": "uv",
"args": [
"--directory", "/ABSOLUTE/PATH/TO/ytmcp",
"run", "ytmcp", "serve"
],
"env": {
"YTMCP_AUTH_MODE": "cookie",
"YTMCP_COOKIE_FILE": "/ABSOLUTE/PATH/TO/cookies.txt"
}
}
}
}Restart Claude Desktop — the agent will now see 20 tools for controlling your channel.
See examples/claude_desktop_config.json and docs/TOOLS.md.
🧰 MCP tools
Tool | Auth | Description |
| ✅ | Upload a video file with metadata |
| ✅ | Edit title/description/tags/category |
| ✅ | public / unlisted / private / scheduled |
| ✅ | Permanently delete a video |
| — | Fetch video details |
| — | Search YouTube |
| — | List a channel's uploads |
| ✅ | Create a playlist |
| — | List channel playlists |
| ✅ | Add a video to a playlist |
| ✅ | Remove a video from a playlist |
| ✅ | Delete a playlist |
| — | List video comments |
| ✅ | Reply to a comment |
| ✅ | Approve / hold / reject a comment |
| — | Channel metadata |
| — | Subscriber count |
| ✅ | Banner / avatar / links |
| ✅ | Views, watch-time, growth |
| — | Most-viewed videos |
🧩 Example agent workflow
"Upload
intro.mp4as a private video titled Hello World, add it to my Demos playlist, then reply to the latest comment."
The agent chains: upload_video → list_playlists → add_video_to_playlist → list_comments → reply_to_comment. See examples/agent_batch_upload.py.
🏗️ Architecture
AI Agent ──MCP──► mcp/server.py ──► core/* ──► YouTube endpoints
api/app.py ──►
cli.py ──►See docs/ARCHITECTURE.md for the full breakdown.
🧪 Development
uv pip install -e ".[dev]" # install dev dependencies
uv run ruff check . # lint
uv run ruff format . # format
uv run mypy src # type-checkTesting
The suite lives in tests/ and runs on pytest
with pytest-asyncio (asyncio_mode = "auto")
and respx for HTTP mocking — no network
access or credentials are needed for the default run.
# Run the whole suite (unit tests + integration tests, which skip by default)
uv run pytest
# Run only the unit tests
uv run pytest tests/unit
# Run a single file / test
uv run pytest tests/unit/test_upload.py -q
uv run pytest tests/unit/test_config.py::test_settings_defaults -qCoverage
Coverage is configured with pytest-cov
and coverage.py. Configuration lives in
pyproject.toml under [tool.coverage.run] (source = src/ytmcp, branch
coverage enabled) and [tool.coverage.report].
# Terminal report highlighting missing lines
uv run pytest --cov=src/ytmcp --cov-report=term-missing
# HTML report (written to htmlcov/, git-ignored)
uv run pytest --cov=src/ytmcp --cov-report=html
open htmlcov/index.html
# Fail the run if total coverage drops below a threshold
uv run pytest --cov=src/ytmcp --cov-report=term-missing --cov-fail-under=70Integration tests (opt-in)
End-to-end multi-service flows live in tests/integration/. They are marked
integration and skipped by default; opt in with the environment variable:
# Run everything, including integration tests
YTMCP_RUN_INTEGRATION=1 uv run pytest -m integration
# Run only the integration marker
YTMCP_RUN_INTEGRATION=1 uv run pytest tests/integration -m integrationQuality gates
uv run pytest # tests
uv run pytest --cov=src/ytmcp --cov-report=term-missing # tests + coverage
uv run ruff check . # lint
uv run mypy src # type-check📄 License
MIT — provided as-is, without warranty. See the disclaimer above.
Available Tools
20 toolsadd_video_to_playlistC
Add a video to a playlist.
Args: playlist_id: Target playlist id (starts with 'PL'). video_id: Video id to add.
Inputs: video_id (required), playlist_id (required). Returns: result
create_playlistB
Create a new playlist on the channel.
Args: title: Playlist title. description: Playlist description. visibility: One of 'public', 'unlisted', 'private'.
Inputs: title (required), visibility, description. Returns: result
delete_playlistC
Delete a playlist.
Args: playlist_id: Playlist id to delete.
Inputs: playlist_id (required). Returns: result
delete_videoB
Permanently delete a video from the channel.
Args: video_id: The YouTube video id to delete.
Inputs: video_id (required). Returns: result
get_analyticsB
Get channel analytics (views, watch-time, subscribers gained/lost).
Args: channel_id: Channel id. period_days: Reporting window in days (default 28).
Inputs: channel_id (required), period_days. Returns: result
get_channel_infoB
Get information about a channel (title, description, banner).
Args: channel_id: Channel id; if omitted, uses the authenticated channel.
Inputs: channel_id. Returns: result
get_subscriber_countB
Get the subscriber count of a channel.
Args: channel_id: Channel id; if omitted, uses the authenticated channel.
Inputs: channel_id. Returns: result
get_top_videosC
Get a channel's most-viewed videos.
Args: channel_id: Channel id. limit: Maximum number of videos to return.
Inputs: channel_id (required), limit. Returns: result
get_video_infoB
Get detailed information about a video (title, views, description).
Args: video_id: The YouTube video id.
Inputs: video_id (required). Returns: result
list_channel_videosB
List a channel's uploaded videos (newest first).
Args: channel_id: The channel id (starts with 'UC'). limit: Maximum number of videos to return.
Inputs: channel_id (required), limit. Returns: result
list_commentsB
List top-level comments for a video.
Args: video_id: The YouTube video id. limit: Maximum number of comments to return.
Inputs: video_id (required), limit. Returns: result
list_playlistsC
List all playlists belonging to a channel.
Args: channel_id: The channel id (starts with 'UC').
Inputs: channel_id (required). Returns: result
moderate_commentB
Moderate a comment (approve, hold, or reject).
Args: comment_id: Target comment id. action: One of 'published', 'heldForReview', 'rejected'.
Inputs: comment_id (required), action. Returns: result
remove_video_from_playlistC
Remove a video from a playlist.
Args: playlist_id: Target playlist id. video_id: Video id to remove.
Inputs: video_id (required), playlist_id (required). Returns: result
reply_to_commentB
Reply to a comment on a video.
Args: video_id: The video id the comment belongs to. comment_id: The comment to reply to. text: Reply text.
Inputs: text (required), video_id (required), comment_id (required). Returns: result
search_videosC
Search YouTube for videos.
Args: query: Search keywords. limit: Maximum number of results (default 20).
Inputs: query (required), limit. Returns: result
set_video_visibilityB
Change a video's visibility.
Args: video_id: The YouTube video id. visibility: One of 'public', 'unlisted', 'private', 'scheduled'. publish_at: ISO-8601 datetime; required for 'scheduled'.
Inputs: video_id (required), visibility (required), publish_at. Returns: result
update_channel_brandingB
Update channel branding: banner, avatar, and profile links.
Args: banner_path: Local path to a new banner image. avatar_path: Local path to a new avatar image. links: List of {'title': ..., 'url': ...} profile links.
Inputs: links, avatar_path, banner_path. Returns: result
update_video_metadataB
Update the metadata of an existing video.
Args: video_id: The YouTube video id to edit. title: New title (optional). description: New description (optional). tags: New tag list (optional). category_id: New category id (optional). default_language: New default language code, e.g. 'en' (optional).
Inputs: video_id (required), tags, title, category_id, +2 more. Returns: result
upload_videoA
Upload a video file to the authenticated YouTube channel.
Args: file_path: Absolute path to the video file on the local machine. title: Video title (max 100 chars). description: Video description text. tags: Optional list of tags/keywords. visibility: One of 'public', 'unlisted', 'private', 'scheduled'. category_id: YouTube category id (default '22' = People & Blogs). publish_at: ISO-8601 datetime; required when visibility='scheduled'. made_for_kids: COPPA compliance flag. thumbnail_path: Optional path to a custom thumbnail image.
Inputs: title (required), file_path (required), tags, publish_at, +5 more. Returns: result
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 20 tools
Most tools have clearly distinct purposes, but a few channel-video retrieval and channel-info tools have closely related scopes (e.g., get_top_videos vs list_channel_videos, get_channel_info vs get_subscriber_count), which could cause minor misselection.
All tool names use a consistent snake_case verb_noun pattern (get_, list_, create_, update_, delete_, etc.) with no mixed conventions, making them predictable and readable.
20 tools is on the higher side but reasonable for the broad YouTube channel management domain, covering videos, playlists, comments, analytics, and channel branding without obvious redundancy.
Core CRUD exists for videos and playlists, but notable gaps remain: no way to list videos within a playlist, no update_playlist, no update_channel_description/title, and no delete comment. These missing operations could hinder full playlist and channel management.
Maintenance
Related MCP Connectors
YouTube transcripts, search, channel browsing, and playlists for AI agents via MCP.
Build, run, schedule, and publish AI video pipelines to YouTube and TikTok from any MCP client.
YouTube for AI agents: transcripts, comments, video stats, channel monitor, Shorts captions.
Give AI agents a creator's video pipeline: Shorts, thumbnails and YouTube publishing.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceGives AI coding agents full control over a YouTube channel with 22 tools for channel management, videos, playlists, comments, search, analytics, thumbnails, and captions.34 npm3MIT
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to control YouTube Live Streaming, including creating broadcasts, managing chat, and monitoring stream health via MCP tools.34 npmMIT
- FlicenseNot gradedqualityDmaintenanceEnables AI models to interact with YouTube content through 18 MCP tools for videos, transcripts, channels, and playlists.29 npm-
- AlicenseAqualityCmaintenanceEnables Claude to control a YouTube channel through MCP, including uploading and editing videos, scheduling releases, and reading channel and video analytics via official APIs.8MIT