Skip to main content
Glama

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


Related MCP server: youtube-mcp

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)

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

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

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


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).

// 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


Available Tools

17 tools
youtube.auth.statusA

Show whether API key and OAuth are configured

Inputs: no named parameters.

youtube.cache.statusA

Show cache size, freshness, hit rate, and stale records

Inputs: no named parameters.

youtube.channel.get_profileB

Fetch channel title, description, statistics, thumbnails, and branding metadata

Inputs: channel (required), forceRefresh.

youtube.channel.get_uploadsC

Fetch recent uploads through the channel uploads playlist

Inputs: channel (required), pageToken, maxResults, forceRefresh.

youtube.channel.resolveA

Resolve channel URL, handle, custom URL, channel ID, or video URL to canonical channel ID

Inputs: input (required).

youtube.healthcheckC

Server readiness, dependency status, API reachability, and schema version

Inputs: no named parameters.

youtube.niche.findC

Rank niche opportunities from seed topics using search demand and competition proxies

Inputs: seedTopics (required), maxResults, regionCode.

youtube.packaging.analyze_titleC

Score a title by clarity, curiosity, specificity, length, and detected formula

Inputs: title (required).

youtube.quota.statusA

Show estimated YouTube API quota usage by endpoint and day

Inputs: no named parameters.

youtube.strategy.channel_auditB

Channel audit with upload cadence, top videos, outliers, title patterns, and thumbnail availability

Inputs: channel (required), maxVideos, forceRefresh.

youtube.thumbnail.getB

Return all available thumbnail URLs and dimensions for a video

Inputs: video (required).

youtube.transcript.analyzeC

Analyze user-provided transcript for hook, structure, CTAs, and retention signals

Inputs: transcriptText (required), analysisTypes.

youtube.transcript.getC

Retrieve transcript using approved modes (provided_text supported; OAuth captions planned)

Inputs: mode (required), video, language, transcriptText.

youtube.video.batch_get_detailsB

Batch video lookup by IDs or URLs with cache-aware quota handling

Inputs: videos (required), includeTags, forceRefresh.

youtube.video.get_detailsC

Fetch video metadata, statistics, duration, and thumbnails

Inputs: video (required), includeTags, forceRefresh.

youtube.video.performance_snapshotC

Return views, engagement rate, views per day, and packaging metrics for a video

Inputs: video (required).

youtube.video.searchC

Search YouTube by keyword with filters for region, duration, recency, and order

Inputs: query (required), type, order, recency, +5 more.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.5/5.0

    Scored across 17 tools

    Disambiguation5/5

    Each tool has a clearly distinct purpose, organized by category prefixes (e.g., youtube.channel, youtube.video). No two tools overlap in functionality; an agent can easily differentiate them.

    Naming Consistency5/5

    All tool names follow a consistent pattern: lowercase with dot-separated categories and underscores (e.g., youtube.channel.get_profile, youtube.video.get_details). No mixing of conventions.

    Tool Count5/5

    17 tools cover a comprehensive range of YouTube data and analysis operations (channels, videos, transcripts, niche analysis, etc.) without being excessive. The count is well-scoped for the server's purpose.

    Completeness5/5

    The tool set covers core YouTube information retrieval and analysis needs: channel details, video details, transcripts, thumbnails, search, niche analysis, and channel audit. Missing CRUD operations are outside the server's analytical scope.

    Maintenance

    ActivityInactive
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      D
      maintenance
      Enables AI assistants to search videos, read channels, browse playlists, fetch comments, and get transcripts from YouTube using the YouTube Data API v3 and InnerTube API for captions.
      2
      GPL 3.0
    • A
      license
      A
      quality
      D
      maintenance
      Enables AI tools to access YouTube content, including transcript extraction, video/channel info, and search.
      4
      23 npm
      MIT
    • F
      license
      Not graded
      quality
      C
      maintenance
      Enables AI assistants to search videos, retrieve transcripts and metadata, analyze channels, and access trending and engagement analytics for YouTube content.
      26 npm
      -