Skip to main content
Glama
sacahan

YouTube Search MCP Server

by sacahan
README.md
# YouTube Search API

Zero-cost YouTube video search service powered by web scraping

## Features

- ✅ No YouTube API key required - completely free
- ✅ RESTful API design with Swagger documentation
- ✅ MCP (Model Context Protocol) support - integrate with AI assistants
- ✅ Redis caching optimization (1 hour TTL)
- ✅ Complete video metadata extraction
- ✅ Sorting and filtering capabilities
- ✅ Docker containerization support

## Quick Start

### Install Dependencies

```bash
uv sync
```

### Start the Service

```bash
python main.py
```

The service will start at `http://localhost:8000`.

### API Documentation

Visit `http://localhost:8000/docs` for interactive API documentation.

## API Usage Examples

### Basic Search

```bash
curl "http://localhost:8000/api/v1/search?keyword=Python tutorial"
```

### Specify Result Count

```bash
curl "http://localhost:8000/api/v1/search?keyword=Python&limit=5"
```

### Sort by Date

```bash
curl "http://localhost:8000/api/v1/search?keyword=Python&sort_by=date&limit=3"
```

## Audio Download Feature

Download YouTube videos as MP3 audio files with automatic caching and cleanup.

### Download Features

- ✅ Download YouTube videos as 128kbps MP3 files
- ✅ Support for single and batch downloads
- ✅ Redis-based caching to avoid duplicate downloads
- ✅ Automatic cleanup of expired files (24-hour TTL)
- ✅ Rate limiting: 20 downloads per IP per hour
- ✅ Video duration limit: maximum 10 minutes
- ✅ Direct streaming or download link format

### Download API Examples

#### Single Video Download (Link Format)

```bash
# Get download link
curl -X POST "http://localhost:8000/api/v1/download/audio?video_id=dQw4w9WgXcQ&format=link"

# Response
{
  "video_id": "dQw4w9WgXcQ",
  "title": "Rick Astley - Never Gonna Give You Up",
  "duration": 212,
  "download_url": "http://localhost:8000/downloads/dQw4w9WgXcQ_Rick_Astley.mp3",
  "cached": false,
  "file_size": 3400000
}
```

#### Single Video Download (Stream Format)

```bash
# Direct MP3 stream - returns binary audio data
curl -X POST "http://localhost:8000/api/v1/download/audio?video_id=dQw4w9WgXcQ&format=stream" -o output.mp3
```

#### Batch Download

```bash
# Download multiple videos at once (max 20)
curl -X POST "http://localhost:8000/api/v1/download/batch" \
  -H "Content-Type: application/json" \
  -d '{
    "video_ids": ["dQw4w9WgXcQ", "jNQXAC9IVRw"]
  }'

# Response
{
  "total": 2,
  "successful": 1,
  "failed": 1,
  "items": [
    {
      "video_id": "dQw4w9WgXcQ",
      "status": "success",
      "download_url": "http://localhost:8000/downloads/...",
      "duration": 212,
      "cached": false
    },
    {
      "video_id": "jNQXAC9IVRw",
      "status": "failed",
      "error_message": "Video duration exceeds limit"
    }
  ]
}
```

### Configuration

Set these environment variables to customize download behavior:

```bash
# Download storage directory
DOWNLOAD_DIR=/tmp/youtube_audio

# Base URL for serving downloads (used in download links)
DOWNLOAD_BASE_URL=http://localhost:8000/downloads

# Download timeout in seconds
DOWNLOAD_TIMEOUT=300

# Maximum video duration in seconds (default: 600 = 10 minutes)
MAX_VIDEO_DURATION=600

# Audio bitrate in kbps
AUDIO_BITRATE=128

# Cache TTL in hours
CACHE_TTL_HOURS=24

# Rate limit: downloads per IP per hour
RATE_LIMIT_DOWNLOAD_PER_HOUR=20

# Enable rate limiting
RATE_LIMIT_ENABLED=true
```

### Error Handling

The API returns appropriate HTTP status codes:

- `400` - Invalid video ID or parameters
- `403` - Video too long, live stream, or access restricted
- `404` - Video not found or deleted
- `503` - Download failed or YouTube unavailable
- `507` - Server storage full

### Cleanup

Expired audio files are automatically deleted after 24 hours. Manual cleanup can be triggered:

```bash
# Manual cleanup script
python scripts/cleanup_cron.py

# Schedule with cron (daily at 2 AM)
0 2 * * * /usr/bin/python /path/to/scripts/cleanup_cron.py >> /path/to/logs/cleanup.log 2>&1
```

## MCP Integration (Model Context Protocol)

This service provides MCP server functionality, allowing AI assistants (such as Claude Desktop) to directly invoke YouTube search tools via the MCP protocol.

### MCP Service Types

- **HTTP Service**: Provided via StreamableHTTPSessionManager, integrated with existing FastAPI application
- **Supported Transport Modes**: HTTP (MVP)
- **Future Iterations**: Consider supporting stdio and SSE modes

### REST API and MCP Coexistence

- **REST API Preservation**: Existing REST API endpoints (`/api/v1/search`, etc.) remain fully functional
- **Flexible Deployment**: Choose between integrated (same FastAPI app) or separate (independent process) deployment
- **Backward Compatibility**: MCP additions do not modify any existing REST API signatures or behaviors

### MCP Configuration

#### Claude Desktop Setup

Add the following to Claude Desktop's configuration file (`~/.config/claude/settings.json` or `%APPDATA%\Claude\settings.json`):

```json
{
  "servers": {
    "youtube-search-mcp": {
      "command": "uv",
      "args": ["run", "python", "mcp_stdio.py"],
      "env": {
        "MCP_SEARCH_TIMEOUT": "15",
        "MCP_SEARCH_RETRIES": "3",
        "PYTHONUNBUFFERED": "1"
      }
    }
  }
}
```

#### Environment Variables

- `MCP_SEARCH_TIMEOUT` (default: 15 seconds): Search operation timeout
- `MCP_SEARCH_RETRIES` (default: 3 times): Retry attempts on search failure
- `REDIS_HOST`, `REDIS_PORT`, `REDIS_DB`: Redis cache configuration (optional)

### Starting the MCP Server

```bash
# Start MCP server (stdio mode)
python mcp_stdio.py

# Or using uv
uv run python mcp_stdio.py
```

### MCP Tool: youtube_search

**Tool Name**: `youtube_search`

**Description**: Search YouTube videos and return complete metadata

**Parameters**:

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `keyword` | string | ✅ | - | Search keyword (1-200 characters) |
| `limit` | integer | ❌ | 1 | Number of results to return (1-100) |
| `sort_by` | string | ❌ | relevance | Sort order: `relevance` or `date` |

**Response Format**:

```json
{
  "videos": [
    {
      "video_id": "mIF-nn_y2_8",
      "title": "Jackie Cheung - Farewell Kiss",
      "channel": "Music Without Boundaries",
      "url": "https://www.youtube.com/watch?v=mIF-nn_y2_8",
      "channel_url": "https://www.youtube.com/@channel_name",
      "publish_date": "2020-01-15",
      "view_count": "1500000",
      "description": "Classic Cantonese song..."
    }
  ],
  "message": "Successfully returned 1 result"
}
```

**Error Handling**:

- Empty keyword: Returns `{"error": "INVALID_KEYWORD", "message": "Search keyword cannot be empty..."}`
- Invalid limit: Returns `{"error": "INVALID_LIMIT", "message": "limit must be between 1-100..."}`
- YouTube service unavailable: Returns `{"error": "SERVICE_UNAVAILABLE", "message": "YouTube service is temporarily unavailable..."}`
- Cache service failure: Gracefully degrades to direct search and returns normal results

## Environment Configuration

Copy `.env.example` to `.env` and modify as needed:

```bash
cp .env.example .env
```

## Docker Deployment

```bash
docker-compose up -d
```

## Testing

```bash
pytest tests/
```

## Project Structure

```text
src/youtube_search/
├── models/          # Pydantic data models
├── services/        # Business logic layer
├── api/             # API routes
└── utils/           # Utility functions
```

## License

MIT License

TDQS

A4/5.0

Scored across 1 tool

Disambiguation5/5

Only one tool exists, so there is no possibility of confusion between tools. The single tool has a clear purpose.

Naming Consistency5/5

With only one tool, naming consistency is perfect. The name 'youtube_search' follows a clear verb_noun pattern.

Tool Count3/5

The server has only one tool, which feels thin for a video platform. While it covers basic search, typical servers offer more endpoints for a richer interaction.

Completeness2/5

The server only provides search functionality. Missing features like fetching video details, channel information, or trending videos create significant gaps for a comprehensive YouTube tool.

Maintenance

ActivityInactive
ResponsivenessNo issues