ig_publish_carousel
Publish Instagram carousel posts with 2-10 images or videos using the Meta MCP server. Upload media via URLs, add captions, and include alt text for accessibility.
Instructions
Publish a carousel (album) post with 2-10 images/videos. Each item needs an image_url or video_url.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| items | Yes | Array of media items | |
| caption | No | Post caption | |
| location_id | No | Facebook Page location ID |
Implementation Reference
- src/tools/instagram/publishing.ts:82-132 (handler)The implementation of the `ig_publish_carousel` tool, which registers the tool, handles the schema validation, and executes the carousel publishing logic in 3 steps: creating child containers, creating the carousel container, and publishing the carousel.
server.tool( "ig_publish_carousel", "Publish a carousel (album) post with 2-10 images/videos. Each item needs an image_url or video_url.", { items: z.array(z.object({ type: z.enum(["IMAGE", "VIDEO"]).describe("Media type"), url: z.string().url().describe("Public HTTPS URL of the media"), alt_text: z.string().optional().describe("Alt text for this image item"), })).min(2).max(10).describe("Array of media items"), caption: z.string().optional().describe("Post caption"), location_id: z.string().optional().describe("Facebook Page location ID"), }, async ({ items, caption, location_id }) => { try { // Step 1: Create child containers const childIds: string[] = []; for (const item of items) { const params: Record<string, unknown> = { is_carousel_item: true }; if (item.type === "IMAGE") { params.image_url = item.url; if (item.alt_text) params.alt_text = item.alt_text; } else { params.video_url = item.url; params.media_type = "VIDEO"; } const { data: child } = await client.ig("POST", `/${client.igUserId}/media`, params); const childId = (child as { id: string }).id; if (item.type === "VIDEO") { await waitForContainer(client, childId); } childIds.push(childId); } // Step 2: Create carousel container const carouselParams: Record<string, unknown> = { media_type: "CAROUSEL", children: childIds.join(","), }; if (caption) carouselParams.caption = caption; if (location_id) carouselParams.location_id = location_id; const { data: carousel } = await client.ig("POST", `/${client.igUserId}/media`, carouselParams); const carouselId = (carousel as { id: string }).id; // Step 3: Publish const { data, rateLimit } = await client.ig("POST", `/${client.igUserId}/media_publish`, { creation_id: carouselId, }); return { content: [{ type: "text", text: JSON.stringify({ ...data as object, _rateLimit: rateLimit }, null, 2) }] }; } catch (error) { return { content: [{ type: "text", text: `Publish carousel failed: ${error instanceof Error ? error.message : String(error)}` }], isError: true }; } } );