Skip to main content
Glama
tuitamogamer-gpt

youtube-mcp-server

Server Configuration

Describes the environment variables required to run the server.

NameRequiredDescriptionDefault
YT_CLIENT_IDNoOAuth client ID (ends with apps.googleusercontent.com). Required if not using token.json.
YT_TOKEN_PATHNoAbsolute path to token.json file. If not set, looks for token.json in the project root.
YT_CLIENT_SECRETNoOAuth client secret. Required if not using token.json.
YT_REFRESH_TOKENNoOAuth refresh token. Required if not using token.json.

Capabilities

Features and capabilities supported by this server

CapabilityDetails
tools
{
  "listChanged": true
}

Tools

Functions exposed to the LLM to take actions

NameDescription
youtube_get_my_channelA

Retrieve full details for the authenticated user's own YouTube channel.

Args:

  • response_format (optional): "markdown" (default) for a concise human-readable summary or "json" for the raw API payload.

Returns (JSON shape):

{
  "id": "UCxxxxxxxx",
  "snippet": { "title", "description", "customUrl", "publishedAt", "country", "defaultLanguage", "thumbnails" },
  "statistics": { "subscriberCount", "videoCount", "viewCount", "commentCount" },
  "status": { "privacyStatus", "madeForKids", ... },
  "brandingSettings": { "channel": { "title", "description", "keywords", "country", "defaultLanguage", "unsubscribedTrailer" } },
  "contentDetails": { "relatedPlaylists": { "uploads", "watchHistory", "watchLater" } },
  "topicDetails": { "topicCategories": [...] }
}

Examples:

  • "Show me my channel info" → call with no arguments.

  • "Give me the full JSON for my channel" → pass response_format: "json".

Errors:

  • 401 / 403: credentials missing or expired — re-run npm run auth.

  • 404: no YouTube channel associated with this Google account.

youtube_get_channelA

Retrieve public details for any YouTube channel by one of three identifiers: channel ID, @handle, or legacy username. Exactly one of channelId, handle, or username must be supplied.

Args:

  • channelId (optional): The channel's unique ID, e.g. "UCxxxxxxxx".

  • handle (optional): The channel's @handle. The leading @ is stripped automatically, e.g. "@MrBeast" or "MrBeast".

  • username (optional): A legacy YouTube username (deprecated by YouTube but still supported), e.g. "PewDiePie".

  • response_format (optional): "markdown" (default) or "json".

Returns (JSON shape):

{
  "id": "UCxxxxxxxx",
  "snippet": { "title", "description", "customUrl", "publishedAt", "country", "thumbnails" },
  "statistics": { "subscriberCount", "videoCount", "viewCount", "commentCount" },
  "brandingSettings": { "channel": { "title", "description", "keywords" } },
  "contentDetails": { "relatedPlaylists": { "uploads" } }
}

Examples:

  • "Look up channel UCxxxxxxxx" → pass channelId: "UCxxxxxxxx".

  • "Get info on @MrBeast" → pass handle: "@MrBeast".

  • "Find channel for username PewDiePie" → pass username: "PewDiePie".

Errors:

  • 400: none of the three identifiers was provided.

  • 404: channel not found or not publicly accessible.

youtube_update_channel_brandingA

Update one or more branding fields on the authenticated user's YouTube channel. At least one field must be supplied. The current branding is fetched first and merged, so omitted fields are preserved.

Args (all optional, but at least one required):

  • description (optional): Channel description text (max ~1000 chars visible in branding settings).

  • keywords (optional): Space-separated or quoted keywords for the channel, e.g. "coding tutorial javascript".

  • country (optional): ISO 3166-1 alpha-2 country code, e.g. "US", "GB".

  • defaultLanguage (optional): BCP-47 language code, e.g. "en", "fr".

  • unsubscribedTrailer (optional): Video ID to use as the channel trailer for unsubscribed visitors.

Returns (JSON shape):

{
  "id": "UCxxxxxxxx",
  "brandingSettings": {
    "channel": { "description", "keywords", "country", "defaultLanguage", "unsubscribedTrailer" }
  }
}

Examples:

  • "Set my channel country to GB and keywords to 'gaming commentary'" → pass country: "GB", keywords: "gaming commentary".

  • "Change my trailer video to dQw4w9WgXcQ" → pass unsubscribedTrailer: "dQw4w9WgXcQ".

Errors:

  • 400: invalid field value (e.g. unsupported country code or language tag).

  • 401 / 403: insufficient scope or expired credentials — re-run npm run auth.

youtube_list_channel_sectionsA

List all sections on the authenticated user's YouTube channel home page (e.g. Featured Playlists, Single Playlist, Popular Uploads, etc.).

Args:

  • response_format (optional): "markdown" (default) for a readable table or "json" for the full API payload array.

Returns (JSON shape):

[
  {
    "id": "CS_ID",
    "snippet": {
      "type": "singlePlaylist",
      "title": "Section title",
      "position": 0,
      "channelId": "UCxxxxxxxx"
    },
    "contentDetails": {
      "playlists": ["PLxxxxxxxx"],
      "channels": []
    }
  }
]

Examples:

  • "What sections are on my channel page?" → call with no arguments.

  • "Give me the raw JSON of my channel sections" → pass response_format: "json".

Errors:

  • 401 / 403: credentials expired or missing scope — re-run npm run auth.

  • 404: authenticated account has no YouTube channel.

youtube_list_my_videosA

List videos uploaded to the authenticated channel.

Fetches the channel's uploads playlist ID via channels.list(mine=true), then pages through playlistItems.list to return video metadata.

Args

  • maxResults (integer 1–50, default 25): number of items per page

  • pageToken (string, optional): cursor token returned in a previous response

  • response_format: "markdown" (default) or "json"

Returns JSON shape:

{
  "items": [
    {
      "videoId": "abc123",
      "title": "My Video",
      "description": "...",
      "publishedAt": "2024-01-01T00:00:00Z",
      "thumbnailUrl": "https://..."
    }
  ],
  "nextPageToken": "CAUQAA",
  "totalResults": 42
}

Examples

  • List first 10 videos: { "maxResults": 10 }

  • Get next page: { "maxResults": 10, "pageToken": "CAUQAA" }

Errors

  • 401/403: credentials expired or missing upload scope — re-run npm run auth

  • 404: channel has no uploads playlist (newly created channel?)

youtube_get_videoA

Fetch full metadata for a single video by ID.

Calls videos.list with parts: snippet, statistics, status, contentDetails, topicDetails, player, and liveStreamingDetails.

Args

  • videoId (string, required): the YouTube video ID (e.g. "dQw4w9WgXcQ")

  • response_format: "markdown" (default) or "json"

Returns JSON shape:

{
  "id": "dQw4w9WgXcQ",
  "title": "Never Gonna Give You Up",
  "description": "...",
  "publishedAt": "2009-10-25T06:57:33Z",
  "channelTitle": "Rick Astley",
  "categoryId": "10",
  "tags": ["rick astley", "pop"],
  "duration": "PT3M32S",
  "viewCount": "1400000000",
  "likeCount": "15000000",
  "commentCount": "2000000",
  "privacyStatus": "public",
  "embeddable": true,
  "madeForKids": false,
  "thumbnails": { ... },
  "statistics": { ... },
  "contentDetails": { ... }
}

Examples

  • Get video: { "videoId": "dQw4w9WgXcQ" }

  • JSON output: { "videoId": "dQw4w9WgXcQ", "response_format": "json" }

Errors

  • 404: video does not exist or is private/deleted

  • 403: insufficient permissions to view this video

youtube_update_videoA

Update the metadata of an existing video.

Fetches the current video (snippet + status) first, merges your provided fields, then calls videos.update. This ensures snippet.title and snippet.categoryId (both required by the API) are always present even if you only change one field.

Args

  • videoId (string, required): video to update

  • title (string, optional): new title

  • description (string, optional): new description

  • tags (string[], optional): full replacement tag list

  • categoryId (string, optional): numeric category ID (use youtube_list_video_categories)

  • privacyStatus ("public"|"unlisted"|"private", optional)

  • madeForKids (boolean, optional): sets status.selfDeclaredMadeForKids

  • embeddable (boolean, optional)

  • publicStatsViewable (boolean, optional)

  • defaultLanguage (string, optional): BCP-47 language code

Returns Short confirmation markdown + full updated video resource as structuredContent.

Examples

  • Update title: { "videoId": "abc123", "title": "New Title" }

  • Make private: { "videoId": "abc123", "privacyStatus": "private" }

Errors

  • 400: required fields invalid

  • 403: not your video or scope missing

  • 404: video not found

youtube_upload_videoA

Upload a local video file to YouTube.

Calls videos.insert with a resumable media upload. The file is streamed from disk via fs.createReadStream so large files are handled without loading them fully into memory.

Note: This operation costs approximately 1600 quota units.

Args

  • filePath (string, required): absolute path to the local video file

  • title (string, required): video title (shown on YouTube)

  • description (string, optional): video description

  • tags (string[], optional): tags / keywords

  • categoryId (string, optional): numeric category ID, default "22" (People & Blogs)

  • privacyStatus ("public"|"unlisted"|"private", optional, default "private")

  • madeForKids (boolean, optional, default false)

Returns Short confirmation markdown + the new video resource as structuredContent (includes the new video ID at structured.video.id).

Examples

  • Upload privately: { "filePath": "/tmp/myvideo.mp4", "title": "Test" }

  • Upload publicly: { "filePath": "/tmp/myvideo.mp4", "title": "Launch", "privacyStatus": "public" }

Errors

  • 400: file not found or unreadable, or required title missing

  • 403: upload scope missing — re-run npm run auth

  • 429: quota exceeded (upload costs ~1600 units)

youtube_delete_videoA

Permanently delete a video from the authenticated channel.

This action is irreversible. You must pass confirm:true to proceed.

Args

  • videoId (string, required): ID of the video to delete

  • confirm (boolean, required): must be true to proceed — safety guard

Returns Short confirmation that the video was deleted.

Examples

  • Delete: { "videoId": "abc123", "confirm": true }

Errors

  • 403: video is not owned by the authenticated account

  • 404: video not found

youtube_set_thumbnailA

Upload and set a custom thumbnail for a video.

The image is streamed from a local file. The MIME type is inferred from the file extension (.png, .jpg/.jpeg, .gif, .bmp).

Args

  • videoId (string, required): video to update the thumbnail for

  • imagePath (string, required): absolute path to the local image file

Returns Short confirmation + thumbnail resource with URLs for all size variants.

Examples

  • Set thumbnail: { "videoId": "abc123", "imagePath": "/tmp/thumb.jpg" }

Errors

  • 400: file not found, unsupported format, or image too large (max 2 MB)

  • 403: thumbnails require a verified channel or custom thumbnail permission

youtube_rate_videoA

Like, dislike, or remove your rating from a video.

Calls videos.rate. The rating applies to the authenticated user's account.

Args

  • videoId (string, required): video to rate

  • rating ("like"|"dislike"|"none", required): the rating to apply

Returns Short confirmation of the rating applied.

Examples

  • Like: { "videoId": "dQw4w9WgXcQ", "rating": "like" }

  • Remove rating: { "videoId": "dQw4w9WgXcQ", "rating": "none" }

Errors

  • 400: invalid rating value

  • 403: scope missing or video not accessible

youtube_list_video_categoriesA

List available YouTube video categories for a region.

Calls videoCategories.list with the given regionCode. The returned category IDs can be used as the categoryId field in youtube_upload_video and youtube_update_video.

Args

  • regionCode (string, optional): ISO 3166-1 alpha-2 region code, default "US"

  • response_format: "markdown" (default) or "json"

Returns JSON shape:

{
  "regionCode": "US",
  "categories": [
    { "id": "10", "title": "Music", "assignable": true },
    { "id": "22", "title": "People & Blogs", "assignable": true }
  ]
}

Examples

  • US categories: {}

  • GB categories: { "regionCode": "GB" }

Errors

  • 400: invalid regionCode

youtube_list_playlistsA

List all playlists belonging to the authenticated channel.

Args

  • maxResults (integer 1–50, default 25): Number of playlists to return per page.

  • pageToken (string, optional): Pagination cursor from a previous call's nextPageToken.

  • response_format ("markdown" | "json", default "markdown"): Output format.

Returns JSON shape:

{
  "playlists": [
    {
      "id": "PL...",
      "title": "My Playlist",
      "description": "...",
      "privacyStatus": "public" | "private" | "unlisted",
      "itemCount": 12,
      "publishedAt": "2024-01-01T00:00:00Z"
    }
  ],
  "nextPageToken": "...",
  "totalResults": 42
}

Examples

  • List first page: youtube_list_playlists()

  • Page 2: youtube_list_playlists({ pageToken: "..." })

Errors

  • 401/403 → re-run npm run auth; check OAuth scopes.

youtube_get_playlistA

Fetch full details for a single playlist by its ID.

Args

  • playlistId (string, required): The YouTube playlist ID (e.g. PLrEnWoR732-B...).

  • response_format ("markdown" | "json", default "markdown"): Output format.

Returns JSON shape:

{
  "id": "PL...",
  "title": "My Playlist",
  "description": "...",
  "privacyStatus": "public",
  "itemCount": 12,
  "publishedAt": "2024-01-01T00:00:00Z",
  "defaultLanguage": "en",
  "channelId": "UC...",
  "channelTitle": "My Channel"
}

Examples

  • youtube_get_playlist({ playlistId: "PLrEnWoR732-B..." })

Errors

  • 404 → playlist not found or not accessible.

  • 403 → insufficient permission.

youtube_create_playlistA

Create a new playlist on the authenticated channel.

Args

  • title (string, required): Playlist title (max 255 characters).

  • description (string, optional): Playlist description.

  • privacyStatus ("public" | "private" | "unlisted", default "private"): Visibility.

  • defaultLanguage (string, optional): BCP-47 language code (e.g. "en").

Returns Confirmation Markdown + structured new playlist resource:

{ "id": "PL...", "title": "...", "privacyStatus": "private", "publishedAt": "..." }

Examples

  • youtube_create_playlist({ title: "My Shorts", privacyStatus: "public" })

Errors

  • 400 → invalid parameters (e.g. empty title).

  • 403 → quota exceeded or insufficient scope.

youtube_update_playlistA

Update metadata of an existing playlist. Fetches the current playlist first and merges only the provided fields, so omitted fields are preserved. snippet.title is always required by the API — the existing title is kept when not supplied.

Args

  • playlistId (string, required): Playlist ID to update.

  • title (string, optional): New title. If omitted, existing title is preserved.

  • description (string, optional): New description.

  • privacyStatus ("public" | "private" | "unlisted", optional): New visibility.

Returns Confirmation Markdown + structured updated playlist resource.

Examples

  • youtube_update_playlist({ playlistId: "PL...", title: "Best of 2024" })

  • youtube_update_playlist({ playlistId: "PL...", privacyStatus: "public" })

Errors

  • 404 → playlist not found.

  • 403 → not your playlist or scope missing.

youtube_delete_playlistA

Permanently delete a playlist. This is irreversible.

Args

  • playlistId (string, required): Playlist ID to delete.

  • confirm (boolean, default false): Must be true to execute the deletion.

Returns Confirmation text on success.

Examples

  • youtube_delete_playlist({ playlistId: "PL...", confirm: true })

Errors

  • 404 → playlist not found.

  • 403 → not your playlist or scope missing.

  • Not passing confirm: true → refused with instructions to re-call.

youtube_list_playlist_itemsA

List the videos inside a playlist, with pagination support.

Args

  • playlistId (string, required): Playlist ID to list items from.

  • maxResults (integer 1–50, default 25): Items per page.

  • pageToken (string, optional): Pagination cursor from a previous call's nextPageToken.

  • response_format ("markdown" | "json", default "markdown"): Output format.

Returns JSON shape:

{
  "playlistId": "PL...",
  "items": [
    {
      "playlistItemId": "PLitem...",
      "position": 0,
      "videoId": "dQw4w9WgXcQ",
      "title": "Video Title",
      "description": "...",
      "publishedAt": "2024-01-01T00:00:00Z",
      "videoOwnerChannelTitle": "Channel Name"
    }
  ],
  "nextPageToken": "...",
  "totalResults": 50
}

Examples

  • youtube_list_playlist_items({ playlistId: "PL..." })

  • Next page: youtube_list_playlist_items({ playlistId: "PL...", pageToken: "..." })

Errors

  • 404 → playlist not found.

  • 403 → no access.

youtube_add_video_to_playlistA

Add a YouTube video to one of your playlists, with optional position.

Args

  • playlistId (string, required): The target playlist ID.

  • videoId (string, required): The video ID to add.

  • position (integer ≥ 0, optional): Zero-based position to insert at. If omitted, appends to end.

Returns Confirmation Markdown + structured new playlist item resource:

{
  "playlistItemId": "...",
  "playlistId": "PL...",
  "videoId": "...",
  "position": 0
}

Examples

  • youtube_add_video_to_playlist({ playlistId: "PL...", videoId: "dQw4w9WgXcQ" })

  • Add at position 0: youtube_add_video_to_playlist({ playlistId: "PL...", videoId: "...", position: 0 })

Errors

  • 404 → playlist or video not found.

  • 403 → not your playlist or quota exceeded.

youtube_update_playlist_itemA

Update the position or video reference of an existing playlist item. All four arguments are required by the YouTube API.

Args

  • playlistItemId (string, required): The playlist item ID to update.

  • playlistId (string, required): The playlist this item belongs to.

  • videoId (string, required): The video ID for this item.

  • position (integer ≥ 0, required): New zero-based position in the playlist.

Returns Confirmation Markdown + structured updated playlist item resource:

{
  "playlistItemId": "...",
  "playlistId": "PL...",
  "videoId": "...",
  "position": 2
}

Examples

  • Move to position 0: youtube_update_playlist_item({ playlistItemId: "...", playlistId: "PL...", videoId: "...", position: 0 })

Errors

  • 404 → item not found.

  • 403 → not your playlist.

youtube_remove_playlist_itemA

Remove a video from a playlist (deletes the playlist item). This is irreversible. Use youtube_list_playlist_items to find the playlistItemId.

Args

  • playlistItemId (string, required): The playlist item ID to remove.

  • confirm (boolean, default false): Must be true to execute the removal.

Returns Confirmation text on success.

Examples

  • youtube_remove_playlist_item({ playlistItemId: "...", confirm: true })

Errors

  • 404 → item not found.

  • 403 → not your playlist.

  • Not passing confirm: true → refused with instructions to re-call.

youtube_list_comment_threadsA

Retrieves a page of top-level comment threads for a YouTube video or channel.

Args

  • videoId (string, optional) — ID of the video whose comment threads to list.

  • channelId (string, optional) — Channel ID; lists all threads related to that channel (includes video comments and channel comments).

  • Exactly one of videoId / channelId must be supplied.

  • order ("time" | "relevance", default "time") — Sort order.

  • searchTerms (string, optional) — Filter threads containing this text.

  • maxResults (1–50, default 25) — Number of threads per page.

  • pageToken (string, optional) — Cursor returned from a previous call to fetch the next page.

  • response_format ("markdown" | "json", default "markdown") — Output format.

Returns

{
  "threads": [
    {
      "id": "string",
      "authorDisplayName": "string",
      "text": "string",
      "likeCount": 0,
      "publishedAt": "ISO-8601",
      "updatedAt": "ISO-8601",
      "totalReplyCount": 0,
      "replies": [ { "id": "string", "authorDisplayName": "string", "text": "string" } ]
    }
  ],
  "nextPageToken": "string | null"
}

Examples

  • List the first 10 comment threads on a video: { "videoId": "dQw4w9WgXcQ", "maxResults": 10 }

  • Page through channel comments: { "channelId": "UCxxxxxxx", "pageToken": "CAUQAA" }

Errors

  • 400 if neither or both of videoId / channelId are provided.

  • 403 if comments are disabled on the video or quota is exceeded.

  • 404 if the video or channel does not exist.

youtube_list_comment_repliesA

Retrieves a page of replies to a specific top-level comment thread.

Args

  • parentId (string, required) — ID of the parent comment thread (top-level comment ID).

  • maxResults (1–50, default 25) — Number of replies per page.

  • pageToken (string, optional) — Cursor from a previous response to fetch the next page.

  • response_format ("markdown" | "json", default "markdown") — Output format.

Returns

{
  "replies": [
    {
      "id": "string",
      "parentId": "string",
      "authorDisplayName": "string",
      "text": "string",
      "likeCount": 0,
      "publishedAt": "ISO-8601",
      "updatedAt": "ISO-8601"
    }
  ],
  "nextPageToken": "string | null"
}

Examples

  • Fetch replies for a comment thread: { "parentId": "UgxABC123_replies", "maxResults": 10 }

Errors

  • 404 if the parent comment does not exist.

  • 403 if the video's comments are disabled or quota is exceeded.

youtube_reply_to_commentA

Posts a reply to an existing top-level comment thread on behalf of the authenticated channel.

Args

  • parentId (string, required) — ID of the top-level comment thread to reply to.

  • text (string, required) — Text of the reply (supports basic HTML entities).

Returns The newly created comment resource:

{
  "id": "string",
  "parentId": "string",
  "authorDisplayName": "string",
  "text": "string",
  "publishedAt": "ISO-8601"
}

Examples

  • Reply to a comment: { "parentId": "UgxABC123", "text": "Thank you for watching!" }

Errors

  • 400 if text is empty or parentId is invalid.

  • 403 if the video has comments disabled or quota is exceeded.

  • 404 if the parent comment does not exist.

youtube_create_comment_threadA

Posts a new top-level comment on a YouTube video, creating a new comment thread.

Args

  • videoId (string, required) — ID of the video to comment on.

  • text (string, required) — Text of the top-level comment (supports basic HTML entities).

Returns The newly created commentThread resource:

{
  "id": "string",
  "videoId": "string",
  "authorDisplayName": "string",
  "text": "string",
  "likeCount": 0,
  "publishedAt": "ISO-8601"
}

Examples

  • Comment on a video: { "videoId": "dQw4w9WgXcQ", "text": "Great video!" }

Errors

  • 400 if text is empty.

  • 403 if comments are disabled for the video or quota is exceeded.

  • 404 if the video does not exist.

youtube_update_commentA

Updates the text of an existing comment owned by the authenticated channel.

Args

  • commentId (string, required) — ID of the comment to update.

  • text (string, required) — New text content for the comment.

Returns The updated comment resource:

{
  "id": "string",
  "parentId": "string",
  "authorDisplayName": "string",
  "text": "string",
  "updatedAt": "ISO-8601"
}

Examples

  • Fix a typo in a comment: { "commentId": "UgxABC123_reply", "text": "Corrected text here." }

Errors

  • 400 if text is empty or the commentId is invalid.

  • 403 if the comment does not belong to the authenticated channel, or quota is exceeded.

  • 404 if the comment does not exist.

youtube_delete_commentA

Permanently deletes a comment owned by the authenticated channel. This action is irreversible.

Args

  • commentId (string, required) — ID of the comment to delete.

  • confirm (boolean, default false) — Must be explicitly set to true to proceed. Safety guard against accidental deletion.

Returns A short confirmation message and the deleted comment ID:

{ "deleted": true, "commentId": "string" }

Examples

  • Delete a comment: { "commentId": "UgxABC123", "confirm": true }

Errors

  • Refused if confirm is not true.

  • 403 if the comment does not belong to the authenticated channel, or quota is exceeded.

  • 404 if the comment does not exist.

youtube_set_comment_moderationA

Sets the moderation status of one or more comments. Can optionally ban the comment author(s).

Args

  • commentId (string, required) — ID of the comment to moderate. Accepts a comma-separated list of IDs to moderate multiple comments in one call (e.g. "id1,id2,id3").

  • moderationStatus ("published" | "heldForReview" | "rejected", required) — Target moderation state:

    • published: approve and make public.

    • heldForReview: hold for manual review.

    • rejected: reject (hide) the comment.

  • banAuthor (boolean, default false) — If true, bans the author(s) from commenting on the channel.

Returns

{ "moderated": true, "commentIds": ["string"], "moderationStatus": "string", "banAuthor": false }

Examples

  • Approve a comment: { "commentId": "UgxABC123", "moderationStatus": "published" }

  • Reject and ban: { "commentId": "UgxXYZ,UgxFOO", "moderationStatus": "rejected", "banAuthor": true }

Errors

  • 400 if moderationStatus is invalid.

  • 403 if the comment(s) do not belong to the authenticated channel's videos, or quota is exceeded.

  • 404 if a comment ID does not exist.

youtube_mark_comment_as_spamA

Marks a comment as spam, flagging it for review by YouTube's moderation systems.

Args

  • commentId (string, required) — ID of the comment to mark as spam.

Returns

{ "markedAsSpam": true, "commentId": "string" }

Examples

  • Flag a spam comment: { "commentId": "UgxABC123" }

Errors

  • 403 if you do not have permission to moderate this comment, or quota is exceeded.

  • 404 if the comment does not exist.

youtube_list_captionsA

List all caption tracks available for a YouTube video.

Args

  • videoId (string, required): The YouTube video ID whose captions to list.

  • response_format ("markdown" | "json", default "markdown"): Output format.

Returns JSON shape:

{
  "videoId": "string",
  "items": [
    {
      "id": "string",
      "language": "string",
      "name": "string",
      "trackKind": "standard|asr|forced",
      "isDraft": boolean,
      "isAutoSynced": boolean,
      "status": "string"
    }
  ],
  "totalCount": number
}

Examples

  • List captions for video "dQw4w9WgXcQ": videoId="dQw4w9WgXcQ"

  • Get JSON output: videoId="dQw4w9WgXcQ", response_format="json"

Errors

  • 403: Forbidden — you can only list captions for videos on your own channel, or you lack the youtube.force-ssl scope.

  • 404: Video not found or not accessible with current credentials.

youtube_download_captionA

Download the raw content of a caption track by its ID.

If outPath is provided the content is written to that local file path and a confirmation message is returned. Otherwise the caption text is returned directly (truncated to the character limit if necessary).

Args

  • captionId (string, required): The caption track ID to download.

  • format ("srt" | "vtt" | "sbv", optional): Subtitle format. Defaults to the track's native format when omitted.

  • tlang (string, optional): ISO 639-1 language code for auto-translated output (e.g. "fr", "de").

  • outPath (string, optional): Absolute local path to write the caption file to.

Returns

  • Without outPath: the raw caption file content as a text string.

  • With outPath: a confirmation string "Written N bytes to <path>".

JSON shape (structured) when content returned inline:

{ "captionId": "string", "format": "string|null", "tlang": "string|null", "content": "string" }

Examples

  • Download as SRT: captionId="AYtvM...", format="srt"

  • Translate to French and save: captionId="AYtvM...", tlang="fr", outPath="/tmp/fr.vtt"

Errors

  • 403: Captions can only be downloaded for videos on your own channel. Check scopes (youtube.force-ssl).

  • 404: Caption track not found.

youtube_upload_captionA

Upload a new caption track to a YouTube video from a local file.

The file is streamed directly from disk via fs.createReadStream. The MIME type is inferred from the file extension (.vtt → text/vtt, .srt → application/x-subrip, .sbv → text/x-google-video-subtitle, .ttml → application/ttml+xml).

Args

  • videoId (string, required): The video ID to attach the caption track to.

  • language (string, required): BCP-47 language tag for the track (e.g. "en", "fr-CA").

  • name (string, required): A human-readable display name for the track (e.g. "English (CC)").

  • filePath (string, required): Absolute local path to the caption file (.vtt, .srt, .sbv, .ttml).

  • isDraft (boolean, default false): Whether to upload the track as a draft (not publicly visible).

Returns

{
  "id": "string",
  "videoId": "string",
  "language": "string",
  "name": "string",
  "trackKind": "string",
  "isDraft": boolean
}

Examples

  • Upload an English SRT: videoId="dQw4w9WgXcQ", language="en", name="English", filePath="/captions/en.srt"

  • Upload as draft: videoId="dQw4w9WgXcQ", language="es", name="Spanish", filePath="/captions/es.vtt", isDraft=true

Errors

  • 400: Invalid language tag or file format not supported.

  • 403: You can only add captions to videos on your own channel. Check scopes (youtube.force-ssl).

  • 404: Video not found.

youtube_update_captionA

Update an existing caption track's draft status and/or replace its content.

When filePath is supplied the caption file is replaced by streaming the new file from disk. When only isDraft is supplied only the metadata is updated (no file replacement).

Args

  • captionId (string, required): The ID of the caption track to update.

  • isDraft (boolean, optional): New draft state. Omit to leave unchanged.

  • filePath (string, optional): Absolute local path to a replacement caption file. When provided, the track content is replaced.

Returns

{
  "id": "string",
  "language": "string",
  "name": "string",
  "trackKind": "string",
  "isDraft": boolean
}

Examples

  • Publish a draft track: captionId="AYtvM...", isDraft=false

  • Replace content: captionId="AYtvM...", filePath="/updated/en.vtt"

  • Replace and publish: captionId="AYtvM...", isDraft=false, filePath="/updated/en.vtt"

Errors

  • 403: You can only update captions on your own channel. Check scopes (youtube.force-ssl).

  • 404: Caption track not found.

youtube_delete_captionA

Permanently delete a caption track from a YouTube video.

This action is irreversible. You must pass confirm: true explicitly or the tool will refuse to proceed.

Args

  • captionId (string, required): The ID of the caption track to delete.

  • confirm (boolean, default false): Must be set to true to authorize the deletion.

Returns A short confirmation string on success:

Caption track <captionId> deleted successfully.

Examples

  • Delete a track (dry run — will be refused): captionId="AYtvM..."

  • Delete a track (confirmed): captionId="AYtvM...", confirm=true

Errors

  • 403: You can only delete captions on your own channel. Check scopes (youtube.force-ssl).

  • 404: Caption track not found.

  • Refused: If confirm is not true the tool returns an error without calling the API.

youtube_searchA

Search YouTube for videos, channels, and/or playlists using the YouTube Data API v3 search.list endpoint.

IMPORTANT — Quota cost: Every call to this tool costs 100 quota units (vs. 1 for most other tools). Use it sparingly and narrow the query as much as possible before calling.

Args:

  • query (required) — Free-text search query (e.g., "typescript tutorial 2024").

  • type — Comma-separated list of resource types to return. Allowed values: video, channel, playlist. Default: "video".

  • channelId — Restrict results to a specific channel's content. Optional.

  • order — Sort order: relevance (default), date, rating, title, viewCount.

  • maxResults — Number of results to return (1–50, default 25).

  • pageToken — Pagination cursor from a previous response's nextPageToken. Optional.

  • publishedAfter — Only return results published after this RFC 3339 datetime (e.g., "2024-01-01T00:00:00Z"). Optional.

  • publishedBefore — Only return results published before this RFC 3339 datetime. Optional.

  • regionCode — ISO 3166-1 alpha-2 code to bias results (e.g., "US"). Defaults to server default.

  • relevanceLanguage — ISO 639-1 language code to bias relevance (e.g., "en"). Optional.

  • forMine — When true, restricts results to the authenticated user's own videos. Requires type to include only "video". Optional.

  • response_format"markdown" (default) or "json".

Returns (JSON shape):

{
  "nextPageToken": "string | null",
  "pageInfo": { "totalResults": 1234, "resultsPerPage": 25 },
  "items": [
    {
      "kind": "youtube#searchResult",
      "id": { "kind": "youtube#video", "videoId": "abc123" },
      "snippet": {
        "publishedAt": "2024-01-15T12:00:00Z",
        "channelId": "UCxxx",
        "title": "Result title",
        "description": "Short description...",
        "thumbnails": { "default": { "url": "..." } },
        "channelTitle": "Channel Name",
        "liveBroadcastContent": "none"
      }
    }
  ]
}

Examples:

  1. Search for recent TypeScript videos: { "query": "typescript tutorial", "order": "date", "maxResults": 10 }

  2. Search own channel for a topic: { "query": "react hooks", "forMine": true, "type": "video" }

  3. Paginate to the next page: { "query": "nodejs", "pageToken": "<nextPageToken from previous call>" }

Common Errors:

  • 403 quotaExceeded — Daily quota exhausted (each call costs 100 units). Try again after midnight Pacific time.

  • 400 invalidSearchFilter — Conflicting filters, e.g. forMine:true with type containing non-video values.

  • 401 / 403 authError — Credentials missing or expired; re-run npm run auth.

youtube_list_subscriptionsA

List all channels that the authenticated user is subscribed to, using the YouTube Data API v3 subscriptions.list endpoint with mine:true.

Args:

  • order — Sort order for the returned list. One of:

    • relevance (default) — YouTube's relevance ranking.

    • unread — Channels with new activity appear first.

    • alphabetical — Alphabetical by channel title.

  • maxResults — Number of subscriptions to return per page (1–50, default 25).

  • pageToken — Pagination cursor. Pass the nextPageToken from a previous response to retrieve the next page. Optional.

  • response_format"markdown" (default, human-readable summary) or "json" (full structured data).

Returns (JSON shape):

{
  "nextPageToken": "string | null",
  "pageInfo": { "totalResults": 142, "resultsPerPage": 25 },
  "items": [
    {
      "id": "subscription-resource-id",
      "snippet": {
        "publishedAt": "2021-03-10T08:00:00Z",
        "title": "Channel Title",
        "description": "Channel description...",
        "resourceId": { "kind": "youtube#channel", "channelId": "UCxxxxxx" },
        "thumbnails": { "default": { "url": "https://..." } }
      },
      "contentDetails": {
        "totalItemCount": 312,
        "newItemCount": 5,
        "activityType": "all"
      }
    }
  ]
}

Examples:

  1. List first 25 subscriptions alphabetically: { "order": "alphabetical" }

  2. Find channels with new videos: { "order": "unread", "maxResults": 10 }

  3. Paginate to the next page: { "pageToken": "<nextPageToken from previous call>" }

Common Errors:

  • 401 / 403 authError — Credentials missing or expired; re-run npm run auth.

  • 403 forbidden — The authenticated account does not have permission to list its own subscriptions; check scopes include https://www.googleapis.com/auth/youtube.

youtube_subscribeA

Subscribe the authenticated user to a YouTube channel, using the YouTube Data API v3 subscriptions.insert endpoint.

Args:

  • channelId (required) — The YouTube channel ID to subscribe to (e.g., "UCxxxxxx"). This is the channel's resource ID, not a handle or name. You can obtain it from youtube_search (type: channel) or youtube_list_subscriptions.

Returns (JSON shape):

{
  "id": "new-subscription-resource-id",
  "snippet": {
    "publishedAt": "2024-06-03T10:00:00Z",
    "title": "Subscribed Channel Title",
    "description": "Channel description...",
    "resourceId": { "kind": "youtube#channel", "channelId": "UCxxxxxx" },
    "thumbnails": { "default": { "url": "https://..." } }
  },
  "contentDetails": {
    "totalItemCount": 0,
    "newItemCount": 0,
    "activityType": "all"
  }
}

Examples:

  1. Subscribe to a channel: { "channelId": "UC_x5XG1OV2P6uZZ5FSM9Ttw" }

Common Errors:

  • 400 subscriptionDuplicate — The authenticated user is already subscribed to this channel.

  • 400 invalidChannelId — The provided channelId does not correspond to an existing channel.

  • 401 / 403 authError — Credentials missing or expired; re-run npm run auth.

  • 403 forbidden — The authenticated account cannot subscribe (e.g., cannot subscribe to own channel, or missing scope https://www.googleapis.com/auth/youtube).

youtube_unsubscribeA

Remove a subscription for the authenticated user, using the YouTube Data API v3 subscriptions.delete endpoint.

IMPORTANT: This tool takes the subscription resource ID (the id field returned by youtube_list_subscriptions), not the channel's channelId. To find the correct ID, call youtube_list_subscriptions first and note the id field on each subscription item.

This action is destructive and irreversible — you must pass confirm: true to proceed. Without it the tool refuses and explains what would happen.

Args:

  • subscriptionId (required) — The subscription resource ID to delete (e.g., "ABCDefgh1234…"). Obtained from the id field of a youtube_list_subscriptions result item.

  • confirm — Must be true to actually perform the deletion. Default: false (dry-run refusal).

Returns: A short confirmation message on success. The YouTube API returns HTTP 204 (no body) on success, so no structured resource is returned.

Examples:

  1. Dry run (safe, returns an error explaining what would happen): { "subscriptionId": "ABCDefgh1234" }

  2. Actually unsubscribe: { "subscriptionId": "ABCDefgh1234", "confirm": true }

Common Errors:

  • 404 subscriptionNotFound — No subscription with the given ID exists for the authenticated user. Confirm the ID comes from youtube_list_subscriptions, not a channel ID.

  • 403 forbidden — Insufficient permissions or the subscription belongs to a different account; check scopes.

  • 401 / 403 authError — Credentials missing or expired; re-run npm run auth.

youtube_run_analytics_queryA

Execute a flexible YouTube Analytics API query against the authenticated channel. Supports any combination of metrics, dimensions, filters, and sort orders supported by the YouTube Analytics API v2. startDate and endDate default to the last 28 days when omitted.

Args:

  • metrics (required): Comma-separated metric names, e.g. "views,estimatedMinutesWatched,likes".

  • startDate (optional): Inclusive start date in YYYY-MM-DD format. Defaults to 28 days ago.

  • endDate (optional): Inclusive end date in YYYY-MM-DD format. Defaults to today.

  • dimensions (optional): Comma-separated dimension names, e.g. "day", "video", "country".

  • filters (optional): Semicolon-separated filter expressions, e.g. "video==VIDEO_ID".

  • sort (optional): Comma-separated sort keys. Prefix with - for descending, e.g. "-views".

  • maxResults (optional): Maximum rows to return (1–200).

  • currency (optional): ISO 4217 currency code for monetary metrics, e.g. "EUR". Defaults to "USD".

  • response_format (optional): "markdown" (default) or "json".

Returns (JSON shape):

{
  "columns": ["day", "views", "estimatedMinutesWatched"],
  "rows": [["2025-01-01", 1234, 5678], ...]
}

Examples:

  • "Show me daily views for the last 7 days" → metrics: "views", dimensions: "day", startDate: "2025-01-01", endDate: "2025-01-07".

  • "Top traffic sources by watch time" → metrics: "views,estimatedMinutesWatched", dimensions: "insightTrafficSourceType", sort: "-estimatedMinutesWatched".

Errors:

  • 400: invalid metric/dimension combination — check the Analytics API docs for valid pairings.

  • 403: missing scope or channel not accessible — re-run npm run auth.

youtube_channel_summaryA

Retrieve a broad performance summary for the authenticated channel covering views, watch time, subscriber changes, likes, dislikes, comments, and shares. Optionally break the data down by day or month.

Args:

  • startDate (optional): Inclusive start date in YYYY-MM-DD format. Defaults to 28 days ago.

  • endDate (optional): Inclusive end date in YYYY-MM-DD format. Defaults to today.

  • dimension (optional): Time grouping — "none" (default, aggregate totals), "day" (one row per day), or "month" (one row per month).

  • response_format (optional): "markdown" (default) or "json".

Returns (JSON shape):

{
  "columns": ["views", "estimatedMinutesWatched", "averageViewDuration", "averageViewPercentage",
               "subscribersGained", "subscribersLost", "likes", "dislikes", "comments", "shares"],
  "rows": [[12345, 67890, 240, 45.2, 100, 10, 500, 20, 80, 30]]
}

When dimension is "day" or "month", the first column is the date/month string.

Examples:

  • "Give me my channel stats for last month" → pass startDate / endDate covering that month.

  • "Daily breakdown of my channel this week" → dimension: "day" with appropriate dates.

Errors:

  • 403: insufficient scope — re-run npm run auth.

youtube_top_videosA

Return the top-performing videos on the authenticated channel ranked by views, enriched with video titles fetched from the YouTube Data API.

Args:

  • startDate (optional): Inclusive start date in YYYY-MM-DD format. Defaults to 28 days ago.

  • endDate (optional): Inclusive end date in YYYY-MM-DD format. Defaults to today.

  • maxResults (optional): Number of top videos to return (1–50, default 10).

  • response_format (optional): "markdown" (default) or "json".

Returns (JSON shape):

{
  "columns": ["video", "title", "views", "estimatedMinutesWatched", "averageViewDuration",
               "averageViewPercentage", "subscribersGained", "likes"],
  "rows": [["VIDEO_ID", "Video Title", 5000, 12000, 144, 55.3, 80, 200], ...]
}

Examples:

  • "What are my top 5 videos this month?" → maxResults: 5 with appropriate dates.

  • "Best performing videos over the past 90 days" → startDate 90 days ago.

Errors:

  • 403: insufficient scope — re-run npm run auth.

  • 400: invalid date range.

youtube_video_performanceA

Retrieve detailed analytics for a single YouTube video, including views, watch time, retention, subscriber impact, engagement, and more. Optionally break down by day.

Args:

  • videoId (required): The YouTube video ID, e.g. "dQw4w9WgXcQ".

  • startDate (optional): Inclusive start date in YYYY-MM-DD format. Defaults to 28 days ago.

  • endDate (optional): Inclusive end date in YYYY-MM-DD format. Defaults to today.

  • dimension (optional): "none" (default, aggregate) or "day" (per-day breakdown).

  • response_format (optional): "markdown" (default) or "json".

Returns (JSON shape):

{
  "columns": ["views", "estimatedMinutesWatched", "averageViewDuration", "averageViewPercentage",
               "subscribersGained", "subscribersLost", "likes", "dislikes", "comments", "shares"],
  "rows": [[5000, 12000, 144, 55.3, 30, 2, 200, 5, 40, 15]]
}

When dimension is "day", the first column is the date string.

Examples:

  • "How did video dQw4w9WgXcQ perform last month?" → videoId: "dQw4w9WgXcQ" with date args.

  • "Day-by-day views for my latest video" → videoId: "...", dimension: "day".

Errors:

  • 400: invalid video ID format or unsupported metric/dimension pair.

  • 403: insufficient scope — re-run npm run auth.

youtube_traffic_sourcesA

Show how viewers find the channel's videos, broken down by traffic source type (e.g. YouTube search, suggested videos, external, direct, playlists, etc.).

Args:

  • startDate (optional): Inclusive start date in YYYY-MM-DD format. Defaults to 28 days ago.

  • endDate (optional): Inclusive end date in YYYY-MM-DD format. Defaults to today.

  • response_format (optional): "markdown" (default) or "json".

Returns (JSON shape):

{
  "columns": ["insightTrafficSourceType", "views", "estimatedMinutesWatched"],
  "rows": [["YT_SEARCH", 5000, 12000], ["SUGGESTED_VIDEO", 3000, 8000], ...]
}

Examples:

  • "Where do my viewers come from?" → call with no arguments.

  • "Traffic sources for the last 7 days" → pass matching startDate / endDate.

Errors:

  • 403: insufficient scope — re-run npm run auth.

youtube_audience_demographicsA

Retrieve the age group and gender distribution of the channel's viewers, expressed as percentages of total viewership.

Args:

  • startDate (optional): Inclusive start date in YYYY-MM-DD format. Defaults to 28 days ago.

  • endDate (optional): Inclusive end date in YYYY-MM-DD format. Defaults to today.

  • response_format (optional): "markdown" (default) or "json".

Returns (JSON shape):

{
  "columns": ["ageGroup", "gender", "viewerPercentage"],
  "rows": [
    ["age25-34", "male", 23.5],
    ["age18-24", "female", 18.2],
    ...
  ]
}

Examples:

  • "What is my audience demographics?" → call with no arguments.

  • "Demographics for Q1 2025" → pass matching startDate / endDate.

Errors:

  • 403: insufficient scope or the channel has insufficient data — re-run npm run auth.

  • rows empty: channel may not have enough viewership data to surface demographics.

youtube_geographyA

Break down views, watch time, and average view duration by country for the authenticated channel.

Args:

  • startDate (optional): Inclusive start date in YYYY-MM-DD format. Defaults to 28 days ago.

  • endDate (optional): Inclusive end date in YYYY-MM-DD format. Defaults to today.

  • maxResults (optional): Number of countries to return (1–50, default 25).

  • response_format (optional): "markdown" (default) or "json".

Returns (JSON shape):

{
  "columns": ["country", "views", "estimatedMinutesWatched", "averageViewDuration"],
  "rows": [["US", 10000, 45000, 270], ["IN", 8000, 30000, 225], ...]
}

Examples:

  • "Where are my viewers located?" → call with no arguments.

  • "Top 10 countries by views this month" → maxResults: 10 with appropriate dates.

Errors:

  • 403: insufficient scope — re-run npm run auth.

youtube_revenueA

Retrieve revenue and monetization metrics for the authenticated channel, including estimated revenue, CPM, monetized playbacks, and ad impressions. Optionally break down by day or month.

IMPORTANT: This tool requires:

  1. The yt-analytics-monetary.readonly OAuth scope (included if you ran npm run auth with the default SCOPES).

  2. The channel must be enrolled in the YouTube Partner Program (monetized). If either condition is not met, the API returns HTTP 403.

Args:

  • startDate (optional): Inclusive start date in YYYY-MM-DD format. Defaults to 28 days ago.

  • endDate (optional): Inclusive end date in YYYY-MM-DD format. Defaults to today.

  • dimension (optional): "none" (default, aggregate), "day", or "month".

  • currency (optional): ISO 4217 three-letter currency code, e.g. "EUR". Defaults to "USD".

  • response_format (optional): "markdown" (default) or "json".

Returns (JSON shape):

{
  "columns": ["estimatedRevenue", "estimatedAdRevenue", "grossRevenue", "cpm",
               "playbackBasedCpm", "monetizedPlaybacks", "adImpressions"],
  "rows": [[1234.56, 1100.00, 1300.00, 5.20, 4.80, 240000, 1500000]]
}

When dimension is "day" or "month", the first column is the date string.

Examples:

  • "How much revenue did I make this month?" → pass appropriate date range.

  • "Daily revenue breakdown in EUR" → dimension: "day", currency: "EUR".

Errors:

  • 403: channel is not in the YouTube Partner Program, the yt-analytics-monetary.readonly scope was not granted, or YouTube Partner status is missing. Re-run npm run auth and ensure your channel is monetized.

Prompts

Interactive templates invoked by user choice

NameDescription

No prompts

Resources

Contextual data attached and managed by the client

NameDescription

No resources

Latest Blog Posts

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/tuitamogamer-gpt/youtube-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server