Skip to main content
Glama
granitebps

YouTube MCP Server

by granitebps

YouTube MCP

CI npm version npm downloads MCP Registry License: ISC

YouTube MCP lets an MCP client read YouTube video metadata, caption transcripts, comments, and search results. By default it needs no YouTube API key or account; an optional official YouTube Data API provider serves metadata, comments, and search with an API key.

Supports both stdio (local) and Streamable HTTP (VPS/remote) transports.

Access model

This is an independent, unofficial open-source project. It is not affiliated with, endorsed by, or sponsored by YouTube or Google.

  • The default innertube provider serves metadata, comments, and search through youtubei.js, using an unofficial/internal YouTube interface without a YouTube Data API key. Unofficial access may change, break, be restricted, or be blocked.

  • Select YT_PROVIDER=api and supply your own YOUTUBE_API_KEY to use the official YouTube Data API v3 for those three tools.

  • Transcript tools always use youtube-transcript-plus, regardless of YT_PROVIDER. Transcript retrieval remains unofficial and does not use the official Data API path or your API key.

Users are responsible for deciding whether an access method suits their use and for complying with applicable service terms and law. See access methods and service terms for the tool/backend mapping, BYOK setup, limitations, and software licenses.

Related MCP server: yt

Features

Tool

Description

search_youtube

Search videos with filters for upload date and popularity

get_video_info

Video metadata: title, channel, description, duration, views, likes, upload date, tags

get_video_comments

Comment threads with author info, likes, and the replies YouTube includes

get_video_transcript

Transcripts (manual + auto-generated captions) with timestamps

get_transcript_languages

Lists available manual and auto-generated caption languages

get_server_info

Server version, active provider, and the backend serving each tool

Requirements

  • Node.js 22 or newer. CI checks Node 22.21.0 and Node 24.

No YouTube API key required by default. The default innertube provider uses youtubei.js (an unofficial/internal YouTube interface) for video info, comments, and search. Transcripts always use youtube-transcript-plus. Neither needs an API key or authentication. See Providers for the optional official API.

Quick start

Your MCP client can run the published package without a clone:

npx -y @granitebps/youtube-mcp

The server uses stdio. Keep stdout reserved for MCP traffic.

Run from a cloned repository

To develop the server or use a clone directly:

git clone https://github.com/granitebps/youtube-mcp.git
cd youtube-mcp
npm ci
npm run build

Point your MCP client at the compiled entry point:

node /absolute/path/to/youtube-mcp/dist/index.js

Run npm run build after each source change. Do not use src or npm run dev as the client's stdio command; build output on stdout can corrupt MCP messages.

Client configuration

Each example starts with the npm package, followed by the local equivalent. Replace /absolute/path/to/youtube-mcp with your clone's path. Settings from Configuration can be added as environment variables.

Claude

Add the npm package to Claude Code:

claude mcp add youtube -- npx -y @granitebps/youtube-mcp

For a local build:

claude mcp add youtube -- node /absolute/path/to/youtube-mcp/dist/index.js

Claude Code uses local scope by default. Add --scope user before youtube to make the server available across projects.

Claude Desktop reads the same server from claude_desktop_config.json (on macOS, ~/Library/Application Support/Claude/claude_desktop_config.json). Restart the app after editing the file.

{
  "mcpServers": {
    "youtube": {
      "command": "npx",
      "args": ["-y", "@granitebps/youtube-mcp"]
    }
  }
}

For a local build, replace command and args with:

{
  "command": "node",
  "args": ["/absolute/path/to/youtube-mcp/dist/index.js"]
}

Codex

Add the npm package to ~/.codex/config.toml, or to .codex/config.toml in a trusted project:

[mcp_servers.youtube]
command = "npx"
args = ["-y", "@granitebps/youtube-mcp"]

For a local build:

[mcp_servers.youtube]
command = "node"
args = ["/absolute/path/to/youtube-mcp/dist/index.js"]

Restart Codex after editing the file.

OpenCode

Add the npm package to opencode.json or opencode.jsonc:

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "youtube": {
      "type": "local",
      "command": ["npx", "-y", "@granitebps/youtube-mcp"],
      "enabled": true
    }
  }
}

For a local build, replace the command array with:

{
  "command": ["node", "/absolute/path/to/youtube-mcp/dist/index.js"]
}

Cursor

Add the npm package to .cursor/mcp.json in a project, or to ~/.cursor/mcp.json for global use:

{
  "mcpServers": {
    "youtube": {
      "command": "npx",
      "args": ["-y", "@granitebps/youtube-mcp"]
    }
  }
}

For a local build, replace command and args with:

{
  "command": "node",
  "args": ["/absolute/path/to/youtube-mcp/dist/index.js"]
}

GitHub Copilot (VS Code)

Add to your VS Code settings.json:

{
  "mcp": {
    "servers": {
      "youtube": {
        "command": "npx",
        "args": ["-y", "@granitebps/youtube-mcp"]
      }
    }
  }
}

VPS deployment (Streamable HTTP)

For remote deployment, the server runs as a persistent HTTP service using the Streamable HTTP transport (the current MCP standard, replacing the deprecated SSE transport).

1. Deploy to your VPS

# On your VPS
git clone https://github.com/granitebps/youtube-mcp.git
cd youtube-mcp
npm ci
npm run build

# Create .env (optional, for HTTP mode)
cp .env.example .env
# Uncomment TRANSPORT=http, PORT, HOST as needed

YouTube often blocks datacenter IPs. If get_video_info returns ACCESS_BLOCKED with "Sign in to confirm you're not a bot", set YT_PROVIDER=api and YOUTUBE_API_KEY to serve metadata, comments, and search through the official API. See Providers.

2. Run with HTTP transport

# Using --http flag
node dist/index.js --http

# Or using environment variable
TRANSPORT=http PORT=3000 node dist/index.js

# Or using npm script
npm run start:http

The server will listen on http://0.0.0.0:3000/mcp.

3. Set up Nginx reverse proxy with TLS

server {
    listen 443 ssl;
    server_name mcp.yourdomain.com;

    ssl_certificate     /etc/letsencrypt/live/mcp.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/mcp.yourdomain.com/privkey.pem;

    location /mcp {
        proxy_pass http://127.0.0.1:3000/mcp;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # Required for SSE streaming
        proxy_set_header Connection '';
        proxy_buffering off;
        proxy_cache off;
        chunked_transfer_encoding on;
    }
}

Get a free TLS certificate:

sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d mcp.yourdomain.com

4. Keep it running with systemd

Create /etc/systemd/system/youtube-mcp.service:

[Unit]
Description=YouTube MCP Server
After=network.target

[Service]
Type=simple
User=your_user
WorkingDirectory=/path/to/youtube-mcp
ExecStart=/usr/bin/node dist/index.js --http
Restart=always
RestartSec=5
Environment=TRANSPORT=http
Environment=PORT=3000
Environment=HOST=127.0.0.1

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable youtube-mcp
sudo systemctl start youtube-mcp
sudo systemctl status youtube-mcp

5. Connect MCP clients to your VPS

GitHub Copilot (VS Code) — Remote

{
  "mcp": {
    "servers": {
      "youtube": {
        "type": "http",
        "url": "https://mcp.yourdomain.com/mcp"
      }
    }
  }
}

Claude Desktop — Remote

{
  "mcpServers": {
    "youtube": {
      "type": "streamable-http",
      "url": "https://mcp.yourdomain.com/mcp"
    }
  }
}

Usage Examples

Once connected, you can ask your AI agent things like:

  • "Get info about this YouTube video: https://www.youtube.com/watch?v=dQw4w9WgXcQ"

  • "Show me the top comments on video ID abc123"

  • "Get the transcript of this video in English"

  • "Summarize the transcript of https://youtu.be/xyz789"

  • "Search for Node.js tutorials uploaded this week, sorted by views"

  • "Find the most popular React videos from the last month"

Tool Response Format

All tools return:

  • content: short human-readable text for chat-style MCP clients

  • structuredContent: JSON-shaped data for agents that need reliable fields

The server is intentionally JSON-first, text-second. Agents should prefer structuredContent when they need to filter, transform, or chain tool results.

Example shape from get_video_info:

{
  "content": [
    {
      "type": "text",
      "text": "📹 Example title\n\nChannel: Example channel\n..."
    }
  ],
  "structuredContent": {
    "videoId": "dQw4w9WgXcQ",
    "title": "Example title",
    "description": "Example description",
    "channelName": "Example channel",
    "channelId": "UC123",
    "uploadedAt": "Sep 14, 2017",
    "duration": "3m 33s",
    "durationSeconds": 213,
    "viewCount": "123456",
    "likeCount": "7890",
    "commentCount": null,
    "tags": ["music", "pop"],
    "thumbnailUrl": "https://..."
  }
}

Values YouTube did not provide are null, never placeholders such as "0", "N/A" or "Unknown".

Errors

Failures return isError: true. The text starts with a code (❌ [ACCESS_BLOCKED] ...) and _meta["youtube-mcp/error"] carries the details:

{
  "isError": true,
  "content": [{ "type": "text", "text": "❌ [ACCESS_BLOCKED] YouTube requires sign-in to access video C7OQHIpDlvA: Sign in to confirm you’re not a bot" }],
  "_meta": {
    "youtube-mcp/error": {
      "code": "ACCESS_BLOCKED",
      "message": "...",
      "retryable": false,
      "upstream": { "playabilityStatus": "LOGIN_REQUIRED", "reason": "Sign in to confirm you’re not a bot", "accessKind": "login_required" }
    }
  }
}

The error is in _meta, not structuredContent, because MCP SDK clients validate any structuredContent against the tool's output schema, even on error results.

Code

Meaning

INVALID_INPUT

Not a YouTube URL or 11-character video ID, or an invalid language code

ACCESS_BLOCKED

YouTube refused this client: HTTP 429/403, CAPTCHA, consent page, sign-in or bot check. upstream.accessKind is rate_limited, forbidden, login_required, consent_required, or quota_exceeded (official API quota used up). Says nothing about whether the video exists or has captions

VIDEO_UNAVAILABLE

YouTube reports the video as ERROR, UNPLAYABLE, private or offline. upstream.reason is YouTube's own text

CAPTIONS_UNAVAILABLE / LANGUAGE_UNAVAILABLE

Used internally; transcript tools return these as available: false results, not errors

COMMENTS_UNAVAILABLE

Comments are disabled or YouTube returned no comments section

PARSE_ERROR

YouTube answered but the response could not be interpreted (layout change, wrong video ID returned)

LIMIT_EXCEEDED

A configured size limit was hit

TIMEOUT

A configured deadline expired; the underlying requests were aborted

CANCELLED

The MCP client cancelled the request, or the server is shutting down

UPSTREAM_ERROR

Other HTTP or network failure (retryable: true)

The server never retries on its own.

Providers

YT_PROVIDER selects the backend for get_video_info, get_video_comments, and search_youtube. get_video_transcript and get_transcript_languages always use youtube-transcript-plus, whichever provider is active. get_server_info reports the active provider.

Provider

Select with

Needs

Notes

InnerTube

Default, or YT_PROVIDER=innertube

Nothing

Uses an unofficial/internal interface through youtubei.js, with no Data API key. YouTube may restrict or block access, including from datacenter IPs (VPS, cloud)

Official API

YT_PROVIDER=api

YOUTUBE_API_KEY

Uses the YouTube Data API v3. Subject to your Google Cloud project's quota, key restrictions, and applicable service terms

This server does not use the Data API for captions. Google's caption-download endpoint requires OAuth authorization and permission to edit the video; an API key alone is insufficient. Transcript tools use the unofficial youtube-transcript-plus path and can return ACCESS_BLOCKED with either provider.

Using the official API

Bring your own key (BYOK). The key belongs to you; the project does not distribute or host a shared YouTube API key. Supply these settings through the process or MCP client environment; the server does not automatically load .env files.

  1. In the Google Cloud console, create a project, enable YouTube Data API v3, and create an API key. Restricting the key to that API is recommended.

  2. Start the server with:

YT_PROVIDER=api YOUTUBE_API_KEY=your_api_key npx -y @granitebps/youtube-mcp

Quota (costs): the default allocation is 10,000 units per day, plus a separate allowance of 100 search.list calls per day.

Tool

API calls

get_video_info

videos.list: 1 unit

get_video_comments

commentThreads.list: 1 unit per page. page: N walks the N-1 pages before it, so it costs N units

search_youtube

search.list (search allowance) plus one videos.list for views and durations: 1 unit

Results are cached as with the default provider (video info 30 min, comments 10 min, search 15 min), so repeated calls cost nothing. A used-up quota returns ACCESS_BLOCKED with upstream.accessKind: "quota_exceeded"; an invalid key or disabled API returns ACCESS_BLOCKED with accessKind: "forbidden".

Differences from the default provider:

  • uploadedAt (get_video_info) and publishedAt (comments, search) are ISO 8601 timestamps instead of display text such as "Sep 14, 2017" or "2 days ago"

  • Search viewCount is a plain number such as "1234" instead of "1.2K views", and duration uses the same format as get_video_info ("3m 5s")

  • search_youtube applies all sortBy and uploadDate values exactly and never returns warnings. videoDuration: "short" means under 4 minutes and medium 4 to 20 minutes (YouTube's API definitions)

  • get_video_comments returns only the replies the API includes with each thread (a subset); replyCount is the full count

Configuration

All settings are optional environment variables, except YOUTUBE_API_KEY when YT_PROVIDER=api. Invalid values stop the server at startup with a message on stderr.

Variable

Default

Effect

YT_PROVIDER

innertube

Provider for video info, comments, and search: innertube or api. See Providers

YOUTUBE_API_KEY

none

Your own YouTube Data API v3 key. Required when YT_PROVIDER=api, ignored otherwise

YT_INIT_TIMEOUT_MS

15000

Deadline for creating the shared YouTube client

YT_REQUEST_TIMEOUT_MS

20000

Deadline for one tool call's upstream work, including waiting for client init

YT_TRANSCRIPT_MAX_BYTES

5000000

Maximum bytes read from each response fetched for captions

YT_TRANSCRIPT_MAX_SEGMENTS

50000

Maximum caption segments processed from one track

YT_TRANSCRIPT_PAGE_MAX_SEGMENTS

500

Maximum segments returned in one get_video_transcript response

When a deadline expires or the client cancels, the in-flight HTTP requests are aborted, not just abandoned.

Tool Details

search_youtube

  • Input: query (search text), maxResults (1-50, default 10), sortBy (relevance | date | viewCount | rating), uploadDate (any | hour | today | week | month | year), videoDuration (any | short | medium | long)

  • Returns: Human-readable summary in content plus structured JSON results in structuredContent

  • Note: With the default innertube provider, YouTube search only orders by relevance or popularity and only filters uploads from today up. sortBy: "date" keeps relevance order, sortBy: "rating" sorts by popularity, and uploadDate: "hour" is applied as today. Each case adds an entry to the optional warnings array (code, message). The api provider applies every option exactly

get_video_info

  • Input: video (YouTube URL or video ID)

  • Returns: Human-readable summary in content plus structured JSON metadata in structuredContent, including durationSeconds. Metadata is returned even when YouTube refuses playback, as long as it provides the video details

get_video_comments

  • Input: video (URL or ID), maxResults (1-20, default 20), sortBy (relevance or time), page (default 1)

  • Returns: Human-readable summary in content plus structured JSON comment threads, pagination fields, and hasMore in structuredContent

  • Note: replies contains only replies YouTube includes with the thread; replyCount is the full count. Fetching the rest would cost one request per thread

get_video_transcript

  • Input: video (URL or ID), lang (optional language code; omitted means the first manual track, or the first auto-generated one if there is none), maxSegments (default 0: as many as YT_TRANSCRIPT_PAGE_MAX_SEGMENTS allows), startSegment (default 0)

  • Returns: Human-readable transcript in content plus structured JSON segments, plain text, and pagination metadata in structuredContent. Continue with startSegment = nextStartSegment and the returned languageCode as lang while hasMore is true. isAutoGenerated tells whether the track is YouTube's automatic captions

  • No captions: available: false with reason: "NO_CAPTIONS", or reason: "LANGUAGE_UNAVAILABLE" plus availableLanguages. Access problems are errors, never available: false

  • Note: When a language has both manual and automatic tracks, the manual track is returned

  • Note: Does NOT require an API key — works via YouTube's internal caption system. A transcript is caption text only; it is not an analysis of the video's picture

get_transcript_languages

  • Input: video (YouTube URL or video ID)

  • Returns: Human-readable language list in content plus structured JSON language metadata in structuredContent. available: false means the video is playable and has no caption tracks; access problems are errors

get_server_info

  • Input: none

  • Returns: name, version, provider (innertube or api), authenticated, exactSearchFilters, and tools, a map from each tool to the backend serving it

Development

npm test        # builds, then runs the offline test suite (no network access)
npm run check   # tests plus release metadata, package contents, and tarball install checks

See CONTRIBUTING.md.

Release verification

The automated suite covers input parsing, configuration, error classification, cancellation, the compiled stdio entry point, release metadata, and installation from an npm tarball. It never calls YouTube. Live YouTube checks are manual and separate from CI.

Maintainers follow the release guide for the approved-tag npm, MCP Registry, and GitHub release process.

Rate Limits

The default innertube provider and transcript tools use unofficial YouTube interfaces. They do not use the Data API quota system, but this does not imply unrestricted access:

  • Heavy automated usage may trigger CAPTCHAs or temporary blocks

  • Requests from datacenter IPs (VPS, cloud) are often blocked outright

  • Request pacing does not guarantee access or establish permission under service terms

The api provider is limited by your Google Cloud project's YouTube Data API quota instead. See Providers.

License

ISC. The software license is separate from YouTube/Google service terms and rights in retrieved content. See the access guide.

Available Tools

6 tools
get_server_infoA

Report the server version, the active provider (innertube or api) for video info, comments, and search, and which backend serves each tool. Transcript tools always use youtube-transcript-plus.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
nameYes
toolsYesBackend serving each tool
versionYes
providerYesValue of YT_PROVIDER; selects the backend for video info, comments, and search
authenticatedYesWhether the provider sends credentials (a YouTube Data API key)
exactSearchFiltersYesWhether search_youtube applies every sortBy and uploadDate option exactly, without warnings

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full behavioral burden. "Report" implies a side-effect-free read, and the provider-routing detail (transcripts always use youtube-transcript-plus) adds real context, but there is no explicit confirmation of read-only safety, cost, or failure behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences, front-loaded with the primary output (version and provider) and the caveat about transcript tools last. No filler text.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

A zero-parameter diagnostic tool with an output schema; the description explains the meaning of the returned fields (what innertube vs api implies, per-tool backend, transcript exception), which is exactly the context the schema's field names cannot supply.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so the baseline for this dimension is 4; there are no parameter semantics to clarify and the description rightly spends its space on the return payload instead.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ("Report") and enumerates the exact resources returned: server version, active provider per feature, and per-tool backend. That makes it unmistakably a diagnostic/meta tool versus the content-oriented siblings, though no sibling is named explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied — an agent can infer this is for inspecting server/provider configuration — but there is no explicit statement of when to call it (e.g., to debug why a provider behaves a certain way) and no exclusions or alternatives offered.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_transcript_languagesA

List all available caption/transcript languages for a YouTube video. Returns language codes and names for both manual and auto-generated captions. Call this first to discover available languages before fetching a transcript.

ParametersJSON Schema
NameRequiredDescriptionDefault
videoYesYouTube video URL or video ID

Output Schema

ParametersJSON Schema
NameRequiredDescription
messageNo
videoIdYes
availableYesfalse only when the video is playable and genuinely has no caption tracks; access problems are returned as errors
languagesYes
manualCountYes
totalTracksYes
autoGeneratedCountYes

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the behavioral burden, and it does disclose the return content categories (language codes and names, manual and auto-generated captions), which is meaningful context. It does not discuss permissions, rate limits, or error behavior, but for a simple read-only enumeration that is a minor gap.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, each earning its place: purpose, return contents, and workflow ordering. The core purpose is front-loaded and there is no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so the description need not enumerate return fields, and it still adds the useful manual-vs-auto distinction. Combined with the workflow guidance and full parameter documentation, an agent has everything needed to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, and the single 'video' parameter is fully documented in the schema as a URL or video ID. The description adds no format, alias, or validation detail beyond that, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (List) and resource (available caption/transcript languages) with the scope of a YouTube video, and explicitly notes it covers both manual and auto-generated captions. This clearly separates it from the sibling get_video_transcript, which fetches content rather than enumerating languages.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The final sentence gives explicit sequencing guidance: call this first to discover available languages before fetching a transcript, which directly references and routes relative to the sibling get_video_transcript. An agent knows both when to use it and what to do next.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_video_commentsA

Get YouTube video comments with replies. Returns comment text, author, likes, and date. Supports sorting by 'relevance' (top comments) or 'time' (newest). Returns error if comments are disabled. Served by the provider selected with YT_PROVIDER.

ParametersJSON Schema
NameRequiredDescriptionDefault
pageNoPage number for pagination. Each page returns up to 20 comment threads. Use hasMore in the response to know if more pages exist.
videoYesYouTube video URL or video ID
sortByNoSort order: 'relevance' (top comments) or 'time' (newest first)relevance
maxResultsNoNumber of comment threads per page (1-20, YouTube returns ~20 per page)

Output Schema

ParametersJSON Schema
NameRequiredDescription
pageYes
sortByYes
hasMoreYes
threadsYes
videoIdYes
threadCountYes
totalFetchedYes

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the burden, and it does disclose meaningful traits: the returned fields (text, author, likes, date), sorting behavior, the error condition when comments are disabled, and the provider dependency. It omits auth/permission needs and rate-limit behavior, leaving some gaps.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four compact sentences with no filler, and the core purpose is front-loaded. The trailing YT_PROVIDER note is environmental context of marginal value but does not bloat the definition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With a full output schema and 100% parameter coverage, the description need not explain return values, and it still adds the useful error and provider notes. It is essentially complete for a read-only comment fetcher.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents video, page, sortBy, and maxResults fully. The description's note on 'relevance' vs 'time' duplicates the enum documentation rather than adding new meaning, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Get YouTube video comments with replies') and clearly differentiates from siblings like get_video_info and get_video_transcript, which retrieve different data about the same video.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Describes the sorting options and the error case, giving implied context for use, but offers no explicit when-to-use vs. when-not guidance or routing to alternative tools. Siblings cover different resources, so little overlap exists to disambiguate.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_video_infoA

Get YouTube video metadata: title, channel, description, duration (text and seconds), views, likes, comment count, upload date, and tags. Unknown values are null. Served by the provider selected with YT_PROVIDER (see get_server_info). Input: YouTube URL or video ID. Errors carry a code (e.g. ACCESS_BLOCKED, VIDEO_UNAVAILABLE, TIMEOUT) in _meta["youtube-mcp/error"] and as a [CODE] text prefix.

ParametersJSON Schema
NameRequiredDescriptionDefault
videoYesYouTube video URL or video ID

Output Schema

ParametersJSON Schema
NameRequiredDescription
tagsYes
titleYes
videoIdYes
durationYesHuman-readable duration, e.g. '1m 21s'; null when unknown or live
channelIdYes
likeCountYes
viewCountYes
uploadedAtYesinnertube provider: display text such as 'Sep 14, 2017' or 'Premiered May 27, 2020'. api provider: ISO 8601 timestamp
channelNameYes
descriptionYesnull when YouTube did not provide a description; empty string when it is empty
commentCountYes
thumbnailUrlYes
durationSecondsYesDuration in seconds; null when unknown or live

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does well: it discloses that unknown values come back as null, that results depend on a provider chosen via YT_PROVIDER (pointing to get_server_info), and that failures surface a code such as ACCESS_BLOCKED/VIDEO_UNAVAILABLE/TIMEOUT in both _meta["youtube-mcp/error"] and a [CODE] text prefix. It omits rate-limit, caching, or quota behavior, which keeps it short of a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the returned fields, then the input contract, then error semantics — a sensible order with no filler. It is dense, but the only slightly expendable material is the redundant enumeration of return fields, which the output schema already covers.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter read tool with an output schema, the description covers input format, null semantics, provider dependency, and error signaling, which is enough to call and interpret it. Remaining gaps (auth/API-key requirement, rate limits, whether ACCESS_BLOCKED is retryable) are minor given an output schema exists.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and there is a single parameter, so the baseline is 3. The description's 'YouTube URL or video ID' simply restates the schema's own wording with no added syntax, accepted URL forms, or examples (e.g. youtu.be vs watch?v=).

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Get') plus resource ('YouTube video metadata') and then enumerates the exact fields returned (title, channel, duration, views, likes, comment count, upload date, tags), which cleanly separates it from get_video_comments, get_video_transcript, and search_youtube. An agent can identify the tool without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The field enumeration and the 'Input: YouTube URL or video ID' line make the use case clear: fetch metadata for one known video. However, it never explicitly says when-not to use it or names an alternative (e.g. search_youtube for discovery, get_video_comments for engagement detail), so guidance is contextual rather than prescriptive.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_video_transcriptA

Get YouTube video transcript/captions (manual or auto-generated) with timestamps. Use 'lang' to pick a language code (e.g. 'en', 'id'), or omit it to get the first manual track (else the first auto-generated one); get_transcript_languages lists the codes. Returns both timestamped and plain text versions, paginated with startSegment/nextStartSegment. available=false with reason NO_CAPTIONS or LANGUAGE_UNAVAILABLE when captions are absent; access problems (ACCESS_BLOCKED etc.) are errors.

ParametersJSON Schema
NameRequiredDescriptionDefault
langNoLanguage code for the transcript (e.g., 'en', 'id', 'ja'). Omit to get the first manual track, or the first auto-generated one if there is no manual track. get_transcript_languages lists the codes.
videoYesYouTube video URL or video ID
maxSegmentsNoMaximum number of transcript segments to return. 0 (default) returns as many as the server allows per response (currently 500). Use with startSegment for pagination.
startSegmentNoSegment index to start from (0-based). Use nextStartSegment from the previous response to paginate through long transcripts.

Output Schema

ParametersJSON Schema
NameRequiredDescription
reasonNoWhy available is false
hasMoreYes
messageNo
videoIdYes
segmentsYes
availableYes
plainTextYes
languageCodeYesLanguage of the returned track; the requested code when unavailable; null when none was requested and the video has no captions
startSegmentYes
totalSegmentsYes
isAutoGeneratedNoWhether the returned track is YouTube's automatic (ASR) captions; null if unknown
nextStartSegmentYes
returnedSegmentsYes
availableLanguagesNoLanguage codes that do exist, when reason is LANGUAGE_UNAVAILABLE

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does so well: it discloses the return shape (timestamped and plain text versions), the pagination mechanism (startSegment/nextStartSegment), the non-error failure mode (available=false with NO_CAPTIONS or LANGUAGE_UNAVAILABLE), and that access problems surface as errors. Only auth and rate-limit behavior are unstated.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core purpose and packed with useful detail in a few dense semicolon-joined clauses. Nothing is wasted, though the single run-on sentence is harder to scan than separated bullets would be.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 4-parameter read tool with an output schema and no annotations, the description covers purpose, language selection, pagination, and both failure modes. An agent has everything needed to call it correctly and interpret the response.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description largely restates what the schema already documents (lang omission behavior, pagination with startSegment), adding no syntax or format details beyond it.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Get YouTube video transcript/captions') plus the distinguishing scope (manual or auto-generated, with timestamps). It also names the sibling get_transcript_languages, so an agent can route between the two without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explains the selection rule for 'lang' (provide a code, omit for first manual track else first auto-generated) and points to get_transcript_languages for valid codes. It gives clear context but no explicit exclusions against the other siblings (get_video_info, get_video_comments).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_youtubeA

Search YouTube videos by query. Returns up to 50 results with title, channel, views, duration, and URL. Supports filtering by uploadDate (today/week/month/year) and videoDuration (short/medium/long), and sorting by relevance, date, viewCount, or rating. Served by the provider selected with YT_PROVIDER; with the default innertube provider some options are approximated and reported in warnings.

ParametersJSON Schema
NameRequiredDescriptionDefault
queryYesSearch query string
sortByNoSort order: 'relevance' (default), 'date', 'viewCount' (most popular), or 'rating'. With the default innertube provider, 'date' keeps relevance order and 'rating' sorts by popularity, each with a warning; the api provider applies all four exactly.relevance
maxResultsNoMaximum number of results to return (1-50)
uploadDateNoFilter by upload date: 'any', 'hour', 'today', 'week', 'month', 'year'. With the innertube provider, 'hour' is applied as 'today' with a warning.any
videoDurationNoFilter by duration: 'any', 'short', 'medium', 'long'. innertube: <3min, 3-20min, >20min. api: <4min, 4-20min, >20minany

Output Schema

ParametersJSON Schema
NameRequiredDescription
queryYes
sortByYes
resultsYes
warningsNoRequested options that YouTube search could not apply exactly
uploadDateYes
resultCountYes
videoDurationYes

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations exist, so the description carries the full burden and largely meets it: it discloses the 50-result cap, provider dependence via YT_PROVIDER, and importantly that the default innertube provider approximates some options and emits warnings while the api provider applies them exactly. It omits auth requirements and rate limits, but the degradation caveats are the most valuable trait an agent needs here.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three dense sentences, front-loaded with the core action and return shape before the parameter summary and the provider caveat. The enumeration of return fields (title, channel, views, duration, URL) slightly duplicates the output schema, but overall there is little waste.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return-shape explanation is optional, yet the description covers filtering, sorting, provider-dependent fidelity, and warnings, which is ample for a 5-parameter tool. Minor gap: 'Returns up to 50 results' can be read as the default result count when the schema states maxResults defaults to 10.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents query, sortBy, maxResults, uploadDate, and videoDuration with enum meanings and provider caveats. The description restates the same filter and sort options without adding syntax or format detail beyond the schema, which is the expected baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Search YouTube videos by query') with the discovery scope made explicit. It is immediately distinguishable from siblings like get_video_info, get_video_comments, and get_video_transcript, which all operate on a known video rather than searching.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The filtering, sorting, and provider context imply when the tool is useful, but the description never states usage conditions relative to alternatives (e.g. 'use get_video_info once you have a video ID'). Guidance is inferable rather than explicit, and no exclusions are given.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 5 tool updatesv1.1.0
    • Addedget_server_info
    • Changedget_transcript_languages1 field changed
      • addedOutput schema / properties / available / description
        Added value: +"false only when the video is playable and genuinely has no caption tracks; access problems are returned as errors"
    • Changedget_video_info14 fields changed
      • changedOutput schema / properties / channelId / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • changedOutput schema / properties / channelName / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • changedOutput schema / properties / commentCount / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • addedOutput schema / properties / description / description
        Added value: +"null when YouTube did not provide a description; empty string when it is empty"
      • changedOutput schema / properties / description / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • addedOutput schema / properties / duration / description
        Added value: +"Human-readable duration, e.g. '1m 21s'; null when unknown or live"
      • changedOutput schema / properties / duration / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • addedOutput schema / properties / durationSeconds
        Added value: +{
        +  "anyOf": [
        +    {
        +      "maximum": 9007199254740991,
        +      "minimum": 1,
        +      "type": "integer"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "description": "Duration in seconds; null when unknown or live"
        +}
      • changedOutput schema / properties / likeCount / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • changedOutput schema / properties / thumbnailUrl / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • addedOutput schema / properties / uploadedAt / description
        Added value: +"innertube provider: display text such as 'Sep 14, 2017' or 'Premiered May 27, 2020'. api provider: ISO 8601 timestamp"
      • changedOutput schema / properties / uploadedAt / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • changedOutput schema / properties / viewCount / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • changedOutput schema / required
        Previous value: -[
        -  "videoId",
        -  "title",
        -  "description",
        -  "channelName",
        -  "channelId",
        -  "uploadedAt",
        -  "duration",
        -  "viewCount",
        -  "likeCount",
        -  "commentCount",
        -  "tags",
        -  "thumbnailUrl"
        -]New value: +[
        +  "videoId",
        +  "title",
        +  "description",
        +  "channelName",
        +  "channelId",
        +  "uploadedAt",
        +  "duration",
        +  "durationSeconds",
        +  "viewCount",
        +  "likeCount",
        +  "commentCount",
        +  "tags",
        +  "thumbnailUrl"
        +]
    • Changedget_video_transcript15 fields changed
      • removedInput schema / properties / lang / default
        Removed value: -"en"
      • changedInput schema / properties / lang / description
        Previous value: -"Language code for the transcript (e.g., 'en', 'id', 'ja')"New value: +"Language code for the transcript (e.g., 'en', 'id', 'ja'). Omit to get the first manual track, or the first auto-generated one if there is no manual track. get_transcript_languages lists the codes."
      • changedInput schema / properties / maxSegments / description
        Previous value: -"Maximum number of transcript segments to return. 0 (default) returns all segments. Use with startSegment for pagination."New value: +"Maximum number of transcript segments to return. 0 (default) returns as many as the server allows per response (currently 500). Use with startSegment for pagination."
      • addedInput schema / properties / maxSegments / maximum
        Added value: +9007199254740991
      • changedInput schema / properties / maxSegments / type
        Previous value: -"number"New value: +"integer"
      • changedInput schema / properties / startSegment / description
        Previous value: -"Segment index to start from (0-based). Use with maxSegments to paginate through long transcripts."New value: +"Segment index to start from (0-based). Use nextStartSegment from the previous response to paginate through long transcripts."
      • addedInput schema / properties / startSegment / maximum
        Added value: +9007199254740991
      • changedInput schema / properties / startSegment / type
        Previous value: -"number"New value: +"integer"
      • addedOutput schema / properties / availableLanguages
        Added value: +{
        +  "description": "Language codes that do exist, when reason is LANGUAGE_UNAVAILABLE",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / isAutoGenerated
        Added value: +{
        +  "description": "Whether the returned track is YouTube's automatic (ASR) captions; null if unknown",
        +  "type": [
        +    "boolean",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / languageCode / description
        Added value: +"Language of the returned track; the requested code when unavailable; null when none was requested and the video has no captions"
      • changedOutput schema / properties / languageCode / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • addedOutput schema / properties / reason
        Added value: +{
        +  "description": "Why available is false",
        +  "enum": [
        +    "NO_CAPTIONS",
        +    "LANGUAGE_UNAVAILABLE"
        +  ],
        +  "type": "string"
        +}
      • removedOutput schema / properties / segments / items / properties / durationSeconds / anyOf
        Removed value: -[
        -  {
        -    "type": "number"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / segments / items / properties / durationSeconds / type
        Added value: +[
        +  "number",
        +  "null"
        +]
    • Changedsearch_youtube4 fields changed
      • changedInput schema / properties / sortBy / description
        Previous value: -"Sort order: 'relevance' (default), 'date' (newest), 'viewCount' (most popular), 'rating' (highest rated)"New value: +"Sort order: 'relevance' (default), 'date', 'viewCount' (most popular), or 'rating'. With the default innertube provider, 'date' keeps relevance order and 'rating' sorts by popularity, each with a warning; the api provider applies all four exactly."
      • changedInput schema / properties / uploadDate / description
        Previous value: -"Filter by upload date: 'any', 'hour', 'today', 'week', 'month', 'year'"New value: +"Filter by upload date: 'any', 'hour', 'today', 'week', 'month', 'year'. With the innertube provider, 'hour' is applied as 'today' with a warning."
      • changedInput schema / properties / videoDuration / description
        Previous value: -"Filter by duration: 'any', 'short' (<3min), 'medium' (3-20min), 'long' (>20min)"New value: +"Filter by duration: 'any', 'short', 'medium', 'long'. innertube: <3min, 3-20min, >20min. api: <4min, 4-20min, >20min"
      • addedOutput schema / properties / warnings
        Added value: +{
        +  "description": "Requested options that YouTube search could not apply exactly",
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "code": {
        +        "type": "string"
        +      },
        +      "message": {
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "code",
        +      "message"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
  2. 5 tool updatesv1.0.0
    • First observedget_transcript_languages
    • First observedget_video_comments
    • First observedget_video_info
    • First observedget_video_transcript
    • First observedsearch_youtube

TDQS

A4.1/5.0

Scored across 6 tools

Disambiguation5/5

Each tool targets a clearly distinct resource and action: video metadata, comments, transcript content, language discovery, search, and server info. There is no overlap in purpose, and the transcript/language split is explicitly signposted (call get_transcript_languages first).

Naming Consistency4/5

Most tools follow a get_<resource> pattern (get_video_info, get_video_comments, get_video_transcript, get_server_info), which is highly readable. Minor deviations exist: search_youtube uses a different verb form and get_transcript_languages breaks the get_video_ prefix used by its sibling transcript tool.

Tool Count5/5

Six tools is well-scoped for a read-oriented YouTube data server, with each tool earning its place and no redundant operations. It sits comfortably in the ideal 3-15 range.

Completeness4/5

The surface covers the core read workflows well: video metadata, comments, transcripts, language discovery, and search. Gaps exist around channel-level and playlist operations, but these are workable omissions for a video-centric read-only server.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

  • YouTube transcripts, search, channel browsing, and playlists for AI agents via MCP.

  • An MCP server that gives any LLM or agent clean YouTube transcripts on demand: a single video, a whole channel, or a playlist, plus AI cleanup of auto-generated captions. API-key auth, credit-based, same backend as the public v1 API. Get a free API key with 25 free credits at youtubetranscriptdownload.com/account.

  • Your agent needs to find video — which channels own a topic, which videos rank for a phrase, what exists in a given country and language. **What you can ask for** • "Which videos rank for 'rag pipeline tutorial' in the US this month?" • "Find channels publishing about MCP, sorted by relevance." • "What playlists cover this subject in Japanese?" • "Search videos uploaded this week only." **How to use it** Point any MCP client at https://mcp.aisa.one/youtube-search/mcp and sign in with OAuth — there is no key to create or paste. One search tool covering videos, channels and playlists, narrowed by country, language, upload date, duration and sort order. **It is also a door to the rest** The same login reaches 26 sources and 580+ operations. Find the video here, then ask the same agent what the channel's site traffic is or what the same phrase does in Google — without adding a second server. **What it costs** Finding and inspecting an operation is free. Running one is billed per call at API prices, with no seat and no monthly minimum, and every call takes max_price_usd so an agent cannot overspend by accident. **Where else it reaches** https://mcp.aisa.one/social/mcp for X plus Instagram, Reddit, Pinterest and YouTube; https://mcp.aisa.one/gtm/mcp for those plus Similarweb and Apollo.

  • YouTube transcripts, search, channel/playlist listings and upload tracking for AI agents.

Related MCP Servers

  • A
    license
    B
    quality
    D
    maintenance
    An MCP server that provides AI assistants with powerful tools to interact with YouTube, including video searching, transcript extraction, comment retrieval, and more.
    8
    19
    Apache 2.0
  • A
    license
    Not graded
    quality
    Not graded
    maintenance
    An MCP server that provides YouTube data access without API keys or quotas. It enables agents to search videos, retrieve transcripts and metadata, and perform full-text search across cached content for AI context retrieval.
    3 npm
    -