list_my_shorts
List your recent YouTube Shorts by scanning recent uploads and filtering to videos 60 seconds or less.
Instructions
List your recent Shorts — scans the most recent uploads and filters to videos ≤60s. Useful when the Data API doesn't expose a direct Shorts filter.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| max_candidates | No | How many of the most recent uploads to scan. Shorts are detected by duration ≤ 60s after fetching. |
Implementation Reference
- src/tools/shorts.ts:59-96 (handler)The async handler function for 'list_my_shorts'. It paginates through the user's uploads via client.listMyUploads(), filters videos with duration ≤60s (the SHORTS_THRESHOLD_SECONDS constant), collects matching items, and returns a formatted text response listing each Short's ID, title, duration, and views.
async (args) => { const collected: Array<{ video: Video; seconds: number }> = []; let pageToken: string | undefined; let scanned = 0; while (scanned < args.max_candidates) { const batch = Math.min(50, args.max_candidates - scanned); const res = await client.listMyUploads(batch, pageToken); for (const v of res.items) { const s = parseIsoDurationSeconds(v.contentDetails?.duration); if (s !== null && s <= SHORTS_THRESHOLD_SECONDS) { collected.push({ video: v, seconds: s }); } } scanned += res.items.length; if (!res.nextPageToken || res.items.length === 0) break; pageToken = res.nextPageToken; } if (collected.length === 0) { return { content: [ { type: "text" as const, text: `No Shorts found in the most recent ${scanned} upload(s).`, }, ], }; } const lines = [ `Found ${collected.length} Short(s) in the most recent ${scanned} upload(s):`, ...collected.map(({ video, seconds }) => { const title = video.snippet?.title ?? "(untitled)"; const views = video.statistics?.viewCount ?? "0"; return ` ${video.id} — ${title} [${seconds}s, ${views} views]`; }), ]; return { content: [{ type: "text" as const, text: lines.join("\n") }] }; }, ); - src/tools/shorts.ts:20-30 (schema)The input schema for 'list_my_shorts', defined as listMyShortsSchema. It accepts a single optional parameter 'max_candidates' (integer 1-200, default 50) controlling how many recent uploads to scan for Shorts.
const listMyShortsSchema = { max_candidates: z .number() .int() .min(1) .max(200) .default(50) .describe( "How many of the most recent uploads to scan. Shorts are detected by duration ≤ 60s after fetching.", ), }; - src/tools/shorts.ts:55-96 (registration)The tool registration via server.tool('list_my_shorts', ...) inside registerShortsTools(). The description explains that it scans recent uploads and filters to videos ≤60s, since the Data API doesn't expose a direct Shorts filter.
server.tool( "list_my_shorts", "List your recent Shorts — scans the most recent uploads and filters to videos ≤60s. Useful when the Data API doesn't expose a direct Shorts filter.", listMyShortsSchema, async (args) => { const collected: Array<{ video: Video; seconds: number }> = []; let pageToken: string | undefined; let scanned = 0; while (scanned < args.max_candidates) { const batch = Math.min(50, args.max_candidates - scanned); const res = await client.listMyUploads(batch, pageToken); for (const v of res.items) { const s = parseIsoDurationSeconds(v.contentDetails?.duration); if (s !== null && s <= SHORTS_THRESHOLD_SECONDS) { collected.push({ video: v, seconds: s }); } } scanned += res.items.length; if (!res.nextPageToken || res.items.length === 0) break; pageToken = res.nextPageToken; } if (collected.length === 0) { return { content: [ { type: "text" as const, text: `No Shorts found in the most recent ${scanned} upload(s).`, }, ], }; } const lines = [ `Found ${collected.length} Short(s) in the most recent ${scanned} upload(s):`, ...collected.map(({ video, seconds }) => { const title = video.snippet?.title ?? "(untitled)"; const views = video.statistics?.viewCount ?? "0"; return ` ${video.id} — ${title} [${seconds}s, ${views} views]`; }), ]; return { content: [{ type: "text" as const, text: lines.join("\n") }] }; }, ); - src/tools/shorts.ts:7-16 (helper)Helper function parseIsoDurationSeconds() that parses ISO 8601 duration strings (e.g., PT1M30S) into total seconds. Used to determine if a video is a Short (≤60 seconds).
function parseIsoDurationSeconds(duration: string | undefined): number | null { if (!duration) return null; const m = duration.match(/^P(?:(\d+)D)?T?(?:(\d+)H)?(?:(\d+)M)?(?:(\d+(?:\.\d+)?)S)?$/); if (!m) return null; const days = Number(m[1] ?? 0); const hours = Number(m[2] ?? 0); const minutes = Number(m[3] ?? 0); const seconds = Number(m[4] ?? 0); return days * 86400 + hours * 3600 + minutes * 60 + seconds; } - src/tools/shorts.ts:18-18 (helper)Constant SHORTS_THRESHOLD_SECONDS = 60, which defines the maximum duration in seconds for a video to be considered a Short.
const SHORTS_THRESHOLD_SECONDS = 60;