Instagram Carousel MCP
Designs multi-slide Instagram carousels as SVG, provides live preview, and exports to PNG for upload.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Instagram Carousel MCPCreate a carousel about remote work tips with midnight theme"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Instagram Carousel MCP
An MCP server that designs multi-slide Instagram carousels as crisp SVG, shows them in a live swipeable preview, and exports them to PNG ready to upload. Pure-Python, no system image libraries required.
What it does
Describe a carousel as a list of slide specs → it renders each slide to SVG.
Six slide templates:
title,content,list,quote,stat,cta.Six themes:
midnight,sunset,mono,forest,slate,bubblegum.Three sizes:
portrait(1080×1350, recommended),square(1080×1080),story(1080×1920).A live preview page (swipe / arrow keys / dots) that also rasterises each slide to PNG in the browser — no extra dependencies for export.
Related MCP server: Carousels MCP from Houtini
Architecture
Claude (the MCP client) calls the tools; the server renders SVG, sources media from a provider chain, and (for reels) rasterises + composites with ffmpeg.
flowchart TB
Client["Claude Code / Desktop<br/>(MCP client)"]
subgraph Server["server.py — FastMCP (stdio)"]
Tools["Tools:<br/>trending_topics · create_carousel · create_reel<br/>save_brand · list_brands · update_slide · add_slide<br/>list_themes · get_preview_url · export_png"]
end
subgraph Core["carousel/ package"]
render["render.py<br/>SVG: templates, wrap, highlight,<br/>drop-shadow, logo/image embed, layers"]
themes["themes.py<br/>themes + custom brand theme"]
brand["brand.py<br/>brand profiles + caption (≤5 tags)"]
news["news.py<br/>Google News RSS"]
images["images.py<br/>image + logo sourcing"]
videos["videos.py<br/>Seedance video clips"]
reel["reel.py<br/>rasterize + ffmpeg<br/>scrim · bug · stitch"]
preview["preview.py<br/>HTTP preview server + viewer"]
end
subgraph Ext["External (keyless unless noted)"]
replicate["Replicate<br/>Flux img + Seedance video<br/>(token)"]
pexels["Pexels (key)"]
openverse["Openverse / Picsum"]
wiki["Wikipedia / Wikimedia"]
gnews["Google News RSS"]
end
subgraph Sys["System binaries"]
ffmpeg["ffmpeg"]
rsvg["rsvg-convert"]
end
Out["output/<id>/<br/>slides.svg · PNGs · reel.mp4<br/>caption.txt · music.txt · index.html"]
Browser["Browser / Preview panel"]
Client <-->|MCP| Tools
Tools --> render & brand & news & reel
render --> themes & images
reel --> render & videos & rsvg & ffmpeg
news --> gnews
images --> replicate & pexels & openverse & wiki
videos --> replicate
Tools --> Out
Tools --> preview --> Browser
Out --> previewImage-source policy (per scene/slide): real entities → portrait/logo
(Wikipedia/Commons); news/real-world → background_photo (Pexels→Openverse→
Picsum); concepts → background_query (Flux); motion → video_query (Seedance).
sequenceDiagram
participant C as Claude
participant S as create_reel
participant R as render.py
participant M as images/videos
participant F as ffmpeg + rsvg
C->>S: scenes + brand + caption + music
loop each scene
S->>R: render fg text layer (SVG)
S->>M: bg → video_query (Seedance) / photo / Flux / still
S->>F: rasterize fg; composite bg+scrim+text+bug
end
S->>F: crossfade-stitch scenes → reel.mp4
S->>C: preview_url + caption + musicTools
Tool | Purpose |
| List available themes with colours. |
| Find recent/trending news headlines for a subject (Google News, no key) to pick a timely angle. |
| Build a carousel from slide specs; writes SVGs + preview. Accepts |
| Compile vertical 9:16 scenes (same specs as slides) into an MP4 Reel — Ken-Burns zoom + crossfades, no audio. Needs ffmpeg + rsvg-convert. |
| Replace one slide (by index) and re-render. |
| Insert/append a slide. |
| Create/update a brand profile (handle, logo, custom theme, default hashtags). |
| List saved brand profiles. |
| Get the live preview URL for an existing carousel. |
| Server-side PNG export (optional; needs Playwright). |
Slide fields
title eyebrow?, heading, subheading?, handle?
content eyebrow?, heading, body
list eyebrow?, heading, items[] (strings), ordered? (bool)
quote quote, author?, role?
stat value, label?, caption?
cta eyebrow?, heading, body?, button?, handle?Any slide also accepts handle (e.g. @brand) and page (bool — show n/total).
Images
Slides aren't text-only — you can add photos:
background_image(any slide): a full-bleed photo behind the content. Text automatically switches to light and a gradient scrim is added so it stays readable on top of the image.image(on thecontenttemplate): an inline rounded image card shown between the heading and the body text.
You don't have to supply files at all — use background_query / image_query
with a text description and the server auto-sources a fitting image, trying in
order: Replicate/Flux (AI, needs REPLICATE_API_TOKEN) → Pexels (stock,
needs PEXELS_API_KEY) → Openverse (free CC photos, no key) → Picsum
(random, guaranteed). Results cache under assets/cache/. Override the order
with IMAGE_PROVIDER_ORDER. So image-sourcing works with zero setup (real
photos) and upgrades to custom AI art once a Replicate token is present.
{ "template": "title", "heading": "The State of Remote Work",
"background_query": "minimal home office, soft morning light" }
{ "template": "content", "heading": "Hybrid is winning",
"image_query": "team collaborating in a bright office",
"body": "58% of teams now run hybrid." }Or supply images explicitly: background_image / image values can be a
local file path, an http(s) URL (downloaded), or a data URI — all
base64-embedded so exported PNGs are self-contained. Drop files in assets/:
{ "template": "title", "heading": "2026 Report",
"background_image": "assets/cover.jpg" }
{ "template": "content", "heading": "Hybrid is winning",
"image": "https://example.com/chart.png",
"body": "58% of teams now run hybrid — up from 41% last year." }Reels (vertical video)
create_reel turns a list of scenes (same spec as carousel slides) into a
1080×1920 MP4: each scene gets a subtle Ken-Burns zoom and scenes crossfade into
each other. No baked-in audio — add trending audio in the Instagram app. Brand,
caption, hashtags, and the image options (background_query, portrait, etc.)
all work the same as carousels.
create_reel(scenes=[...], brand="mypage", per_scene=3.2, transition=0.6)
# -> output/<id>/reel.mp4Requires ffmpeg and rsvg-convert (brew install ffmpeg librsvg). 3–7 scenes
works best.
Real-video backgrounds. A scene can have a moving video background instead of a Ken-Burns still:
video_query: "prompt"— generates a real AI clip (Seedance on Replicate; needs.replicate_token, ~$0.10–0.20/clip, cached).video: "path-or-url"— use a clip you already have. Every scene gets a dark scrim plate + text drop-shadow for legibility over busy footage, and the brand bug sits in Instagram's safe zone. Backgrounds can be mixed per scene (some video, some generated stills, some real photos).
Brand your page (theme + logo)
Save a brand profile once, then pass brand: "<name>" to create_carousel and
every slide gets your colours, logo, @handle, and default hashtags.
// save_brand({ profile: { ... } }) -> brands/mypage.json
{
"name": "mypage",
"handle": "@mypage",
"logo": "mypage-logo.png", // path; absolute, or relative to brands/
"base_theme": "midnight", // theme to extend
"theme": { // override only what you want
"accent": "#f472b6",
"bg": ["#1e1b4b", "#312e81"] // "#hex" solid, or ["#a","#b"] gradient
},
"default_hashtags": ["#buildinpublic", "#startup"],
"caption_signature": "Follow @mypage 🚀",
"default_size": "portrait"
}Logo: any PNG/JPG/SVG. It's base64-embedded into each slide (top-left), so exported PNGs are fully self-contained. Drop your logo in
brands/(or give an absolute path) and setlogoto it.Theme: start from a built-in
base_themeand override any ofaccent,bg,bg_angle,text,muted,accent_fg,font_sans,font_serif.Profiles are JSON in
brands/, so they commit to the repo and sync across devices.
Captions & hashtags
create_carousel (and a follow-up) take caption and hashtags. The final
post text is assembled as caption → brand signature → merged hashtags
(per-call + brand defaults, deduped), written to caption.txt, and shown in the
live preview with a Copy button — paste straight into Instagram.
create_carousel(
slides=[...],
brand="mypage",
caption="Speed compounds. Here are 5 moves that cut our cycle time in half.",
hashtags=["#shipfast", "#engineering"],
)Viewing the output interactively
create_carousel returns a preview_url served by the MCP server itself
(e.g. http://127.0.0.1:<port>/<carousel-id>/). Open it in any browser for the
full interactive carousel + Download all (ZIP) button.
In the Claude Code desktop app, the Preview tool reads
~/.claude/launch.json. The included carousel-preview config serves a
carousel directory over http://127.0.0.1:8745/. To preview a specific
carousel, point its --directory arg at output/<carousel-id> and start the
preview. (Claude can do this for you on request.)
Exporting PNGs
Easiest: click Download all (ZIP) in the live preview — rasterises all slides in the browser and bundles them into one ZIP (a single download, so the browser's multi-download block never trips). Zero setup. "Download this slide (PNG)" grabs just the current one.
Headless / programmatic:
export_png. One-time setup:./.venv/bin/python -m pip install playwright ./.venv/bin/python -m playwright install chromium
Run it on another device
Prerequisites: Python 3.10+ and the claude CLI on PATH.
git clone https://github.com/vaheedsk36/instagram-carousel-mcp.git
cd instagram-carousel-mcp
./setup.sh # creates .venv, installs deps, registers the MCP serversetup.sh registers the server at user scope so it's available in every Claude
Code session on that machine. Verify with claude mcp list | grep carousel.
Your brand profiles travel with the repo (they live in brands/), so the same
look is available everywhere.
Manual equivalent if you'd rather not run the script:
python3 -m venv .venv
./.venv/bin/python -m pip install -r requirements.txt
claude mcp add instagram-carousel --scope user -- \
"$(pwd)/.venv/bin/python" "$(pwd)/server.py"Note: the
.venvis machine-specific and git-ignored — always recreate it per device. Only the source andbrands/profiles are committed.
Project layout
server.py MCP server (FastMCP) — the tools
carousel/themes.py theme palettes + custom-theme builder
carousel/brand.py brand profiles (handle, logo, theme, hashtags) + caption assembly
carousel/render.py slide spec -> SVG (text wrapping, templates, logo embedding)
carousel/preview.py background HTTP preview server + viewer HTML (caption + copy)
carousel/export.py optional Playwright SVG->PNG
brands/ saved brand profiles (committed; sync across devices)
output/<id>/ generated slides, manifest, preview, caption.txt, spec
setup.sh one-shot setup for a fresh machine
requirements.txt Python dependencies
test_render.py smoke test covering all templates
test_brand.py smoke test for brand + logo + captionNote on this machine
The Homebrew Python 3.14 bottle shipped with a mis-linked pyexpat (pointed at
the system libexpat which lacks a newer symbol). It was repaired by repointing
the extension at Homebrew's expat:
install_name_tool -change /usr/lib/libexpat.1.dylib \
/opt/homebrew/opt/expat/lib/libexpat.1.dylib <pyexpat.so>
codesign --force -s - <pyexpat.so>A future brew upgrade python@3.14 may revert this; re-run if import xml.parsers.expat fails again.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/vaheedsk36/instagram-carousel-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server