list_playlist_videos
List YouTube playlist videos with titles, IDs, channels, durations, and views. Sort results by index, title, duration, or views, and limit the number of videos returned.
Instructions
List the videos in a YouTube playlist (titles, IDs, channels, durations, views).
Per-video metadata is intentionally lean so the call stays fast even for big playlists. For full metadata on a specific video, call get_video_metadata with that video's ID.
Args: url: YouTube playlist URL (with ?list=...) or bare playlist ID limit: Maximum videos to return (default 500). Pass a smaller value to truncate. sort_by: Sort key — "index" (playlist order, default), "title", "duration", "views". "upload_date" is not supported in this fast-mode tool. order: "asc" (default) or "desc".
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | ||
| limit | No | ||
| sort_by | No | index | |
| order | No | asc |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| result | Yes |
Implementation Reference
- main.py:432-521 (handler)The @mcp.tool() decorated function that implements the 'list_playlist_videos' tool. It takes a YouTube playlist URL, limit, sort_by, and order parameters, fetches playlist entries via _fetch_playlist, sorts/filters them, and returns a formatted text output listing titles, IDs, channels, durations, and views.
@mcp.tool() def list_playlist_videos( url: str, limit: int = 500, sort_by: str = "index", order: str = "asc", ) -> str: """List the videos in a YouTube playlist (titles, IDs, channels, durations, views). Per-video metadata is intentionally lean so the call stays fast even for big playlists. For full metadata on a specific video, call get_video_metadata with that video's ID. Args: url: YouTube playlist URL (with ?list=...) or bare playlist ID limit: Maximum videos to return (default 500). Pass a smaller value to truncate. sort_by: Sort key — "index" (playlist order, default), "title", "duration", "views". "upload_date" is not supported in this fast-mode tool. order: "asc" (default) or "desc". """ if sort_by not in _PLAYLIST_SORT_KEYS: if sort_by == "upload_date": return ( 'Error: sort_by="upload_date" is not supported by list_playlist_videos ' "(it would require a slow per-video fetch). Call get_video_metadata for " "individual videos if you need upload dates." ) return f"Error: invalid sort_by '{sort_by}'. Choose from: {', '.join(_PLAYLIST_SORT_KEYS)}." if order not in ("asc", "desc"): return f"Error: invalid order '{order}'. Choose 'asc' or 'desc'." if limit <= 0: return f"Error: limit must be a positive integer (got {limit})." try: playlist_id = extract_playlist_id(url) except ValueError as e: return f"Error: {e}" # When sorting by index, push the limit into yt-dlp's playlistend for an efficient # fetch. Other sorts need every entry first. fetch_limit = limit if sort_by == "index" else None playlist = _fetch_playlist(playlist_id, limit=fetch_limit) if playlist is None: return f"Error: Failed to fetch playlist '{playlist_id}'." entries = playlist["entries"] sort_key = _PLAYLIST_SORT_KEYS[sort_by] if sort_key is not None: reverse = order == "desc" # Entries with missing sort values go to the end regardless of direction. def keyfunc(e): v = e.get(sort_key) missing = v is None if isinstance(v, str): v = v.lower() return (missing, v if not missing else "") entries = sorted(entries, key=keyfunc, reverse=reverse) # `reverse=True` would also reverse the missing-flag, so re-pin missing entries to the tail if reverse: present = [e for e in entries if e.get(sort_key) is not None] absent = [e for e in entries if e.get(sort_key) is None] entries = present + absent shown = entries[:limit] total = playlist["total"] lines = [] if playlist.get("title"): lines.append(f"Playlist: {playlist['title']}") if playlist.get("uploader"): lines.append(f"Owner: {playlist['uploader']}") truncated = total and len(shown) < total count_line = f"Showing {len(shown)} of {total} videos" if truncated else f"Videos: {len(shown)}" lines.append(f"{count_line} (sorted by {sort_by}, {order})") lines.append("") for i, e in enumerate(shown, start=1): lines.append(f" {i:>3}. {e.get('title') or '(no title)'}") if e.get("id"): lines.append(f" ID: {e['id']}") if e.get("channel"): lines.append(f" Channel: {e['channel']}") if e.get("duration_seconds") is not None: lines.append(f" Duration: {_format_hms(e['duration_seconds'])}") if e.get("view_count") is not None: lines.append(f" Views: {e['view_count']:,}") if e.get("url"): lines.append(f" URL: {e['url']}") lines.append("") return "\n".join(lines).rstrip() + "\n" - main.py:433-438 (schema)The function signature and docstring define the input schema (url, limit, sort_by, order) and the tool's description.
def list_playlist_videos( url: str, limit: int = 500, sort_by: str = "index", order: str = "asc", ) -> str: - main.py:432-432 (registration)The @mcp.tool() decorator registers this function as an MCP tool.
@mcp.tool()