YouTube MCP Server
Provides tools for interacting with YouTube's API, enabling AI agents to manage channels, videos, playlists, captions, subscriptions, and search YouTube content.
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 get the latest video from the YouTube channel 'GoogleDevelopers'"
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 Server
A Python Model Context Protocol (MCP) server that exposes YouTube Data API tools. Use it from MCP Inspector, Cursor, or any MCP client.
Tool reference: Composio YouTube Toolkit
Table of contents
Related MCP server: mcp-apps
Project structure
youtube mcp/
├── src/youtubemcp/
│ ├── config.py # OAuth2, .env, YouTube API client
│ ├── mcp.py # FastMCP instance
│ ├── main.py # Entry point
│ └── tools/ # Tool modules (channel, captions, playlists, etc.)
├── .env # Your credentials (create from .env.example)
├── .env.example # Template for .env
├── pyproject.toml
├── requirements.txt
├── run.py # Run server: python run.py
└── README.mdPrerequisites
Python 3.10+
Google account (for YouTube / OAuth2)
uv (optional, for
uv run) or pip
Installation
Option A: Using pip
cd "d:\clg files\PROJECTS\youtube mcp"
python -m venv .venv
.venv\Scripts\activate
pip install -r requirements.txtOption B: Using uv
cd "d:\clg files\PROJECTS\youtube mcp"
uv syncGetting OAuth2 credentials
Follow these steps to get Client ID and Client Secret from Google Cloud.
Step 1: Open Google Cloud Console
Go to Google Cloud Console.
Sign in with the Google account you want to use for YouTube.
Step 2: Create or select a project
At the top, click the project dropdown (next to “Google Cloud”).
Click New Project.
Enter a name (e.g. YouTube MCP) and click Create.
Select this project from the dropdown so it’s the active project.
Step 3: Enable YouTube Data API v3
In the left menu: APIs & Services → Library
Or go to: APIs Library.Search for YouTube Data API v3.
Click it, then click Enable.
Step 4: Configure OAuth consent screen
In the left menu: APIs & Services → OAuth consent screen.
Choose External (unless you use Google Workspace and want Internal only).
Click Create.
App information
App name: e.g.
YouTube MCPUser support email: your email
Developer contact: your email
Click Save and Continue.
Scopes
Click Add or Remove Scopes.
Filter or search for YouTube Data API v3.
Add at least:
View your YouTube account (
.../auth/youtube.readonly)See, edit, and permanently delete your YouTube videos, ratings, comments and captions (
.../auth/youtube.force-ssl)Manage your YouTube videos (
.../auth/youtube.upload) — needed for uploads and thumbnails
Click Update → Save and Continue.
Test users (required while app is in Testing)
Click Add Users.
Add the Gmail address you will use to sign in (e.g.
yourname@gmail.com).Click Save and Continue.
Click Back to Dashboard.
Step 5: Create OAuth 2.0 Client ID
In the left menu: APIs & Services → Credentials.
Click + Create Credentials → OAuth client ID.
Application type: Desktop app.
Name: e.g.
YouTube MCP desktop.Click Create.
In the popup, copy:
Client ID (looks like
123456789-xxxx.apps.googleusercontent.com)Client secret (looks like
GOCSPX-xxxxxxxxxxxxxxxx)
Keep these for the next section.
Configuration (.env)
Copy the example env file:
copy .env.example .env(On macOS/Linux:
cp .env.example .env)Open
.envand set your credentials:client_id=YOUR_CLIENT_ID.apps.googleusercontent.com client_secret=YOUR_CLIENT_SECRETOptional variables:
Variable
Description
oauth_redirect_uriRedirect URI (default:
http://localhost)scopesComma-separated OAuth scopes (default includes readonly; add
https://www.googleapis.com/auth/youtube.force-sslandhttps://www.googleapis.com/auth/youtube.uploadfor full features)Example for full access (read, write, upload, thumbnails):
scopes=https://www.googleapis.com/auth/youtube.readonly,https://www.googleapis.com/auth/youtube.force-ssl,https://www.googleapis.com/auth/youtube.uploadFirst run: When you start the server, a browser window will open. Sign in with the same Google account you added as a test user and approve the requested permissions. The app will save tokens to
token.json(created automatically; do not commit it).
Running the server
From the project root:
python run.pyOr, if you use uv:
uv run run.pyThe server runs over STDIO by default (for MCP Inspector and Cursor). It will wait for input; close with Ctrl+C when done.
MCP Inspector
Connect via STDIO (recommended)
Start MCP Inspector:
npx -y @modelcontextprotocol/inspectorIn the Inspector:
Transport: STDIO
Command:
uv(orpython)Arguments:
run run.py(orrun.pyif Command ispython)Ensure the working directory is the project root (where
run.pyand.envare).
Click Connect. The server starts; on first run, a browser may open for Google sign-in.
Call any tool (e.g. get_channel_id_by_handle with
@YouTube) to verify.
Cursor MCP config
Add the server to Cursor so it can call YouTube tools.
Open Cursor Settings → MCP (or edit your MCP config file).
Add a server entry, for example:
{ "mcpServers": { "youtube": { "command": "C:\\path\\to\\youtube mcp\\.venv\\Scripts\\python.exe", "args": ["C:\\path\\to\\youtube mcp\\run.py"], "env": { "YOUTUBE_CLIENT_ID": "YOUR_CLIENT_ID", "YOUTUBE_CLIENT_SECRET": "YOUR_CLIENT_SECRET" } } } }Replace
C:\\path\\to\\youtube mcpwith your actual project path. You can omitenvif.envis in the project root and Cursor runs from there.Restart Cursor or reload MCP; the YouTube tools should appear.
Tools overview
All tools return an object with data (object), error (string, optional), and successful (boolean).
Tool | Description |
get_channel_activities | Recent activities for a channel (uploads, playlists, likes). |
get_channel_id_by_handle | Get channel ID from handle (e.g. |
get_channel_statistics | Channel stats (subscribers, views, video count). |
list_channel_videos | List videos from a channel. |
list_captions | List caption tracks for a video (your videos). |
download_caption_track | Download caption content by track ID (your videos). |
list_user_playlists | Playlists owned by the authenticated user. |
list_user_subscriptions | Channels the authenticated user is subscribed to. |
subscribe_to_channel | Subscribe the authenticated user to a channel. |
search_youtube | Search videos, channels, or playlists. |
update_thumbnail | Set custom thumbnail from image URL (your videos). |
update_video | Update video metadata (title, description, tags, privacy). |
upload_video | Upload a video from a local file path. |
video_details | Get video details (snippet, statistics, etc.) by video ID. |
Troubleshooting
"Access blocked" or "Error 403: access_denied"
Your app is in Testing mode. Add your Google account under OAuth consent screen → Test users and try again.
"Request had insufficient authentication scopes"
Add the needed scope to OAuth consent screen (e.g.
youtube.force-ssl,youtube.upload).Delete
token.json, then run the server again and sign in to get a new token with the new scopes.
"The authenticated user doesn't have permissions to upload and set custom video thumbnails"
Add scope Manage your YouTube videos (
youtube.upload) in the OAuth consent screen.Delete
token.jsonand sign in again.Ensure your YouTube channel is verified (e.g. phone verification in YouTube Studio → Settings → Channel).
"YouTube Data API v3 has not been used in project ... or it is disabled"
In APIs Library, enable YouTube Data API v3 for the same project that has your OAuth client.
Invalid scope (e.g. scopes=https://... in error)
In
.env, thescopesvalue must be only the comma-separated URLs, e.g.scopes=https://www.googleapis.com/auth/youtube.readonly,https://www.googleapis.com/auth/youtube.force-ssl
Do not repeat the wordscopes=inside the value.
Token refresh
Access tokens expire in about an hour. The server refreshes them automatically using
token.json. If you change scopes or get auth errors, deletetoken.jsonand sign in again.
.env and token.json location
Both must be in the project root (same folder as
run.py). The server loads them from there.
License
MIT
Available Tools
14 toolsdownload_caption_trackA
Downloads a specific YouTube caption track, which must be owned by the authenticated user, and returns its content as text.
Args: id: Unique YouTube-assigned ID of the caption track to download (from list_captions response). tfmt: Desired format: 'srt' (SubRip), 'sbv' (SubViewer), 'vtt' (WebVTT). Default: 'srt'.
Returns: Object with 'data' (contains 'content' with caption text), 'error' (if any), and 'successful' boolean.
Inputs: id (required), tfmt. Returns: object
get_channel_activitiesA
Gets recent activities from a YouTube channel including video uploads, playlist additions, likes, and other channel events.
Args: channel_id: The YouTube channel ID to retrieve activities for. Channel IDs typically start with 'UC'. max_results: Maximum number of activities to return (0-50). page_token: Pagination token from a previous response to get the next page. part: Comma-separated list of activity resource properties to include (e.g., 'snippet', 'contentDetails', 'id'). published_after: Return activities published after this date-time (RFC 3339 format: YYYY-MM-DDTHH:MM:SSZ). published_before: Return activities published before this date-time (RFC 3339 format: YYYY-MM-DDTHH:MM:SSZ).
Returns: Object with 'data', 'error' (if any), and 'successful' boolean.
Inputs: channel_id (required), part, page_token, max_results, +2 more. Returns: object
get_channel_id_by_handleA
Retrieves the YouTube channel ID for a specific YouTube channel handle.
Args: channel_handle: The YouTube channel handle (e.g., @Google) for which to retrieve the corresponding channel ID. May include or omit the '@' symbol.
Returns: Object with 'data' (channel info including id), 'error' (if any), and 'successful' boolean.
Inputs: channel_handle (required). Returns: object
get_channel_statisticsA
Gets detailed statistics for YouTube channels including subscriber counts, view counts, and video counts.
Args: id: Comma-separated list of YouTube channel IDs. Channel IDs typically start with 'UC'. part: Comma-separated list of channel resource properties to include. Use 'statistics' for subscriber count. Default: 'statistics,snippet'.
Returns: Object with 'data' (channel stats), 'error' (if any), and 'successful' boolean.
Inputs: id (required), part. Returns: object
list_captionsA
Retrieves a list of caption tracks for a YouTube video. Returns an empty list if no captions exist, or fails if the video ID is invalid or not found.
Args: video_id: The YouTube video ID for which to return caption tracks. part: Comma-separated list of caption resource parts to include. Valid parts are 'id' and 'snippet'. Default: 'id,snippet'.
Returns: Object with 'data' (caption list), 'error' (if any), and 'successful' boolean.
Inputs: video_id (required), part. Returns: object
list_channel_videosA
Lists videos from a specified YouTube channel, ensuring results are of type 'video'.
Args: channel_id: The unique ID of the YouTube channel for which videos are to be retrieved. max_results: Maximum number of videos to return per page (default 5, max 50). page_token: Token for pagination; use nextPageToken from a previous response. part: Search resource properties to include; must be 'snippet' for this action.
Returns: Object with 'data' (video list), 'error' (if any), and 'successful' boolean.
Inputs: channel_id (required), part, page_token, max_results. Returns: object
list_user_playlistsA
Retrieves playlists owned by the authenticated user, implicitly using mine=true.
Args: max_results: Maximum number of playlists to return (0-50). Default: 5. page_token: Token for pagination to retrieve a specific page of results. part: Comma-separated list of playlist resource properties to include. Common values are 'snippet', 'id', and 'contentDetails'. Default: 'snippet,contentDetails'.
Returns: Object with 'data' (playlist list), 'error' (if any), and 'successful' boolean.
Inputs: part, page_token, max_results. Returns: object
list_user_subscriptionsA
Retrieves the authenticated user's YouTube channel subscriptions, allowing specification of response parts and pagination.
Args: max_results: Maximum number of subscription items to return per page (0-50). Default: 5. page_token: Token for a specific page of results, obtained from a previous response. part: Comma-separated subscription resource parts to include. Valid parts are 'id', 'snippet', 'contentDetails', and 'subscriberSnippet'. Default: 'snippet,contentDetails'.
Returns: Object with 'data' (subscription list), 'error' (if any), and 'successful' boolean.
Inputs: part, page_token, max_results. Returns: object
search_youtubeA
Searches YouTube for videos, channels, or playlists using a query term, returning the raw API response.
Args: q: Search query term. Supports: basic text ('machine learning'), exact phrases ('"exact phrase"'), exclusions ('python -snake'), multiple terms ('AI OR ML'), channel search ('@channelhandle' or channel name). max_results: Maximum number of items to return per page (0-50). Default: 5. page_token: Pagination token from a previous response's nextPageToken or prevPageToken. part: Comma-separated list of search resource properties (e.g. 'id', 'snippet') to include. type: Restrict search to 'video', 'channel', or 'playlist'; comma-separate for multiple.
Returns: Object with 'data' (raw API response), 'error' (if any), and 'successful' boolean.
Inputs: q (required), part, type, page_token, +1 more. Returns: object
subscribe_to_channelA
Subscribes the authenticated user to a specified YouTube channel, identified by its unique channelId which must be valid and existing.
Args: channel_id: Unique identifier (ID) of the YouTube channel to subscribe to (typically starts with 'UC').
Returns: Object with 'data' (subscription resource), 'error' (if any), and 'successful' boolean.
Inputs: channel_id (required). Returns: object
update_thumbnailA
Sets the custom thumbnail for a YouTube video using an image from thumbnailUrl. The authenticated user must have permission to edit the video.
Args: thumbnail_url: Publicly accessible URL of the new thumbnail image. Must be JPG, GIF, or PNG; under 2MB. Recommended: 16:9, 1280x720 (min 640px width). video_id: Identifier of the YouTube video for which to update the thumbnail.
Returns: Object with 'data' (thumbnail resource), 'error' (if any), and 'successful' boolean.
Inputs: video_id (required), thumbnail_url (required). Returns: object
update_videoA
Updates metadata for a YouTube video identified by videoId, which must exist. An empty list for tags removes all existing tags. Omitted fields are left unchanged.
Args: video_id: The video's unique YouTube ID (typically found in its URL). title: New video title. No change if omitted. description: New video description. No change if omitted. tags: New tags, replacing all existing. An empty list removes all. No change if omitted. category_id: New YouTube category ID. No change if omitted. privacy_status: New privacy status ('public', 'private', or 'unlisted'). No change if omitted.
Returns: Object with 'data' (updated video resource), 'error' (if any), and 'successful' boolean.
Inputs: video_id (required), tags, title, category_id, +2 more. Returns: object
upload_videoA
Uploads a video from a local file path to a YouTube channel. The video file must be in a YouTube-supported format (e.g. MP4, MOV, AVI).
Args: video_file_path: Local file path (absolute or relative) of the video to upload. title: The title for the video. description: Detailed description of the video content. tags: List of keyword tags (strings) for the video. category_id: YouTube category ID (e.g. '22' for People & Blogs). privacy_status: 'public', 'private', or 'unlisted'.
Returns: Object with 'data' (uploaded video resource), 'error' (if any), and 'successful' boolean.
Inputs: tags (required), title (required), category_id (required), description (required), +2 more. Returns: object
video_detailsA
Retrieves specified information parts (e.g., snippet, contentDetails, statistics) for a YouTube video, identified by its id.
Args: id: The YouTube video ID (typically 11 characters) for which to retrieve details. part: Comma-separated list of video resource parts to include. Valid parts: 'snippet', 'contentDetails', 'statistics', 'status', 'player', etc. Default: 'snippet,contentDetails,statistics'.
Returns: Object with 'data' (video resource), 'error' (if any), and 'successful' boolean.
Inputs: id (required), part. Returns: object
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 14 tools
All tools target distinct resources and actions. Channel stats, activities, videos, playlists, subscriptions, captions, search, upload, and update are clearly separated with no overlapping purposes.
Most tools follow a consistent verb_noun snake_case pattern (get_channel_statistics, list_channel_videos, update_video). One outlier is 'video_details' which is a noun phrase rather than verb-first, but it's readable and doesn't cause confusion.
14 tools is well within the ideal range and matches the broad YouTube API scope. Each tool covers a significant operation, and no redundant tools are present.
The set covers read operations comprehensively (search, details, lists) and includes upload/update for videos. However, missing delete operations (videos, playlists, subscriptions, captions) and playlist creation/modification are notable gaps that limit full lifecycle management.
Maintenance
Related MCP Connectors
YouTube MCP — wraps the YouTube Data API v3 (BYO API key)
YouTube transcripts, search, channel browsing, and playlists for AI agents via MCP.
Hosted MCP for YouTube Studio: uploads, metadata, playlists, comments, analytics, captions.
Real-time YouTube transcripts, comments, channels & video search MCP. Local npx or hosted OAuth.
Related MCP Servers
- AlicenseAqualityDmaintenanceEnables YouTube content browsing, video searching, and metadata retrieval via the YouTube Data API v3. It also facilitates fetching video transcripts for summarization and analysis within MCP-compatible AI clients.726 npm1MIT
- AlicenseNot gradedqualityDmaintenanceEnables interacting with YouTube Data API v3 through MCP tools (get-video, get-channel, get-latest-video) and bundled UI apps for video and channel profiles.7 npm4MIT
- AlicenseAqualityDmaintenanceEnables YouTube search, video details, channels, playlists, and comments scraping via MCP, no API key required.1023 npm1MIT
- AlicenseNot gradedqualityCmaintenanceProvides read-only MCP tools to search YouTube, retrieve video metadata, transcripts, comments, channel information, and popular videos.3MIT