Skip to main content
Glama
artemchuikin

YouTube Transcript & Search MCP Server

README.md
<!-- mcp-name: com.transcriptout/youtube-transcript-and-youtube-search -->

<p align="center">
  <a href="https://transcriptout.com">
    <img src="public/brand/logo-512.png" width="120" height="120" alt="TranscriptOut" />
  </a>
</p>

<h1 align="center">YouTube Transcript &amp; Search MCP Server</h1>

<p align="center">
  <b>Let your AI agent read YouTube.</b><br/>
  Transcripts in five formats, native video and channel search, channel and playlist listings,
  and background jobs that deliver up to 4,000 transcripts at a time. 14 tools behind one hosted
  endpoint. Nothing runs on your machine.
</p>

<p align="center">
  <a href="https://cursor.com/en/install-mcp?name=transcriptout&config=eyJ1cmwiOiJodHRwczovL2FwaS50cmFuc2NyaXB0b3V0LmNvbS9tY3AifQ=="><img alt="Install in Cursor" src="https://img.shields.io/badge/Cursor-Install_MCP-000000?style=for-the-badge&logo=cursor&logoColor=white"/></a>
  <a href="https://insiders.vscode.dev/redirect?url=vscode%3Amcp%2Finstall%3F%7B%22name%22%3A%22transcriptout%22%2C%22url%22%3A%22https%3A%2F%2Fapi.transcriptout.com%2Fmcp%22%7D"><img alt="Install in VS Code" src="https://img.shields.io/badge/VS_Code-Install_MCP-0098FF?style=for-the-badge&logo=visualstudiocode&logoColor=white"/></a>
</p>

<p align="center">
  <a href="https://transcriptout.com"><img src="https://img.shields.io/badge/Website-transcriptout.com-FF3B00?style=for-the-badge" alt="Website"/></a>
  <a href="https://transcriptout.com/docs"><img src="https://img.shields.io/badge/Docs-API_Reference-06B6D4?style=for-the-badge&logo=readthedocs&logoColor=white" alt="Docs"/></a>
  <a href="./LICENSE"><img src="https://img.shields.io/badge/License-MIT-4CAF50?style=for-the-badge" alt="MIT License"/></a>
</p>

<p align="center">
  <a href="#-why">Why</a> ·
  <a href="#-quick-start">Quick start</a> ·
  <a href="#-the-14-tools">Tools</a> ·
  <a href="#-install-in-your-client">Install</a> ·
  <a href="#-recipes">Recipes</a> ·
  <a href="#-pricing-and-limits">Pricing</a> ·
  <a href="#-when-a-call-fails">Errors</a>
</p>

---

## 🎬 Why

Everyone who works with an agent has run this exchange at least once.

```txt
You:   Summarize this. https://www.youtube.com/watch?v=kCc8FmEb1nY
Agent: I'm not able to watch videos. If you paste the transcript here, I'll gladly help!
```

The transcript is precisely the thing the agent cannot get on its own. With this server
connected, the same message simply resolves.

```txt
You:   Summarize this. https://www.youtube.com/watch?v=kCc8FmEb1nY
Agent: → get_transcript(video="kCc8FmEb1nY", video_metadata=true)      1 credit

       That's "Let's build GPT: from scratch, in code, spelled out" by Andrej
       Karpathy, 1:56:20. He starts from an empty file and a bigram model,
       derives self-attention step by step, and ends with a working GPT that...
```

Reading one video is rarely where the job ends. Here is how the three ways of getting YouTube
data into an agent actually compare.

|                          | This server | Local yt-dlp / scraper MCP | Google YouTube Data API |
| ------------------------ | ----------- | -------------------------- | ----------------------- |
| Transcripts              | ✅ any public video, 5 formats | ⚠️ blocked on datacenter IPs, breaks when YouTube changes markup | ❌ not served at all |
| Setup                    | ✅ a URL and an API key | ❌ local install, binaries to keep alive | ❌ Cloud project, OAuth consent screens |
| YouTube search           | ✅ native, 1 credit per page | ❌ | ⚠️ 100 quota units per search |
| Channels & playlists     | ✅ 100 videos/page, or 500 bare IDs | ❌ one video at a time | ⚠️ quota-metered per item |
| Bulk transcripts         | ✅ 4,000 per background job | ❌ | ❌ |
| RAG-ready chunking       | ✅ 20-5,000 chars, word-level timestamps | ❌ | ❌ |
| When YouTube changes     | ✅ fixed server-side, nothing to update | ❌ you patch and redeploy | ✅ |
| Failed calls             | ✅ credits refund themselves | ❌ your retry logic | ⚠️ quota spent anyway |

---

## ⚡ Quick start

**1. Get an API key.** Sign up at [transcriptout.com](https://transcriptout.com) and create a key
in the [dashboard](https://transcriptout.com/dashboard). New accounts receive 100 free credits and
no card is asked. Keys start with `sk_` and are shown once.

**2. Point your client at the server.** It speaks streamable HTTP and authenticates with one
Bearer header.

```json
{
  "mcpServers": {
    "transcriptout": {
      "url": "https://api.transcriptout.com/mcp",
      "headers": { "Authorization": "Bearer YOUR_API_KEY" }
    }
  }
}
```

One-click buttons for Cursor and VS Code sit at the top of this page. Exact snippets for the rest
live under [Install in your client](#-install-in-your-client).

**3. Paste a link.**

```txt
Summarize this talk and pull the three strongest quotes.
https://www.youtube.com/watch?v=dQw4w9WgXcQ
```

The agent picks `get_transcript` on its own, reads the timed text and answers from it. Every
response carries an `X-Credits-Remaining` header, so the budget stays in view the whole session.

---

## 🧰 The 14 tools

All 14 tools are exposed automatically once you connect. **Most calls cost 1 credit.** Credits
are refunded automatically when a call fails before reaching YouTube (validation errors, rate
limits, our own capacity), so you pay for answers, not for failures. A definitive "this video has no
captions" is an answer and is billed like one.

### 1. `get_transcript` · 1 credit

Fetch the transcript of any YouTube video. `format=text` (default) returns plain readable text,
cheapest for a model to reason over, and `format=json` returns timed segments.

| Parameter        | Type    | Default      | Description                                                    |
| ---------------- | ------- | ------------ | -------------------------------------------------------------- |
| `video`          | string  | **required** | YouTube URL (full or short) or 11-char video ID                |
| `lang`           | string  | `"en"`       | Language code of the track (`en`, `de`, ...)                   |
| `format`         | string  | `"text"`     | `"text"` (plain text), `"json"` (segments with `start`/`duration` in seconds), `"srt"`/`"vtt"` (subtitle file body), `"srv3"` (raw YouTube XML) |
| `kind`           | string  | auto-detect  | `"manual"` or `"auto"`. Left out, a manual track wins and auto is the fallback |
| `segment`        | integer | see below    | Max characters per segment. 500-1500 makes RAG-ready chunks    |
| `video_metadata` | boolean | `false`      | Add title, channel, duration and views in the SAME call, same 1 credit |

Left out, `segment` cuts auto-generated tracks into ~180-character segments and returns manual
tracks exactly as their author broke them. Pass it whenever you need one size regardless of which
track answers.

**Example output (`format=json`):**

```json
{
  "video_id": "dQw4w9WgXcQ",
  "language": "en",
  "kind": "manual",
  "transcript": [
    { "text": "Never gonna give you up", "start": 18.0, "duration": 4.12 },
    { "text": "Never gonna let you down", "start": 22.12, "duration": 3.85 }
  ]
}
```

> `srt` and `vtt` come back as complete subtitle file bodies, ready to be written to disk by the
> agent. `srv3` is the raw source XML and does not combine with `segment`.

### 2. `get_video_info` · 1 credit

Metadata for one video (title, channel, duration, views, thumbnails) plus the list of available
transcript languages, WITHOUT downloading the subtitles.

| Parameter | Type   | Default      | Description                |
| --------- | ------ | ------------ | -------------------------- |
| `id`      | string | **required** | YouTube video ID or URL    |

> **Credit hygiene:** if you are going to fetch the transcript anyway, call `get_transcript` with
> `video_metadata=true` instead. It returns both for one credit where these are two calls and two.

### 3. `search_youtube` · 1 credit/page

Search YouTube for videos or channels. Paginate with `next_page_token`. `has_more` tells you
whether another page exists.

| Parameter         | Type    | Default   | Description                          |
| ----------------- | ------- | --------- | ------------------------------------ |
| `q`               | string  | required* | Search query (*unless paginating)    |
| `type`            | string  | `"video"` | `"video"` or `"channel"`             |
| `limit`           | integer | `20`      | Results per page, 1-50               |
| `next_page_token` | string  |           | Token from a previous result         |

### 4. `list_channel_videos` · 1 credit/page

List videos from a channel's Videos tab, newest first. Accepts an `@handle`, a channel name, a
`UC...` channel ID or a channel URL.

| Parameter         | Type    | Default   | Description                                        |
| ----------------- | ------- | --------- | -------------------------------------------------- |
| `name`            | string  | required* | `@handle`, channel name, `UC...` ID or URL         |
| `limit`           | integer | `100`     | Page size, up to 500 with `ids_only`               |
| `ids_only`        | boolean | `false`   | Return just `video_ids[]`, up to 500 per page      |
| `next_page_token` | string  |           | Token from a previous result                       |

> `ids_only=true` is the cheap way to feed `submit_transcripts_job`.

### 5. `search_channel_videos` · 1 credit/page

Search inside one channel using YouTube's native relevance search. A result whose title lacks the
query word is normal. Results are ranked by relevance, not by substring.

| Parameter         | Type    | Default   | Description                          |
| ----------------- | ------- | --------- | ------------------------------------ |
| `name`            | string  | required  | `@handle`, channel name, `UC...` ID or URL |
| `q`               | string  | required  | Query to search within the channel   |
| `limit`           | integer | `30`      | Results per page, 1-100              |
| `next_page_token` | string  |           | Pagination token                     |

### 6. `latest_channel_videos` · 1 credit

The ~15 most recent videos of a channel from its RSS feed. The fastest and cheapest way to check
what a channel published recently.

| Parameter | Type   | Default      | Description                                |
| --------- | ------ | ------------ | ------------------------------------------ |
| `name`    | string | **required** | `@handle`, channel name, `UC...` ID or URL |

### 7. `list_playlist_videos` · 1 credit/page

Every video of a playlist in playlist order. Accepts a `PL...` playlist ID or a URL with `list=`.

| Parameter         | Type    | Default   | Description                                   |
| ----------------- | ------- | --------- | --------------------------------------------- |
| `id`              | string  | required* | Playlist ID or URL                            |
| `limit`           | integer | `100`     | Page size, up to 500 with `ids_only`          |
| `ids_only`        | boolean | `false`   | Return just `video_ids[]`, up to 500 per page |
| `next_page_token` | string  |           | Pagination token                              |

### 8. `search_playlist_videos` · 1 credit

Find videos inside a playlist by a substring of the title (case-insensitive). YouTube has no native
playlist search, so this scans up to 500 playlist items. `truncated=true` means there may be more
matches beyond the scanned window.

| Parameter | Type    | Default  | Description                        |
| --------- | ------- | -------- | ---------------------------------- |
| `id`      | string  | required | Playlist ID or URL                 |
| `q`       | string  | required | Substring to match in video titles |
| `limit`   | integer | `30`     | Max matches, 1-100                 |

### 9. `submit_transcripts_job` · 1 credit per video

Queue transcripts for MANY videos at once (up to 4,000) and get a `job_id` back immediately. The
work continues in the background at your rate limit's pace. Use this instead of calling
`get_transcript` in a loop for more than a handful of videos.

| Parameter         | Type     | Default      | Description                                          |
| ----------------- | -------- | ------------ | ---------------------------------------------------- |
| `videos`          | string[] | **required** | Video IDs or URLs, up to 4,000. Duplicates collapse BEFORE billing |
| `lang`            | string   | `"en"`       | One language for the whole job                       |
| `format`          | string   | `"text"`     | `"text"`, `"json"`, `"srt"`, `"vtt"` or `"srv3"`, one for the whole job |
| `kind`            | string   | auto-detect  | `"manual"` or `"auto"`                               |
| `segment`         | integer  |              | One segment size for the whole job                   |
| `video_metadata`  | boolean  | `false`      | Metadata per video, no extra cost                    |
| `idempotency_key` | string   |              | Resubmitting the same list with the same key returns the SAME job, no double charge |

Requires a user key (`sk_...`). Credits are charged on submit and refunded per video when a video
could not be delivered through our fault.

### 10. `get_transcripts_job` · free

Progress of a batch job: status (`queued`/`running`/`done`/`cancelled`), how many videos are ready,
failed and pending. Polling a job you already paid for costs nothing.

### 11. `get_transcripts_results` · free

Finished transcripts from a batch job, in the order submitted, paged with `next_page_token`
(`limit` 1-500, default 100). Results appear as they are fetched, so you can read before the job is
done. Each entry is exactly what `get_transcript` returns for that video, plus its status.

### 12. `get_transcripts_result` · free

One video's result out of a batch job, by its video id, without paging through the whole result
set. A 404 means the job does not exist or this video has not finished yet, so check
`get_transcripts_job` before concluding anything.

| Parameter  | Type   | Default      | Description                                    |
| ---------- | ------ | ------------ | ---------------------------------------------- |
| `job_id`   | string | **required** | Job id from `submit_transcripts_job`           |
| `video_id` | string | **required** | One of the video ids the job was submitted with |

### 13. `cancel_transcripts_job` · free

Cancel a batch job. Credits are refunded ONLY for videos not started yet. Anything already fetched
stays in the results and stays paid for.

### 14. `get_credits` · free

The remaining credit balance of the key, with no parameters. The balance also rides in the
`X-Credits-Remaining` header of every response, but headers are invisible to the model, so the
number a user actually asks about needs a tool. Handy right before a large batch too, since the
batch charges 1 credit per video on submit.

---

## 🔌 Install in your client

The server is remote, so every install below is a config entry and nothing more. All of them want the same two values, the URL and the Bearer header from [Quick start](#-quick-start).

> **Worth doing once, a standing rule for your client**
>
> With this in your client's rules/instructions, pasting a YouTube link is enough and the word
> "transcript" never has to be typed:
>
> ```txt
> Whenever a YouTube link or video ID appears in my message, call the
> transcriptout get_transcript tool first and answer from the transcript,
> whether I asked for a summary, a quote, a translation or a question.
> ```

<details>
<summary><b>Install in Cursor (One-Click / Manual)</b></summary>

**One-Click Install:**

[![Install MCP Server](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en/install-mcp?name=transcriptout&config=eyJ1cmwiOiJodHRwczovL2FwaS50cmFuc2NyaXB0b3V0LmNvbS9tY3AifQ==)

After installing, open the server settings and add the `Authorization` header with your key.

**Manual configuration** (`~/.cursor/mcp.json`):

```json
{
  "mcpServers": {
    "transcriptout": {
      "url": "https://api.transcriptout.com/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_API_KEY"
      }
    }
  }
}
```

</details>

<details>
<summary><b>Install in Claude Code (CLI)</b></summary>

```sh
claude mcp add --transport http transcriptout https://api.transcriptout.com/mcp \
  --header "Authorization: Bearer YOUR_API_KEY"
```

</details>

<details>
<summary><b>Claude Desktop & Claude Web</b></summary>

Claude's custom connectors authenticate remote servers via OAuth, which TranscriptOut does not
offer yet (API keys only). On desktop, use **Claude Code** (see above), which supports API-key
headers. OAuth support is on the roadmap. Watch the [changelog](https://transcriptout.com/changelog).

</details>

<details>
<summary><b>Install in VS Code</b></summary>

[<img alt="Install in VS Code" src="https://img.shields.io/badge/VS_Code-Install_TranscriptOut_MCP-0098FF?style=for-the-badge&logo=visualstudiocode&logoColor=white">](https://insiders.vscode.dev/redirect?url=vscode%3Amcp%2Finstall%3F%7B%22name%22%3A%22transcriptout%22%2C%22url%22%3A%22https%3A%2F%2Fapi.transcriptout.com%2Fmcp%22%7D)

Or add this to VS Code user settings (`settings.json`):

```json
"mcp.servers": {
  "transcriptout": {
    "type": "http",
    "url": "https://api.transcriptout.com/mcp",
    "headers": {
      "Authorization": "Bearer YOUR_API_KEY"
    }
  }
}
```

</details>

<details>
<summary><b>Install in OpenAI Agent Builder</b></summary>

1. Create a new Agent
2. Under "Actions" or "Tools", add a new **MCP Server**
3. URL: `https://api.transcriptout.com/mcp`
4. Auth Type: **API Key**
5. Paste your API key from the [dashboard](https://transcriptout.com/dashboard)

</details>

<details>
<summary><b>Install in Windsurf</b></summary>

Add to `~/.codeium/windsurf/mcp_config.json`:

```json
{
  "mcpServers": {
    "transcriptout": {
      "serverUrl": "https://api.transcriptout.com/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_API_KEY"
      }
    }
  }
}
```

</details>

<details>
<summary><b>Install in Cline</b></summary>

```json
{
  "mcpServers": {
    "transcriptout": {
      "url": "https://api.transcriptout.com/mcp",
      "type": "streamableHttp",
      "headers": {
        "Authorization": "Bearer YOUR_API_KEY"
      }
    }
  }
}
```

</details>

<details>
<summary><b>Install in Zed</b></summary>

In Zed `settings.json`:

```json
{
  "context_servers": {
    "transcriptout": {
      "source": "remote",
      "url": "https://api.transcriptout.com/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_API_KEY"
      }
    }
  }
}
```

</details>

<details>
<summary><b>Install in Roo Code</b></summary>

```json
{
  "mcpServers": {
    "transcriptout": {
      "type": "streamable-http",
      "url": "https://api.transcriptout.com/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_API_KEY"
      }
    }
  }
}
```

</details>

<details>
<summary><b>Install in Amp</b></summary>

```sh
amp mcp add transcriptout https://api.transcriptout.com/mcp --header "Authorization: Bearer YOUR_API_KEY"
```

</details>

<details>
<summary><b>Install in Augment Code</b></summary>

In `settings.json` under `augment.advanced`:

```json
"augment.advanced": {
  "mcpServers": [
    {
      "name": "transcriptout",
      "url": "https://api.transcriptout.com/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_API_KEY"
      }
    }
  ]
}
```

</details>

<details>
<summary><b>Install in Kilo Code</b></summary>

In `.kilocode/mcp.json`:

```json
{
  "mcpServers": {
    "transcriptout": {
      "type": "streamable-http",
      "url": "https://api.transcriptout.com/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_API_KEY"
      }
    }
  }
}
```

</details>

<details>
<summary><b>Install in JetBrains AI Assistant</b></summary>

In Settings → Tools → AI Assistant → MCP:

```json
{
  "mcpServers": {
    "transcriptout": {
      "url": "https://api.transcriptout.com/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_API_KEY"
      }
    }
  }
}
```

</details>

<details>
<summary><b>Install in Gemini CLI</b></summary>

In `~/.gemini/settings.json`:

```json
{
  "mcpServers": {
    "transcriptout": {
      "httpUrl": "https://api.transcriptout.com/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_API_KEY"
      }
    }
  }
}
```

</details>

<details>
<summary><b>Install in Qwen Coder</b></summary>

In `~/.qwen/settings.json`:

```json
{
  "mcpServers": {
    "transcriptout": {
      "httpUrl": "https://api.transcriptout.com/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_API_KEY"
      }
    }
  }
}
```

</details>

<details>
<summary><b>Install in Google Antigravity</b></summary>

```json
{
  "mcpServers": {
    "transcriptout": {
      "serverUrl": "https://api.transcriptout.com/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_API_KEY"
      }
    }
  }
}
```

</details>

<details>
<summary><b>Install in Trae</b></summary>

```json
{
  "mcpServers": {
    "transcriptout": {
      "url": "https://api.transcriptout.com/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_API_KEY"
      }
    }
  }
}
```

</details>

<details>
<summary><b>Install in LM Studio</b></summary>

In `mcp.json`:

```json
{
  "mcpServers": {
    "transcriptout": {
      "url": "https://api.transcriptout.com/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_API_KEY"
      }
    }
  }
}
```

</details>

<details>
<summary><b>Install in Warp</b></summary>

In Settings → AI → MCP:

```json
{
  "transcriptout": {
    "url": "https://api.transcriptout.com/mcp",
    "headers": {
      "Authorization": "Bearer YOUR_API_KEY"
    }
  }
}
```

</details>

<details>
<summary><b>Install in Perplexity Desktop</b></summary>

In Settings → Connectors → Advanced:

```json
{
  "url": "https://api.transcriptout.com/mcp",
  "headers": {
    "Authorization": "Bearer YOUR_API_KEY"
  }
}
```

</details>

---

## 🧩 Install as an Agent Plugin

This repository root is a conformant **[Agent Plugins 1.0.0](https://agent-plugins.org/specification)**
package, the portable format supported by ChatGPT, Codex, Cursor, GitHub Copilot, Kiro and VS Code.
One install gets you the MCP server **and** a bundled `youtube` skill that teaches your agent when
to use each tool and how not to waste credits.

```text
plugin.json                # manifest
mcp.json                   # hosted MCP server, streamable-http
skills/youtube/SKILL.md    # when + how to use the 14 tools
```

**VS Code.** Command Palette → **Chat: Install Plugin From Source**, then paste:

```txt
https://github.com/artemchuikin/youtube-mcp
```

Or register a local clone in `settings.json`:

```json
"chat.pluginLocations": { "/absolute/path/to/youtube-mcp": true }
```

**Cursor.** **Customize** in the sidebar → find the plugin → **Install**. For a local clone:

```bash
git clone https://github.com/artemchuikin/youtube-mcp ~/.cursor/plugins/local/transcriptout
```

Then **Developer: Reload Window**.

**ChatGPT, Codex, GitHub Copilot, Kiro, any other client.** Point your client's plugin mechanism at
this repository, or at a local clone. Agent Plugins 1.0.0 standardizes the *package format*, not
installation, so each client owns its own install flow.

There are **no credentials in this package**, Agent Plugins 1.0.0 forbids embedded secrets. The
server authenticates with an API key you add in your client's MCP settings (see
[Keys and security](#-keys-and-security)). Verify the package yourself:

```bash
curl -sO https://agent-plugins.org/schemas/1.0.0/plugin.schema.json
curl -sO https://agent-plugins.org/schemas/1.0.0/mcp.schema.json
npx ajv-cli@5 validate --spec=draft2020 -s plugin.schema.json -d plugin.json
npx ajv-cli@5 validate --spec=draft2020 -s mcp.schema.json    -d mcp.json
```

---

## 🔑 Keys and security

- A key is shown once, at creation. Keep it in an environment variable and out of version control.
- A leaked key dies the moment you revoke it in the [dashboard](https://transcriptout.com/dashboard).
  An account holds up to 20 keys, so give every machine its own.
- Prefer to stay in the chat? An agent with the companion
  [youtube-skills](https://github.com/artemchuikin/youtube-skills) installed can open the account
  and mint the key for you, by email and a 6-digit code, no browser involved.
- There is no OAuth flow yet, so clients whose connectors cannot send a custom header (Claude
  Desktop and Claude Web) should go through Claude Code for now.

## 🐳 Run it locally

The hosted endpoint needs no install, but stdio-only clients, sandboxes and container platforms
sometimes want a process of their own. The repo carries one: `server.js` is a complete local MCP
server (official SDK, stdio transport) whose 14 tools each make one HTTPS call to the TranscriptOut
REST API — the same shape as any SaaS-backed MCP server.

```bash
# as a container
docker build -t transcriptout-mcp https://github.com/artemchuikin/youtube-mcp.git
docker run -i -e TRANSCRIPTOUT_API_KEY=sk_your_key transcriptout-mcp

# or straight from a checkout (Node 20+)
npm install && TRANSCRIPTOUT_API_KEY=sk_your_key node server.js
```

Without a key it still connects and lists all tools; tool calls answer with a clear 401 that says
where to get one. Tool definitions ship in `tools.json` and refresh from the live catalog at
startup when the network allows, so the local list never goes stale.

---

## 🍳 Recipes

Every prompt below is paste-able as written.

| Use Case                        | Example Prompt                                                                                 |
| ------------------------------- | ---------------------------------------------------------------------------------------------- |
| 📝 **Summarize a video**        | "Summarize the key points from this video: [URL]"                                              |
| 🔍 **Research a topic**         | "Search YouTube for the 5 most-watched videos on neural radiance fields and summarize each."      |
| 🧠 **Study notes**              | "Create study notes from this MIT lecture series playlist: [PLAYLIST URL]"                     |
| ⚖️ **Compare perspectives**     | "Compare arguments in these two videos: [URL1] [URL2]"                                         |
| 🌐 **Translate**                | "Translate this video's transcript to Spanish: [URL]"                                          |
| ✍️ **Repurpose content**        | "Turn this video into a 1,500-word blog post: [URL]"                                           |
| 📡 **Monitor a creator**        | "Each morning, list new uploads from @kurzgesagt and tell me which to watch."                 |
| 🏛️ **Build a content database** | "Pull every video ID from @3blue1brown and queue a transcript batch for all of them."          |
| 🎯 **Competitor analysis**      | "Search inside @fireship for any video about [competitor product] and summarize the takeaways." |
| 🧩 **RAG ingestion**            | "Fetch this playlist's transcripts as JSON with segment=1000 and load them into the index."    |

**The bulk recipe spelled out.** "Archive a whole channel" is four tool calls, not a script:

1. `list_channel_videos` with `ids_only=true`: up to 500 video IDs per page
2. `submit_transcripts_job` with those IDs (up to 4,000, duplicates dropped before billing,
   `idempotency_key` makes a retry free)
3. `get_transcripts_job` until `status` is `done`. The job paces itself inside your rate limit
4. `get_transcripts_results` page by page, readable while the job still runs

Anything the service fails to deliver is refunded per video, so the bill matches the archive.

---

## 💳 Pricing and limits

| Plan             | Price                  | Credits                     | Rate Limit  |
| ---------------- | ---------------------- | --------------------------- | ----------- |
| **Free**         | $0                     | 100 on signup (one-time)    | 200 req/min |
| **Starter**      | $4.49/month            | 1,000/month                 | 200 req/min |
| **Starter Annual** | $45.29/year (~$3.77/mo) | 1,000/month               | 200 req/min |
| **Scale**        | slider up to $198.99/mo | up to 100,000/month        | 200 req/min |

- Subscriptions are a slider from 1,000 to 100,000 credits/month in steps of 1,000, and the per-1,000
  rate falls with volume (10,000/mo is $27.49, not $44.90). The annual discount grows with volume,
  from ~16% to ~35%.
- **1 credit = 1 answered request.** Calls that fail before reaching YouTube (validation, rate
  limit, our capacity) are refunded automatically. The running balance rides in the
  `X-Credits-Remaining` header.
- One-time credit packs that never expire can be bought on top of an active subscription.
- [View pricing](https://transcriptout.com/#pricing) · [Manage billing](https://transcriptout.com/billing)

---

## 🧯 When a call fails

<details>
<summary><b>Authentication errors (401)</b></summary>

- Verify your API key starts with `sk_`
- Check for extra spaces when copying
- Ensure the key is active in your [dashboard](https://transcriptout.com/dashboard)
- Revoked keys fail immediately. Issue a new one in the dashboard
</details>

<details>
<summary><b>No credits (402)</b></summary>

- Check your balance in the [dashboard](https://transcriptout.com/dashboard)
- Subscribe or buy a credit pack at [transcriptout.com/billing](https://transcriptout.com/billing)
</details>

<details>
<summary><b>Video not available (404 / 410 / 451)</b></summary>

- `404`: the video has no captions on the requested language/track, or the ID is wrong. This is a
  definitive answer, retrying won't change it.
- `410`: the video was removed.
- `451`: age-restricted or members-only content.
</details>

<details>
<summary><b>Rate limiting (429) and capacity (503)</b></summary>

- Respect the `Retry-After` header. Both are refunded automatically
- For bulk work use `submit_transcripts_job`: it paces itself inside your rate limit instead of
  bouncing off it
</details>

<details>
<summary><b>Errors are structured</b></summary>

Every error body is `{"ok": false, "code": "...", "detail": "...", "request_id": "req_..."}`.
Branch on the machine-readable `code`, not on the human text. Include `request_id` when contacting
support.
</details>

---

## 🌐 Prefer plain REST?

Building an app instead of an agent? The same backend ships as a JSON REST API, with the same
five transcript formats plus raw file download (`download=true`).

|                 | MCP                    | REST API                                              |
| --------------- | ---------------------- | ----------------------------------------------------- |
| **Best for**    | AI assistants & agents | Apps & backend services                               |
| **Setup**       | Add a URL + key        | Code integration                                      |
| **Get started** | This README            | [API docs →](https://transcriptout.com/docs)          |

Base URL: `https://api.transcriptout.com/v1`

---

## 🔗 Links

- 🌐 **Website:** [transcriptout.com](https://transcriptout.com)
- 📚 **Docs:** [transcriptout.com/docs](https://transcriptout.com/docs)
- 🧰 **Agent skills (same backend, no MCP required):** [github.com/artemchuikin/youtube-skills](https://github.com/artemchuikin/youtube-skills)
- 💬 **Contact:** support@transcriptout.com

---

## 📇 MCP Registry

This server is published to the official [Model Context Protocol Registry](https://registry.modelcontextprotocol.io/)
under the name:

```
com.transcriptout/youtube-transcript-and-youtube-search
```

---

TranscriptOut is an independent service and is not affiliated with, endorsed by, or sponsored by
YouTube or Google LLC. "YouTube" is a trademark of Google LLC.

<p align="center">
  <sub>© 2026 TranscriptOut · Released under the <a href="./LICENSE">MIT License</a></sub>
</p>

TDQS

A4.3/5.0

Scored across 14 tools

Disambiguation4/5

Each tool has a distinct job: search, list, fetch single transcript, manage batch jobs, or check credits. The main ambiguities are get_transcripts_results vs get_transcripts_result and get_video_info vs get_transcript with video_metadata=true, but the descriptions clearly point agents to the right choice.

Naming Consistency4/5

Most names follow a clean verb_noun pattern like get_transcript, list_channel_videos, submit_transcripts_job. The pattern is slightly mixed by latest_channel_videos and the singular/plural get_transcripts_results/get_transcripts_result, but conventions remain mostly predictable.

Tool Count5/5

With 14 tools, the server is well-scoped for transcript retrieval plus YouTube search and batch job management. Every tool addresses a real workflow and none feel redundant.

Completeness5/5

The surface covers the full workflow: discover videos, get metadata, fetch individual or batch transcripts, poll job status, retrieve results, cancel jobs, and monitor credits. There are no obvious missing operations for the stated domain.

Maintenance

ActivityMaintained
ResponsivenessNo issues