upload_caption
Add caption tracks to YouTube videos using SRT or WebVTT files. Set language, track name, and mark as draft for review.
Instructions
Upload a caption track (SRT or WebVTT) to a video. Creates a new track — use a distinct name per language/track, or is_draft=true while iterating.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| video_id | Yes | Video ID the caption belongs to. | |
| language | Yes | BCP-47 language code, e.g. 'en', 'en-US', 'es', 'ja'. Must match a language the video supports. | |
| name | No | Caption track name shown in the player's caption menu. Empty string for the default track. | |
| caption_text | Yes | Caption content as a string (SRT or WebVTT format). Source this from a file or the model's output. | |
| format | No | Content type of caption_text: 'srt' (SubRip, application/x-subrip) or 'vtt' (WebVTT, text/vtt). | srt |
| is_draft | No | Draft captions aren't visible to viewers. Useful while reviewing auto-translations. |
Implementation Reference
- src/youtube/client.ts:231-273 (helper)The YouTube API helper that performs the multipart upload of the caption track (insertCaption). Constructs a multipart/related body with JSON metadata and caption content.
async insertCaption(params: { videoId: string; language: string; name: string; isDraft: boolean; body: Uint8Array; captionContentType: string; }): Promise<unknown> { const boundary = `youtube-mcp-${Date.now().toString(16)}`; const metadata = JSON.stringify({ snippet: { videoId: params.videoId, language: params.language, name: params.name, isDraft: params.isDraft, }, }); const opening = Buffer.from( `--${boundary}\r\nContent-Type: application/json; charset=UTF-8\r\n\r\n${metadata}\r\n--${boundary}\r\nContent-Type: ${params.captionContentType}\r\n\r\n`, "utf-8", ); const closing = Buffer.from(`\r\n--${boundary}--\r\n`, "utf-8"); const body = Buffer.concat([opening, Buffer.from(params.body), closing]); const url = new URL(`${UPLOAD_API}/captions`); url.searchParams.set("part", "snippet"); url.searchParams.set("uploadType", "multipart"); const token = await this.ensureAccessToken(); const res = await fetch(url.toString(), { method: "POST", headers: { Authorization: `Bearer ${token}`, "Content-Type": `multipart/related; boundary=${boundary}`, "Content-Length": String(body.length), }, body, }); if (!res.ok) { throw new Error( `YouTube caption insert failed: ${res.status} ${await res.text()}`, ); } return res.json();