YouTube MCP Server

YouTube MCP Server

Enables AI assistants to analyze YouTube channels, videos, transcripts, and content strategy through structured tool calls.

Category
Visit Server

README

YouTube MCP Server

A Model Context Protocol (MCP) server that exposes YouTube channel intelligence, video analysis, niche discovery, and content strategy tools to AI assistants such as Cursor, Claude Desktop, and other MCP-compatible clients.

Built for creator workflows: audit channels, benchmark videos, discover niches, score titles, and analyze transcripts — all through structured, agent-friendly JSON responses.

Version: 0.1.0 · Node.js: >= 20 · Transport: stdio


Table of Contents


Why This Exists

YouTube creator research usually means juggling the Data API, spreadsheets, and ad-hoc scripts. This server wraps that work into a consistent MCP tool surface so an AI agent can:

  • Resolve messy inputs (@handle, video URLs, channel IDs) into canonical records
  • Fetch channel and video metadata with quota-aware caching
  • Run opinionated analysis (channel audits, niche scoring, title packaging)
  • Return predictable JSON envelopes that agents can reason over reliably

Every tool response includes data, summary, sources, and warnings so downstream workflows stay auditable.


Features

Category Capabilities
Operations Health checks, auth status, quota tracking, cache statistics
Channels Resolve identifiers, fetch profiles, list recent uploads
Videos Details, batch lookup, search, performance snapshots, thumbnails
Strategy Full channel audits, niche opportunity ranking
Content Transcript analysis (user-provided text), title scoring

v0.1 Tool Inventory (17 tools)

<details> <summary><strong>Operational (4)</strong></summary>

Tool Description
youtube.healthcheck Server readiness, API reachability, schema version
youtube.auth.status API key and OAuth configuration status
youtube.quota.status Daily quota usage by endpoint
youtube.cache.status Cache size, hit rate, stale entries

</details>

<details> <summary><strong>Channel & Video (8)</strong></summary>

Tool Description
youtube.channel.resolve Resolve URL, handle, ID, or video URL → channel
youtube.channel.get_profile Title, stats, thumbnails, branding metadata
youtube.channel.get_uploads Recent upload IDs via uploads playlist
youtube.video.get_details Metadata, stats, duration, thumbnails
youtube.video.batch_get_details Batch lookup (up to 50 videos)
youtube.video.search Keyword search with filters
youtube.video.performance_snapshot Views/day, engagement rate, packaging metrics
youtube.thumbnail.get All thumbnail variants and dimensions

</details>

<details> <summary><strong>Strategy & Analysis (5)</strong></summary>

Tool Description
youtube.strategy.channel_audit Upload cadence, outliers, title patterns
youtube.niche.find Rank niche opportunities from seed topics
youtube.transcript.get Transcript retrieval (provided text mode)
youtube.transcript.analyze Hook, structure, CTA, repurpose signals
youtube.packaging.analyze_title Title clarity, curiosity, length scoring

</details>


Architecture

flowchart TB
    subgraph Client["MCP Client"]
        Cursor["Cursor / Claude / Inspector"]
    end

    subgraph Server["youtube-mcp-server"]
        MCP["MCP Server (stdio)"]
        Registry["Tool Registry"]
        Analyzer["Channel Analyzer"]
        MCP --> Registry
        Registry --> Analyzer
    end

    subgraph Services["YouTube Layer"]
        ChannelSvc["Channel Service"]
        VideoSvc["Video Service"]
        Client_YT["YouTube Client"]
        Registry --> ChannelSvc
        Registry --> VideoSvc
        ChannelSvc --> Client_YT
        VideoSvc --> Client_YT
        Analyzer --> ChannelSvc
        Analyzer --> VideoSvc
    end

    subgraph Storage["Persistence"]
        Cache["SQLite API Cache"]
        Quota["SQLite Quota Tracker"]
        Client_YT --> Cache
        Client_YT --> Quota
    end

    subgraph External["External"]
        API["YouTube Data API v3"]
        Client_YT --> API
    end

    Cursor <-->|stdio| MCP

Design principles

  • Stdio transport — runs as a subprocess; no HTTP server to deploy
  • Zod validation — strict input schemas on every tool call
  • SQLite persistence — response cache and quota ledger share one database file
  • Quota guardrails — pre-flight checks before each API call; configurable daily budget
  • Structured envelopes — uniform { data, summary, sources, warnings } responses

Prerequisites

  1. Node.js 20+nodejs.org
  2. YouTube Data API v3 key — from Google Cloud Console

Obtaining a YouTube API Key

  1. Create or select a Google Cloud project
  2. Enable YouTube Data API v3 under APIs & Services → Library
  3. Go to APIs & Services → Credentials → Create Credentials → API Key
  4. Restrict the key to YouTube Data API v3 (recommended for production)
  5. Copy the key into your environment (see Configuration)

Note: Default Google Cloud quota is 10,000 units/day. This server defaults to a 9,000 unit soft limit to leave headroom.


Quick Start

# Clone and install
git clone <your-repo-url> youtube-mcp-server
cd youtube-mcp-server
npm install

# Configure credentials
cp .env.example .env
# Edit .env and set YOUTUBE_API_KEY=your-key-here

# Build and verify
npm run build
npm test

Verify the server with the MCP Inspector:

npx @modelcontextprotocol/inspector node dist/index.js

Then invoke youtube.healthcheck and youtube.channel.resolve with:

{ "input": "@mkbhd" }

MCP Client Setup

The server communicates over stdio. Point your MCP client at the built entry point (dist/index.js) or the dev runner (tsx src/index.ts).

Cursor

Add to ~/.cursor/mcp.json (Windows: %USERPROFILE%\.cursor\mcp.json):

Production (compiled)

{
  "mcpServers": {
    "youtube": {
      "command": "node",
      "args": ["/absolute/path/to/youtube-mcp-server/dist/index.js"],
      "env": {
        "YOUTUBE_API_KEY": "your-api-key-here"
      }
    }
  }
}

Development (hot reload via tsx)

{
  "mcpServers": {
    "youtube": {
      "command": "npx",
      "args": ["tsx", "/absolute/path/to/youtube-mcp-server/src/index.ts"],
      "env": {
        "YOUTUBE_API_KEY": "your-api-key-here"
      }
    }
  }
}

Claude Desktop

Add to ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or the equivalent path on your OS:

{
  "mcpServers": {
    "youtube": {
      "command": "node",
      "args": ["/absolute/path/to/youtube-mcp-server/dist/index.js"],
      "env": {
        "YOUTUBE_API_KEY": "your-api-key-here"
      }
    }
  }
}

Using a .env file

The server auto-loads .env from the project root when present. If your MCP config launches the server from the project directory, you can omit inline env keys and rely on the file instead:

YOUTUBE_API_KEY=your-api-key-here
CACHE_DB_PATH=./data/cache.db

Environment variables set in the MCP client config take precedence over .env values already in process.env; unset keys fall through to .env.


Configuration

Variable Required Default Description
YOUTUBE_API_KEY Yes YouTube Data API v3 key
CACHE_DB_PATH No ./data/cache.db SQLite database for cache + quota
MAX_DAILY_QUOTA_UNITS No 9000 Soft daily quota budget
CACHE_TTL_CHANNEL_HOURS No 24 TTL for channel/profile cache
CACHE_TTL_VIDEO_HOURS No 12 TTL for video detail cache
CACHE_TTL_SEARCH_HOURS No 6 TTL for search result cache
TRANSCRIPT_MODE No provided_text Comma-separated transcript modes
PUBLIC_TRANSCRIPT_ADAPTER_ENABLED No false Enable public transcript adapter
GOOGLE_CLIENT_ID No OAuth client ID (future caption support)
GOOGLE_CLIENT_SECRET No OAuth client secret
GOOGLE_REDIRECT_URI No OAuth redirect URI

Copy .env.example as a starting point:

cp .env.example .env

Tool Reference

All tools accept JSON arguments and return a structured response. Use forceRefresh: true to bypass cache when you need live data (consumes quota).

Operational

// youtube.healthcheck
{}

// youtube.quota.status
{}

Channel resolution & profiles

// youtube.channel.resolve
{ "input": "@mkbhd" }
{ "input": "https://www.youtube.com/watch?v=dQw4w9WgXcQ" }

// youtube.channel.get_profile
{ "channel": "@mkbhd", "forceRefresh": false }

// youtube.channel.get_uploads
{ "channel": "UC...", "maxResults": 25, "pageToken": null }

Accepted channel identifiers: @handle, channel URL, UC... channel ID, custom URL, or a video URL (resolved to its channel).

Video lookup & search

// youtube.video.get_details
{ "video": "dQw4w9WgXcQ", "includeTags": true }

// youtube.video.batch_get_details
{ "videos": ["id1", "id2", "https://youtu.be/id3"], "includeTags": false }

// youtube.video.search
{
  "query": "home gym setup",
  "maxResults": 10,
  "order": "viewCount",
  "type": "video",
  "regionCode": "US",
  "videoDuration": "medium",
  "recency": "pastMonth"
}

// youtube.video.performance_snapshot
{ "video": "dQw4w9WgXcQ" }

// youtube.thumbnail.get
{ "video": "dQw4w9WgXcQ" }

Search order values: relevance, date, viewCount, rating

Search recency values: any, pastHour, pastDay, pastWeek, pastMonth, pastQuarter, pastYear

Strategy & content analysis

// youtube.strategy.channel_audit
{ "channel": "@mkbhd", "maxVideos": 25 }

// youtube.niche.find
{
  "seedTopics": ["minimalist desk setup", "standing desk review"],
  "regionCode": "US",
  "maxResults": 10
}

// youtube.transcript.get (provided text)
{
  "mode": "provided_text",
  "transcriptText": "Welcome back to the channel...",
  "language": "en"
}

// youtube.transcript.analyze
{
  "transcriptText": "In this video we cover...",
  "analysisTypes": ["hook", "structure", "cta", "repurpose"]
}

// youtube.packaging.analyze_title
{ "title": "I Tried Every Standing Desk Under $300" }

Channel audit output highlights

youtube.strategy.channel_audit returns:

  • Upload cadence — videos/week, consistency score, average gap between uploads
  • Performance — median views, average views/day, engagement rate, outlier count
  • Top videos — highest-performing uploads with engagement metrics
  • Outlier videos — uploads exceeding 2× channel median views
  • Title patterns — average length, common words, detected formulas
  • Thumbnail availability — coverage across analyzed uploads

Niche scoring

youtube.niche.find searches each seed topic, samples top results, and scores opportunities using demand and competition proxies. Results are ranked by overallScore.


Response Format

Successful tool calls return JSON text with this envelope:

{
  "data": { },
  "summary": "Human-readable one-liner for the agent",
  "sources": [
    {
      "type": "youtube_api",
      "endpoint": "channels.list",
      "url": "https://www.youtube.com/@mkbhd",
      "timestamp": "2026-07-07T12:00:00.000Z"
    }
  ],
  "warnings": []
}

Errors return a separate JSON object with isError: true:

{
  "error": {
    "code": "QUOTA_EXCEEDED",
    "message": "Daily quota limit reached (9000/9000 units used)",
    "retryable": true
  }
}

Error codes

Code Retryable Meaning
QUOTA_EXCEEDED Yes Daily soft limit or Google quota hit
TRANSCRIPT_UNAVAILABLE No Requested transcript mode not available
UNKNOWN_TOOL No Tool name not registered
INTERNAL_ERROR No Unexpected server error

Quota & Caching

Quota costs (estimated units per call)

Endpoint Cost
channels.list 1
videos.list 1
playlistItems.list 1
playlists.list 1
search.list 100
captions.list 50
commentThreads.list 1

The quota tracker records usage in SQLite and enforces MAX_DAILY_QUOTA_UNITS before each request. Check status anytime:

// youtube.quota.status →
{
  "dailyLimit": 9000,
  "usedToday": 342,
  "remaining": 8658,
  "byEndpoint": { "search.list": 300, "videos.list": 42 },
  "date": "2026-07-07"
}

Caching behavior

  • Responses are keyed by endpoint + normalized request parameters (SHA-256 hash)
  • TTLs are configurable per resource type (channel, video, search)
  • Stale entries are returned as cache misses and refreshed on next call
  • forceRefresh: true skips cache reads (still records quota on API hit)

Tips for quota efficiency

  1. Prefer youtube.video.batch_get_details over repeated get_details calls
  2. Use youtube.channel.get_profile before re-fetching the same channel
  3. Treat youtube.video.search as expensive (~100 units each)
  4. Run youtube.niche.find with fewer seed topics during development
  5. Monitor with youtube.quota.status and youtube.cache.status

Transcript Modes

Official YouTube caption download requires OAuth and (for most captions) video owner permissions. v0.1 supports:

Mode Status Description
provided_text Supported User pastes transcript text for analysis
owner_oauth Planned OAuth-based owner caption access
public_adapter Disabled Third-party public transcript adapter
speech_to_text Planned Audio → text pipeline

Configure enabled modes via TRANSCRIPT_MODE (comma-separated). Every transcript response includes provenance metadata.

Example workflow

  1. Copy transcript text manually (or from your own pipeline)
  2. Call youtube.transcript.get with mode: "provided_text"
  3. Pass the text to youtube.transcript.analyze for hook/structure/CTA insights

Development

# Run server directly (stdio — intended for MCP clients)
npm run dev

# Type-check
npm run typecheck

# Build for production
npm run build
npm start

NPM scripts

Script Description
npm run dev Start via tsx (no build step)
npm run build Compile TypeScript → dist/
npm start Run compiled dist/index.js
npm test Run Vitest unit tests
npm run typecheck tsc --noEmit

Tech stack

  • Runtime: Node.js 20+, ESM ("type": "module")
  • MCP SDK: @modelcontextprotocol/sdk
  • Validation: Zod
  • Storage: better-sqlite3
  • Testing: Vitest

Testing

npm test

Unit tests cover identifier parsing (@handle, URLs, channel IDs), duration/engagement utilities, title scoring, and transcript analysis heuristics.


Troubleshooting

Symptom Likely cause Fix
YOUTUBE_API_KEY is required Missing API key Set in .env or MCP env block
QUOTA_EXCEEDED Daily limit hit Wait for reset (midnight Pacific) or raise MAX_DAILY_QUOTA_UNITS
YouTube API error (403) API not enabled or key restricted Enable YouTube Data API v3; check key restrictions
Server starts but tools fail Wrong working directory Use absolute paths in MCP config args
Empty search results Overly narrow filters Relax recency, videoDuration, or regionCode
TRANSCRIPT_UNAVAILABLE Unsupported mode Use provided_text with transcriptText
Cache shows stale entries Normal TTL expiry Stale entries refresh on next miss; or use forceRefresh

Debug with MCP Inspector

npx @modelcontextprotocol/inspector node dist/index.js

Inspect raw tool inputs/outputs, list registered tools, and verify API connectivity without an IDE.


Project Structure

youtube-mcp-server/
├── src/
│   ├── index.ts              # Entry point, .env loader
│   ├── server/
│   │   ├── mcpServer.ts      # MCP server + stdio transport
│   │   ├── toolRegistry.ts   # Tool handlers + definitions
│   │   └── schemas.ts        # Zod input schemas
│   ├── youtube/
│   │   ├── youtubeClient.ts  # API client, cache, quota integration
│   │   ├── channelService.ts # Channel resolve, profile, uploads
│   │   ├── videoService.ts   # Video details, search, snapshots
│   │   └── quotaTracker.ts   # Daily quota ledger
│   ├── analysis/
│   │   └── channelAnalyzer.ts # Audits, niche scoring, title/transcript analysis
│   ├── storage/
│   │   └── cache.ts          # SQLite response cache
│   ├── config/
│   │   ├── env.ts            # Environment validation
│   │   └── defaults.ts       # Quota costs, schema version
│   ├── utils/
│   │   ├── ids.ts            # URL/ID parsing
│   │   ├── duration.ts       # ISO duration, engagement math
│   │   └── response.ts       # Response envelope helpers
│   └── tests/
│       └── unit/             # Vitest unit tests
├── .env.example
├── package.json
├── tsconfig.json
└── vitest.config.ts

Roadmap

v0.1 ships 17 tools. A broader roadmap (53+ tools) is documented separately, including:

  • OAuth-based owner caption download
  • Thumbnail vision analysis
  • Competitor comparison reports
  • Export and reporting utilities

See the parent YouTube MCP Server Build Plan for the full phased rollout.


Security

  • Never commit .env, API keys, or *.db files — they are gitignored
  • Restrict your API key to YouTube Data API v3 and (optionally) specific IPs
  • Prefer MCP env injection or OS-level secrets over hardcoding keys in config files shared via git
  • Quota limits are enforced server-side, but Google Cloud quotas are the ultimate ceiling
  • OAuth credentials (GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET) are optional and only needed for future caption features

<p align="center"> <sub>Built for AI-assisted YouTube creator workflows · MCP stdio server · YouTube Data API v3</sub> </p>

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