---
name: bootleg-link-mcp
version: 0.7.3
description: "MCP server for downloading YouTube audio as MP3 with embedded cover art, task queue, progress tracking, and SQLite persistence"
metadata:
  openclaw:
    emoji: "🎵"
    os: ["linux", "darwin"]
    requires:
      bins: ["python3>=3.10"]
---

# Bootleg-Link MCP v0.7.3

Python MCP server for downloading YouTube audio as MP3 with automatic cover art embedding. Features a task queue, concurrent download manager, SQLite-based persistence, and paged playlist support.

## Architecture

Single-file Python MCP server (`src/server.py`) communicating over stdin/stdout via JSON-RPC 2.0.

- **Task Queue**: In-memory queue with SQLite persistence for resume across restarts
- **Download Engine**: yt-dlp Python API with `bestaudio/best` format
- **Cover Art**: Downloads thumbnail via `writethumbnail`, embeds into MP3 ID3 APIC frame using mutagen, then cleans up webp/webm files
- **Concurrency**: ThreadPoolExecutor with configurable worker count
- **Paged Playlist**: Flat playlist extraction (100 per page) for large channel downloads

## MCP Tools

| Tool | Description |
|------|-------------|
| `submit_download_task` | Submit a YouTube URL/channel for audio download |
| `query_progress` | Query task progress and status |
| `list_tasks` | List all tasks with optional status filter |
| `cancel_task` | Cancel a pending or running task |
| `clear_completed` | Clear completed/failed/cancelled tasks |
| `clear_database` | Clear ALL tasks and videos from database |
| `get_queue_status` | Get queue metrics (active, queued, total) |

### submit_download_task

```json
{
  "url": "https://www.youtube.com/@ChannelName/videos",
  "quality": "320",
  "outputDir": "/path/to/output"
}
```

Returns: `{ "success": true, "taskId": "task_xxx", "status": "pending" }`

### query_progress

```json
{
  "taskId": "task_xxx"
}
```

Returns: `{ "status": "downloading", "progress": 45, "songsCompleted": 5, "songsTotal": 100 }`

## Dependencies

- `yt-dlp` — YouTube audio extraction
- `mutagen` — MP3 ID3 tag manipulation and cover art embedding
- Python 3.10+ (stdlib only: `sqlite3`, `json`, `threading`, `concurrent.futures`)

## Configuration

Config file: `~/.bootleg-link-mcp/config.json`

```json
{
  "paths": {
    "outputDir": "~/Downloads/bootleg-link",
    "dbPath": "~/.bootleg-link-mcp/bootleg-link.db"
  },
  "proxy": {
    "http": "http://proxy:port",
    "https": "http://proxy:port"
  },
  "download": {
    "maxConcurrent": 4,
    "quality": "320"
  }
}
```

Or via OpenClaw MCP config with environment variables (deprecated, use config.json):

```json
{
  "command": "python3",
  "args": ["src/server.py"],
  "env": {
    "BOOTLEG_OUTPUT_DIR": "~/Downloads/bootleg-link",
    "BOOTLEG_HTTP_PROXY": "BOOTLEG_HTTP_PROXY",
    "BOOTLEG_HTTPS_PROXY": "BOOTLEG_HTTPS_PROXY"
  }
}
```

