threads_publish_video
Publish video posts on Threads with captions, topic tags, accessibility alt text, and reply controls. Waits for video processing to complete.
Instructions
Publish a video post on Threads. Waits for video processing. Supports topic tag, quote post, alt text, and spoiler flag.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| video_url | Yes | Public HTTPS URL of the video (MP4/MOV, max 1GB, up to 5 min) | |
| text | No | Caption text | |
| reply_control | No | Who can reply | |
| topic_tag | No | Topic tag for the post | |
| quote_post_id | No | ID of a post to quote | |
| alt_text | No | Alt text for accessibility (max 1000 chars) | |
| is_spoiler | No | Mark content as spoiler |
Implementation Reference
- src/tools/threads/publishing.ts:97-129 (handler)The threads_publish_video tool handler and its schema registration. It handles video publication by creating a container, waiting for processing, and then publishing the container ID.
server.tool( "threads_publish_video", "Publish a video post on Threads. Waits for video processing. Supports topic tag, quote post, alt text, and spoiler flag.", { video_url: z.string().url().describe("Public HTTPS URL of the video (MP4/MOV, max 1GB, up to 5 min)"), text: z.string().max(500).optional().describe("Caption text"), reply_control: z.enum(["everyone", "accounts_you_follow", "mentioned_only", "parent_post_author_only", "followers_only"]).optional().describe("Who can reply"), topic_tag: z.string().max(50).optional().describe("Topic tag for the post"), quote_post_id: z.string().optional().describe("ID of a post to quote"), alt_text: z.string().max(1000).optional().describe("Alt text for accessibility (max 1000 chars)"), is_spoiler: z.boolean().optional().describe("Mark content as spoiler"), }, async ({ video_url, text, reply_control, topic_tag, quote_post_id, alt_text, is_spoiler }) => { try { const params: Record<string, unknown> = { media_type: "VIDEO", video_url }; if (text) params.text = text; if (reply_control) params.reply_control = reply_control; if (topic_tag) params.topic_tag = topic_tag; if (quote_post_id) params.quote_post_id = quote_post_id; if (alt_text) params.alt_text = alt_text; if (is_spoiler) params.is_spoiler_media = true; const { data: container } = await client.threads("POST", `/${client.threadsUserId}/threads`, params); const containerId = (container as { id: string }).id; await waitForThreadsContainer(client, containerId); const { data, rateLimit } = await client.threads("POST", `/${client.threadsUserId}/threads_publish`, { creation_id: containerId, }); return { content: [{ type: "text", text: JSON.stringify({ ...data as object, _rateLimit: rateLimit }, null, 2) }] }; } catch (error) { return { content: [{ type: "text", text: `Publish video failed: ${error instanceof Error ? error.message : String(error)}` }], isError: true }; } } );