About Ironbeard MCP Youtube
Ironbeard MCP Youtube is an MCP server in the Social category: mCP server for pulling YouTube video transcripts. Single Rust binary. No Python, Node, or yt-dlp needed.
Install
git clone https://github.com/Alatar86/ironbeard-mcp-youtubeThis server has no ConduID identity, so agent calls to it are not receipted. Pin the version you install and review the source before granting it credentials.
Ask AI
Ask AI about Ironbeard MCP Youtube
Powered by Claude · Grounded in docs
Security checks
- ✓README presentThe repository ships documentation.
5 checks have not been run yet.
README
ironbeard-mcp-youtube
MCP server for pulling YouTube video transcripts. Single Rust binary. No Python, Node, or yt-dlp needed.
Features
- Grabs transcripts from any YouTube video that has captions
- Four output formats: plain text, timestamped, SRT subtitles, JSON
- Language resolution with prefix matching and automatic fallback
- File-based caching with 7-day TTL (SHA-256 hashed keys)
- Retries with exponential backoff on network errors
- Saves transcripts as markdown with YAML frontmatter
- Works on Linux, macOS, and Windows
- Plugs into Claude Desktop, Cursor, or any MCP client
Installation
git clone https://github.com/Alatar86/ironbeard-mcp-youtube.git
cd ironbeard-mcp-youtube
cargo build --release
Binary lands at target/release/ironbeard-mcp-youtube.
Usage
MCP Server Setup
The server runs over stdio. Point your MCP client at the binary.
Claude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json on macOS):
{
"mcpServers": {
"youtube-transcript": {
"command": "/path/to/ironbeard-mcp-youtube"
}
}
}
Cursor (.cursor/mcp.json in workspace root):
{
"mcpServers": {
"youtube-transcript": {
"command": "/path/to/ironbeard-mcp-youtube"
}
}
}
Tool: get_youtube_transcript
| Parameter | Type | Required | Description |
|---|---|---|---|
url |
string |
Yes | YouTube video URL or 11-character video ID |
language |
string |
No | BCP-47 language code (e.g., en, es, ja). Defaults to the video's primary language. |
format |
string |
No | Output format: plain (default), timestamped, srt, json |
Accepted URL formats:
https://www.youtube.com/watch?v=VIDEO_IDhttps://youtu.be/VIDEO_IDhttps://youtube.com/embed/VIDEO_ID- Raw 11-character video ID (e.g.,
dQw4w9WgXcQ)
Command-Line Options
| Flag | Description | Default |
|---|---|---|
--transcript-dir <PATH> |
Where to save transcript .md files |
~/Documents/youtube-transcripts |
--cache-dir <PATH> |
Where to store cached transcript JSON | Platform cache directory (see below) |
As a Rust Library
use ironbeard_mcp_youtube::{TranscriptService, OutputFormat, SaveOutcome};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let service = TranscriptService::new()?;
let result = service
.get_transcript("dQw4w9WgXcQ", Some("en"), OutputFormat::Plain)
.await?;
println!("{}", result.formatted_text);
match &result.save_outcome {
SaveOutcome::Saved(path) => println!("Saved to: {}", path.display()),
SaveOutcome::Failed(err) => eprintln!("Save failed: {}", err),
SaveOutcome::NotAttempted => {}
}
Ok(())
}
Output Formats
Plain
All caption text joined with spaces:
We're no strangers to love You know the rules and so do I...
Timestamped
Each segment prefixed with [HH:MM:SS]:
[00:00:18] We're no strangers to love
[00:00:22] You know the rules and so do I
SRT
Standard SubRip subtitle format:
1
00:00:18,000 --> 00:00:22,000
We're no strangers to love
2
00:00:22,000 --> 00:00:27,000
You know the rules and so do I
JSON
Structured array:
[
{"start": 18.0, "duration": 4.0, "text": "We're no strangers to love"},
{"start": 22.0, "duration": 5.0, "text": "You know the rules and so do I"}
]
Saved Transcripts
Every transcript gets saved as a markdown file named {title} - {author}.md with YAML frontmatter:
---
title: "Never Gonna Give You Up"
author: "Rick Astley"
video_id: "dQw4w9WgXcQ"
url: "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
language: "en"
duration: "00:03:33"
duration_seconds: 213
date_saved: "2026-02-17"
---
# Never Gonna Give You Up
We're no strangers to love You know the rules and so do I...
Configuration
| Environment Variable | Description | Default |
|---|---|---|
TRANSCRIPT_DIR |
Where .md transcript files get saved |
~/Documents/youtube-transcripts |
You can set this in your MCP client config:
{
"mcpServers": {
"youtube-transcript": {
"command": "/path/to/ironbeard-mcp-youtube",
"env": {
"TRANSCRIPT_DIR": "/path/to/my/transcripts"
}
}
}
}
The --transcript-dir CLI flag takes precedence over the environment variable.
Cache
Transcripts are cached as JSON files in the platform cache directory:
| Platform | Directory |
|---|---|
| Linux | ~/.cache/ironbeard-mcp-youtube/ |
| macOS | ~/Library/Caches/ironbeard-mcp-youtube/ |
| Windows | %LOCALAPPDATA%\ironbeard-mcp-youtube\ |
Cache keys are SHA-256 hashes of video_id + language. Entries expire after 7 days and get cleaned up on access.
How It Works
- Parse the video ID from the URL or raw ID
- Check the file cache for a valid entry
- On miss, hit YouTube's innertube
/playerAPI for metadata and caption track URLs - Fetch the timedtext XML from the resolved caption track
- Parse the XML into transcript lines, decode HTML entities
- Cache the result as JSON
- Save transcript as markdown with YAML frontmatter
- Format and return the transcript in the requested output format
Language resolution tries exact match first, then prefix match (en matches en-US), then falls back to the first available track. Network requests retry up to 3 times with exponential backoff (1s, 2s, 4s).
Architecture
src/
main.rs - Entry point, CLI args, starts MCP server on stdio
lib.rs - Public API exports
server.rs - MCP server (rmcp 0.15), tool definitions
service.rs - TranscriptService: fetch, cache, format, save
config.rs - Configuration (directories, env vars, defaults)
youtube/
mod.rs - Video ID parsing, module exports
api.rs - Transcript fetching with retry logic
client.rs - HTTP client with cookie/consent handling
parser.rs - Player API JSON, timedtext XML, and json3 parsing
proto.rs - Manual protobuf encoding for innertube params
types.rs - Data structures (TranscriptLine, VideoMetadata, etc.)
error.rs - Error types (VideoNotFound, NoCaptions, RateLimited, etc.)
processing/
mod.rs - Output formatters (plain, timestamped, SRT, JSON)
cache/
mod.rs - File-based transcript cache with SHA-256 keys and TTL
tests/
integration_test.rs - End-to-end tests against live YouTube
Dependencies
| Crate | Purpose |
|---|---|
rmcp |
MCP server framework (stdio transport) |
tokio |
Async runtime |
reqwest |
HTTP client with cookie support |
serde / serde_json |
Serialization |
schemars |
JSON Schema generation for MCP tool input |
regex |
URL parsing, XML extraction |
sha2 |
Cache key hashing |
dirs |
Platform-specific directory resolution |
clap |
CLI argument parsing |
chrono |
Date formatting for frontmatter |
anyhow |
Application error handling |
thiserror |
Error type derivation |
tracing / tracing-subscriber |
Structured logging |
base64 / urlencoding |
Protobuf param encoding for innertube API |
slug |
Filename slugification for non-Latin titles |
lazy_static |
Static regex compilation |
Development
# Unit tests (offline)
cargo test --lib
# All tests including integration (hits YouTube)
cargo test
# Check formatting
cargo fmt --check
# Lint
cargo clippy
# Build release
cargo build --release
Limitations
- Video needs captions (human or auto-generated)
- Video must be public
- Language availability depends on what YouTube has
- Rapid requests can get rate-limited (server retries automatically)
License
MIT
Contact
Bug reports: GitHub Issues or Ironbeardai@gmail.com
README copy captured when this server was indexed; it may lag the repository. The original is authoritative.