Skip to main content

yt-transcript-mcp

MIT Python 3.11+ MCP PyPI yt-transcript MCP server

YouTube transcripts as token-efficient AI context. One fetch, cached forever.

Agent-first: returns structured JSON by default. Zero dependencies on yt-dlp, ffmpeg, or API keys.

Works with Claude Desktop, ChatGPT Desktop, Cursor, Windsurf, and any MCP client.


Why?

When AI browses YouTube for a transcript, it processes the entire page: navigation, ads, recommendations, scripts. That's 75,000-150,000 tokens of noise to extract maybe 6,000 tokens of actual content.

This tool fetches only the transcript.

Tokens Speed Repeat queries
AI browses YouTube 75-150k 20-90s Same cost every time
ytfetch-mcp 6-12k 1-3s Instant (cached)

~50 KB per video in cache. A year of daily use stays under 120 MB.


Demo

You say:

Fetch the transcript from https://www.youtube.com/watch?v=dQw4w9WgXcQ

Default response (compact JSON, segments only):

{
  "is_error": false,
  "video_id": "dQw4w9WgXcQ",
  "title": "Never Gonna Give You Up",
  "channel": "Rick Astley",
  "published": "2009-10-25",
  "language": "en",
  "caption_type": "manual",
  "segment_count": 56,
  "transcript_duration_seconds": 213.5,
  "content_hash": "a1b2c3...",
  "cache_hit": false,
  "warnings": [],
  "segments": [
    {"text": "We're no strangers to love", "start": 18.0, "end": 21.4},
    {"text": "You know the rules and so do I", "start": 21.4, "end": 24.8}
  ]
}

Structured, machine-readable, one transcript representation. No HTML, no noise, no wasted tokens.


Install

One line. No git clone needed.

Claude Desktop

Add to ~/Library/Application Support/Claude/claude_desktop_config.json:

{
  "mcpServers": {
    "yt-transcript": {
      "command": "uvx",
      "args": ["ytfetch-mcp"]
    }
  }
}

Restart Claude Desktop. Done.

ChatGPT Desktop

Same config in your Codex MCP settings, or add manually:

Field Value
Command uvx (or full path: ~/.local/bin/uvx)
Arguments ytfetch-mcp

Tip: Find your uvx path with which uvx. Restart the app after config changes.

Cursor / Windsurf / VS Code

Paste the same JSON block into your MCP server config.

Requires

uv (includes uvx): curl -LsSf https://astral.sh/uv/install.sh | sh


Parameters

Parameter Description Default
url YouTube URL (required, any format)
languages Language codes in priority order sv,en
output segments, text, or both segments
format json or markdown json
include_timestamps true for [HH:MM:SS] per line in text output false
title Override title
channel Override channel
published Override date (YYYY-MM-DD)
bypass_cache true to force fresh fetch false

Output modes

output What you get
segments (default) Array of {text, start, end} for structured consumption
text Single readable string (clean or timestamped)
both Both representations

Markdown format (format=markdown) always renders readable text regardless of output mode.


How it works

  • Fetches transcripts directly from YouTube's InnerTube API. No yt-dlp, ffmpeg, browser, Node.js, or API key.
  • Tries several YouTube client identities (android_vr, ios, android) and moves to the next only when one is bot-checked or needs a Proof-of-Origin token. A client that was blocked is skipped for 10 minutes.
  • Retries only transient failures (HTTP 429, 5xx, timeouts) and never repeats a permanent one.

This relies on YouTube's unofficial client API, so it can need an update when YouTube changes it.


Error handling

Failures are MCP tool errors (isError: true). The result's text is a structured payload with a machine-readable code and a retryable flag, so agents can branch automatically:

{
  "is_error": true,
  "error_code": "VIDEO_UNAVAILABLE",
  "error_message": "Video is unavailable, private, or removed.",
  "retryable": false,
  "retry_count": 0
}
Error code Meaning Retryable
INVALID_URL Not a YouTube URL or malformed video ID No
TRANSCRIPT_NOT_AVAILABLE Transcripts disabled for this video No
LANGUAGE_NOT_AVAILABLE Reserved, not currently returned: if none of your languages exist, another available track is used and LANGUAGE_FALLBACK is warned No
VIDEO_UNAVAILABLE Video unavailable, private, age-restricted, or unplayable No
YOUTUBE_IP_BLOCKED YouTube bot check on every client tried (often specific to the video) No
PO_TOKEN_REQUIRED Every client tried needs a Proof-of-Origin token No
RATE_LIMITED YouTube rate limit (429), server error, or timeout. Also used for unclassified failures: check retryable Yes, unless retryable is false

Provenance

Every response includes provenance so you know exactly where the data comes from:

  • caption_type: manual, auto-generated, or unknown
  • metadata_sources: per-field tracking ({"title": "oembed", "published": "pytubefix"})
  • content_hash: SHA256 of the segments array for reproducibility
  • warnings: AUTO_GENERATED (speech recognition, may contain errors), LANGUAGE_FALLBACK (got a different language than requested), METADATA_FETCH_FAILED (some metadata unavailable), CLIENT_FALLBACK (an earlier YouTube client was blocked and a later one served the request)

Logging

The server logs to stderr (stdout carries the MCP protocol). Default level is WARNING, which includes client fallbacks and retries. Set YTFETCH_LOG_LEVEL=INFO to also log which YouTube client served each fetch.


Cache

Transcripts cached locally in ~/.cache/yt-transcript/. Keyed by video ID + language preference. Second fetch: instant, zero network.

  • Cache entries validated on load (version, types, segments, metadata)
  • Legacy or corrupted entries silently skipped
  • Cache write failures never block transcript delivery

CLI

Also works standalone, no MCP client needed:

uvx ytfetch-mcp  # starts the MCP server
uv run yt_transcript.py https://youtu.be/ABC123  # CLI mode, saves .md file

CLI flags: --date, --title, --channel, --lang, --out, --no-clean, --no-cache.


Roadmap

  • Summary mode -- condensed output for lower token cost
  • Token budget (max_tokens) -- fit any context window
  • Batch URLs -- multiple videos in one call
  • Chapter/topic filtering -- return only relevant sections
  • Remote HTTP transport -- expose as streamable HTTP MCP server
  • Schema.org metadata -- replace pytubefix for publish date
  • MCP outputSchema / structured content
  • PO-token fallback -- keep working if YouTube enforces tokens on every client

Support

If this saves you time or tokens:

Ko-fi GitHub Sponsors


MIT \u00a9 Bj\u00f6rn Walther

Release files for ytfetch-mcp 1.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ytfetch-mcp 1.3.0
File Size Uploaded
ytfetch_mcp-1.3.0.tar.gz 50.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for ytfetch-mcp 1.3.0
File Interpreter ABI Platform
ytfetch_mcp-1.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 73.0 kB

Release files / ytfetch_mcp-1.3.0.tar.gz

Download URL ytfetch_mcp-1.3.0.tar.gz
Size 50.6 kB
Tags Source
SHA-256 checksum
How to use checksums
936814182af9acd608b66d2c08025b1f147622b391a397f8b851fb15a2ec20a7
BLAKE2b-256 checksum
How to use checksums
5de563d8bf62ce98eb80dfaee2ac24943f487fde27b727a9c357185acecd195a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 19, 2026.

Transparency log

Release files / ytfetch_mcp-1.3.0-py3-none-any.whl

Download URL ytfetch_mcp-1.3.0-py3-none-any.whl
Size 22.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6735fb48be2299c049f9759a660d5ebbdea85c9e0181f60387abf6846880654c
BLAKE2b-256 checksum
How to use checksums
931112c0641424944b49c4ff5dbfadf831b843b4aab7b45ece2bd3ef5b607fa9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 19, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.3.0 This release

2 release files

1.2.0

2 release files

1.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page