YouTube Transcript MCP

YouTube Transcript MCP

Fetches YouTube video transcripts, using free captions when available and falling back to Gemini-based transcription for missing or broken captions.

Category
Visit Server

README

YouTube Transcript MCP

Search YouTube, then get transcripts, without paying for ones you could have had free.

Most YouTube videos already have captions. This gets those first, checks they're any good, and only pays a model to transcribe the video when they're missing or broken. A typical call costs nothing.

You need nothing to start. A key is only for the fallback.

{
  "mcpServers": {
    "yt-transcript": {
      "command": "npx",
      "args": ["-y", "yt-transcript-gemini-mcp"],
      "env": { "AI_GATEWAY_API_KEY": "paste-your-key-here" }
    }
  }
}

What you get back

**Me at the zoo** by jawed, 19s.
Source: human-written captions (en). Free, no model call.

All right, so here we are in front of the elephants...

The source line is the point. A human-written caption track and a machine transcription are different kinds of evidence, and a transcript that doesn't say which it is can't be judged.

Search

Search and filter in one call, free, no API key. The filters combine, which is the point:

a video about rust async with over 50,000 views, from a channel with over 80,000 subscribers, longer than a minute

**3** result(s) for **rust async**.
Read 19 result(s), 3 channel lookup(s). Free, no API key.

- **Async Rust explained in 20 minutes**
  `wXtngLBkK4Q` · 62,742 views · 2 months ago · 19:15
  Let's Get Rusty (172,000 subscribers)
Filter Cost Notes
minViews / maxViews free Comes back with the search results
publishedWithinDays free Coarse; see below
minDurationSeconds / maxDurationSeconds free 60 excludes most Shorts
minSubscribers one request per channel Runs last, after the free filters have cut the set. Each channel is looked up once however many of its videos survive

The date filter is approximate, and the tool says so every time you use it. YouTube reports "3 weeks ago", not a date. Anything posted inside the current month reads as weeks at best, so "the past month" is honest and "since the 14th" is not.

The result tells you how many raw results were read and how many channel lookups it cost, so a filter that had to work hard is visible rather than silent. If it returns fewer than you asked for, raise maxPages.

Several videos at once

youtube_transcripts takes up to 20 URLs or ids and runs them in parallel. One failure doesn't stop the rest.

The paid fallback is OFF by default here, which is the opposite of the single-video tool. Twenty videos is twenty bills, and an agent handed a search result will pass the whole list. allowPaid: true when you mean it.

Three sources, in order

1. The video's own captions. Free. Fetched through YouTube's InnerTube endpoint, parsed, and checked before you get them.

2. Gemini reads the URL. Billed. The watch URL goes straight to the model; there's no download and no upload step. Needs a key.

3. yt-dlp. Free, if you have it installed. Last because it's the only step with a binary to install and keep current.

That order is deliberate and it isn't what the research recommended. Every write-up on this puts yt-dlp second, because it's the traditional answer. But Gemini needs no binary, no PATH, and no maintenance against a target that actively changes to break you, so it earns the middle slot.

Run it locally

YouTube refuses most datacentre addresses outright. The caption path works from a home connection and fails from a cloud host, which quietly pushes every request onto the paid fallback and turns a free tool into a billed one.

npx in your own MCP config is exactly right. A hosted deployment is the case to think twice about.

What it checks before handing captions over

All local string work, so the checks cost nothing. That's the design: the expensive decision is whether to pay, and deciding shouldn't itself cost money.

Check Rejects
Coverage A track that stops a third of the way in. The text that IS there reads fine, which is what makes this the failure people miss
Language A German track when you asked for English. Returning the wrong language silently is worse than returning nothing
Repetition A stuck recogniser looping one phrase. Only applied to auto-generated tracks: a human track that repeats is a chorus
Punctuation Auto-captions with no full stops or capitals. Sent for repair rather than rejected

Note: the repetition check ignoring human tracks is not a nicety. Measured on a pop video, 56% of the phrasing repeated and the captions were perfect. Applying that check to a manual track rejects every chorus ever written.

Repairing beats replacing

When a video has auto-captions and nothing better, the words are usually right. What's missing is punctuation, casing and paragraphs. Sending that text back as text costs a fraction of sending the video, because video is billed by sampled frames and audio seconds while text is billed by the word.

Measured on the same 19-second video:

cost
Transcribe the video $0.0028
Repair the captions $0.0006

On by default. YT_TRANSCRIPT_REPAIR=false turns it off and you get the raw unpunctuated track instead.

Two things that cost money for no reason

Both found by measuring, and both the opposite of what they look like.

Thinking is off, and that's most of the saving. Transcription has nothing to reason about, but the model reasons anyway: 438 of 503 output tokens on one call, 1,097 of 1,146 on another. Output is billed at five times input, so that was 96% of the bill spent deliberating over where to put full stops. Setting the thinking budget to zero gives identical text for a twentieth of the tokens.

Flex tier is a false economy here, so it's off. Flex halves both rates, which sounds like free money. It also ignores the thinking budget. Measured twice on the same prompt: standard with thinking off returned 33 output tokens; flex with identical options returned 604 and 650, nearly all reasoning. Half the rate on nineteen times the tokens is about nine times the bill. YT_TRANSCRIPT_FLEX=true if a future gateway release honours the setting.

Getting a key

Only needed for the fallback. Captions work without one.

Vercel AI Gateway (vercel.com/docs/ai-gateway) is the one to get. gemini-3.6-flash resolves there.

Google AI Studio (aistudio.google.com/apikey) also works, with a caveat worth knowing: on the key tested here, gemini-3.6-flash returned 404 while every other model resolved. If yours does the same, set YT_TRANSCRIPT_MODEL=gemini-3.5-flash, which works and transcribes fine.

Treat either like a password.

About money

Captions are free and most videos have them. The bill only starts when they don't.

Set a budget anyway. Vercel and Google Cloud both let you set a spending limit and an alert. Two minutes each, and it's the difference between a surprise and a number you chose.

This server caps transcription at 30 per hour and 180 minutes per video, both on by default, because an agent looping over a playlist is the shape that runs up a bill nobody agreed to. Captions are never capped.

No liability for spend. Free software, as-is, MIT. You are responsible for your own API usage and any charges Google or Vercel bill you, including charges caused by bugs, misconfiguration, runaway agents, or anything else. Neither Luke Rhodes nor Fledgeling is liable for your spending. Set a budget.

Settings

All optional. The server runs with none of them, captions only.

Setting Default What it does
AI_GATEWAY_API_KEY Vercel AI Gateway. Preferred, because gemini-3.6-flash resolves there
GEMINI_API_KEY AI Studio key. GOOGLE_API_KEY works too
YT_TRANSCRIPT_MODEL gemini-3.6-flash Which model transcribes. The gateway prefix is added for you
YT_TRANSCRIPT_REPAIR true Repair auto-captions with a text call instead of re-transcribing
YT_TRANSCRIPT_FLEX false Vercel's flex tier. Off because it ignores the thinking budget; see above
YT_TRANSCRIPT_MAX_PER_HOUR 30 Transcriptions per rolling hour. 0 removes the cap
YT_TRANSCRIPT_MAX_MINUTES 180 Longest video the paid path will accept
YT_TRANSCRIPT_TIMEOUT_MS 600000 How long to wait on a model call
YT_DLP_PATH yt-dlp Where yt-dlp lives, if it isn't on PATH

Tools

youtube_search searches and filters. Free, no key.

youtube_transcript takes a URL or a bare video id, plus optional languages, timestamps, and allowPaid. Set allowPaid: false to get captions or nothing, which is right when cost matters more than coverage.

youtube_transcripts does up to 20 at once, in parallel, with the paid fallback off unless you ask for it.

youtube_transcript_doctor says what actually works right now: whether captions are reachable from this address, whether a key is configured, whether yt-dlp is installed. Free.

What it doesn't do

Timestamps only survive the caption path. A model transcription has no timings, so timestamps: true is quietly ignored there.

It doesn't work on private or unlisted videos, through any of the three paths.

It doesn't evade blocks. No proxy rotation, no token harvesting. On a refusal it says so and moves to the next source. Working around a bot check is against YouTube's terms and a treadmill nobody wins.

Things that surprised me

Written down because they contradict what's widely published, and they'll drift again.

Watch-page caption URLs are dead. They return HTTP 200 with zero bytes, in every format, with every client parameter. That looks exactly like a video with no captions unless you check the length.

Search and captions need different InnerTube clients. IOS serves captions; its search response carries only videoId, with no view counts, dates or channel. WEB serves a full search result but its caption URLs return nothing. So the two paths use different clients, and neither is a typo.

The subscriber count on a channel page is not subscriberCountText. A channel response carries several of those and none of them is the channel's own: they're the recommended-channel sidebar. Measured on a channel with 4.24M subscribers, the two values present were 466 thousand and 49 thousand. The real figure is in the page header's metadata rows. An early version of this server reported the sidebar number, which is wrong and entirely plausible.

IOS is the InnerTube client that works for captions. yt-dlp's PO Token Guide lists tv, android_vr and web_embedded as the ones needing no token. Measured on 2 August 2026, those return LOGIN_REQUIRED, LOGIN_REQUIRED and ERROR. IOS answers with a usable caption list. The guide may describe a different request context, or it may have drifted.

The client list is ordered rather than fixed, because this is an undocumented surface and a second client is a cheaper recovery than a release.

For developers

TypeScript, ESM, Node 20.11 or newer. FastMCP over stdio, Vercel AI SDK v7, Zod at every boundary, exactOptionalPropertyTypes on, no any.

npm install
npm run gate     # typecheck, lint, test, build

Who made this

I'm Luke Rhodes, a founder and engineer building Fledgeling. I spent years shipping developer tools and got tired of proprietary formats and slow editors, so Fledgeling is the opposite of that: fast software built from scratch, your work in plain text you own, and AI as a collaborator you can always overrule. The human is always the editor of record.

I'm also co-founder of Diolog with Amy Benson, building investor-relations software for listed companies and the retail investors following them.

Three related things

Media Gen Pro generates images and video. Eight image models and four video ones behind one call, with the server reading your prompt to pick which. Returns file paths, not megabytes of base64.

npx -y media-gen-pro-mcp

Google Search MCP does the looking: Google search through the Gemini API, returning the answer, the real source URLs, and the queries the model actually ran.

Dossier runs proper deep research: several backends on the same question at once, then checks the citations resolve and flags where the backends disagree. The architecture of this server came out of a Dossier panel, and two of its recommendations turned out to be wrong when measured, which is exactly why the merge tells you which claims only one backend made.

Licence

MIT. Use it, fork it, ship it.

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured