LinkedIn Carousel Maker

Let your AI agent make the carousel

Everything the editor can do is also available to software: an MCP server for AI agents, a REST API for scripts, and a skill file that teaches an agent how to write a good LinkedIn carousel with them. All three sit on the same service layer as the app, so a carousel made by your agent opens in the editor, saves to your projects, and exports to the same PDF.

Typical use: you tell Claude Code, Codex or Cursor “turn this article into a LinkedIn carousel”. The agent calls generate_carousel, reads the result, tightens two slides with edit_carousel, and hands you a PDF link from export_carousel. You review it in the editor or post it as is.

On this page

1. Create an API key

Sign in, open Settings → API keys and create a key. Keys start with lcm_, are shown once, and can be revoked and recreated at any time. A free account has one key. Store it in your environment as LCM_API_KEY, not in a chat window and not in a repository:

# ~/.zshrc, ~/.bashrc, or a git-ignored .env in the project
export LCM_API_KEY=lcm_your_key_here

Every request then sends it as a bearer token, Authorization: Bearer $LCM_API_KEY. Rotating the key is one visit to Settings → API keys (also linked from your dashboard) and one update of the variable; nothing in the agent setup changes.

2. Connect your harness

Pick your agent below. Each one has a setup prompt: with LCM_API_KEY set in your environment, copy the prompt, paste it into the agent, and the agent does the rest: connects the MCP server with Authorization: Bearer $LCM_API_KEY, installs the skill, checks the connection, then asks you for a topic. The key never goes through the chat. Prefer to do it by hand? The manual steps follow each prompt.

The MCP server is at https://linkedincarouselmaker.com/mcp: Streamable HTTP, stateless (one server per request, so it runs on serverless), JSON responses, POST only. Any MCP client that can send a custom header works.

Claude Code

Terminal or VS Code extension. Paste this as your first message in the project you want to work from:

Set up the LinkedIn Carousel Maker for me, then make a carousel.

My API key is in the environment variable LCM_API_KEY. Never ask me to paste it and never print it.

1. Connect the MCP server by creating or merging .mcp.json in this project with:
   { "mcpServers": { "lcm": { "type": "http", "url": "https://linkedincarouselmaker.com/mcp", "headers": { "Authorization": "Bearer ${LCM_API_KEY}" } } } }
   Keep the ${LCM_API_KEY} placeholder as written; Claude Code expands it from my environment at runtime.
2. Install the skill so you know how to write a good carousel:
   mkdir -p .claude/skills/linkedin-carousel && curl -fsSL -o .claude/skills/linkedin-carousel/SKILL.md https://linkedincarouselmaker.com/skills/linkedin-carousel/SKILL.md
3. Tell me to approve the new project server when Claude Code asks, then verify: list the lcm tools and call get_me. Tell me how many AI generations and edits I have left this month. If the key is rejected, tell me to set LCM_API_KEY from Settings → API keys and restart you.
4. Read the skill, then ask me for a topic, pasted text or an article URL. Follow the skill: generate_carousel, get_carousel, review every slide against the writing rules, fix with edit_carousel or update_carousel, show me the slide texts and caption, apply my changes, then export_carousel as PDF and give me the download link.

What happens. Claude Code writes a project .mcp.json whose header reads ${LCM_API_KEY} (expanded from your environment at runtime, so the file is safe to commit), downloads the skill, asks you to approve the new server, calls get_me to prove the key works and read your remaining credits, then asks for your topic. The skill loads on demand whenever a carousel comes up, in this project and any future session here. For every project, install the skill to ~/.claude/skills/linkedin-carousel/SKILL.md instead.

Manual steps. The same two files by hand:

// .mcp.json in the project root
{
  "mcpServers": {
    "lcm": {
      "type": "http",
      "url": "https://linkedincarouselmaker.com/mcp",
      "headers": { "Authorization": "Bearer ${LCM_API_KEY}" }
    }
  }
}
mkdir -p .claude/skills/linkedin-carousel
curl -fsSL -o .claude/skills/linkedin-carousel/SKILL.md https://linkedincarouselmaker.com/skills/linkedin-carousel/SKILL.md

For every project instead of one, run claude mcp add --scope user --transport http lcm https://linkedincarouselmaker.com/mcp --header "Authorization: Bearer $LCM_API_KEY" (your shell fills the value into Claude Code's private user config) and put the skill in ~/.claude/skills/. Then ask: “Make a LinkedIn carousel from this article: …”.

Codex CLI

Paste this into Codex in the project you want to work from:

Set up the LinkedIn Carousel Maker for me, then make a carousel.

My API key is in the environment variable LCM_API_KEY. Never ask me to paste it and never print it in chat.

1. Read $LCM_API_KEY from the environment and add this MCP server to ~/.codex/config.toml (create the file if needed, keep anything already there), filling the header from the variable:
   [mcp_servers.lcm]
   url = "https://linkedincarouselmaker.com/mcp"
   http_headers = { Authorization = "Bearer <value of LCM_API_KEY>" }
   That file is private to my machine; do not copy the key anywhere else.
2. Download https://linkedincarouselmaker.com/skills/linkedin-carousel/SKILL.md and append its contents to AGENTS.md in this project, under a heading "LinkedIn carousel skill". It holds the workflow and writing rules.
3. Tell me to restart Codex so the server loads, and stop.
After the restart: call the lcm tool get_me and tell me my remaining AI generations and edits. Then ask me for a topic, pasted text or an article URL and follow the skill: generate_carousel, get_carousel, review every slide against the writing rules, fix with edit_carousel or update_carousel, show me the slide texts and caption, apply my changes, then export_carousel as PDF and give me the download link.

What happens. Codex reads $LCM_API_KEY from your shell and writes the server into ~/.codex/config.toml, a file private to your machine, so the key is never typed into the chat. It saves the skill next to your project instructions so it is read on every run, and asks you to restart it once (MCP servers load at start). After the restart it calls get_me and asks for your topic.

Manual steps.

cat >> ~/.codex/config.toml <<EOF

[mcp_servers.lcm]
url = "https://linkedincarouselmaker.com/mcp"
http_headers = { Authorization = "Bearer $LCM_API_KEY" }
EOF
curl -fsSL https://linkedincarouselmaker.com/skills/linkedin-carousel/SKILL.md >> AGENTS.md

Codex reads AGENTS.md at the start of every session, so appending the skill there is the reliable way to give it the writing rules. If your Codex version supports a skills folder, save the file as ~/.codex/skills/linkedin-carousel/SKILL.md instead and keep AGENTS.md clean.

Cursor

Open the project in Cursor, start an Agent chat, and paste:

Set up the LinkedIn Carousel Maker for me, then make a carousel.

My API key is in the environment variable LCM_API_KEY. Never ask me to paste it and never print it.

1. Create .cursor/mcp.json in this project (merge if it exists) with:
   { "mcpServers": { "lcm": { "url": "https://linkedincarouselmaker.com/mcp", "headers": { "Authorization": "Bearer ${env:LCM_API_KEY}" } } } }
   Keep the ${env:LCM_API_KEY} placeholder as written; Cursor reads it from my environment.
2. Download https://linkedincarouselmaker.com/skills/linkedin-carousel/SKILL.md and save it as .cursor/rules/linkedin-carousel.mdc with this front matter on top:
   ---
   description: Make, write or export a LinkedIn carousel through the LinkedIn Carousel Maker MCP tools
   alwaysApply: false
   ---
3. Ask me to enable the "lcm" server in Cursor Settings → MCP, then wait.
4. Verify: call the lcm tool get_me and tell me my remaining AI generations and edits. If the key is rejected, tell me to set LCM_API_KEY from Settings → API keys and restart Cursor.
5. Ask me for a topic, pasted text or an article URL and follow the rule: generate_carousel, get_carousel, review every slide against the writing rules, fix with edit_carousel or update_carousel, show me the slide texts and caption, apply my changes, then export_carousel as PDF and give me the download link.

What happens. Cursor writes .cursor/mcp.json with the header Bearer ${env:LCM_API_KEY}, which Cursor fills from your environment, and a rule file holding the skill. It asks you to approve the new server in Settings → MCP (a one-time toggle), then calls get_me and asks for your topic. The rule carries the skill's description, so Cursor attaches it whenever a carousel comes up.

Manual steps.

// .cursor/mcp.json   (or ~/.cursor/mcp.json for every project)
{
  "mcpServers": {
    "lcm": {
      "url": "https://linkedincarouselmaker.com/mcp",
      "headers": { "Authorization": "Bearer ${env:LCM_API_KEY}" }
    }
  }
}

Launch Cursor from a shell where the variable is set, or add it to your login environment, so the interpolation finds it.

mkdir -p .cursor/rules
{ printf -- '---\ndescription: Make, write or export a LinkedIn carousel through the LinkedIn Carousel Maker MCP tools\nalwaysApply: false\n---\n'; curl -fsSL https://linkedincarouselmaker.com/skills/linkedin-carousel/SKILL.md; } > .cursor/rules/linkedin-carousel.mdc

Claude Desktop and Claude.ai

Claude Desktop cannot run a setup prompt before it is connected, and its custom connectors do not send a bearer header, so this one is manual. Bridge through mcp-remote, a small local process that adds the header. Desktop does not see your shell environment, so the key goes into the config's env block (a private file on your machine) and mcp-remote reads it as ${LCM_API_KEY}. Needs Node.js installed. Edit the config file:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\\Claude\\claude_desktop_config.json
{
  "mcpServers": {
    "lcm": {
      "command": "npx",
      "args": [
        "-y", "mcp-remote", "https://linkedincarouselmaker.com/mcp",
        "--header", "Authorization: Bearer ${LCM_API_KEY}"
      ],
      "env": { "LCM_API_KEY": "lcm_your_key_here" }
    }
  }
}

Restart Claude Desktop; the tools appear under the hammer icon. For the skill, create a Project and paste the contents of SKILL.md into its instructions, then chat inside that project. Claude.ai in the browser has no header-capable connector today, so use Desktop for MCP; its Projects still take the skill text as instructions and you can call the REST API from the Analysis tool if you prefer.

Any other agent, script or automation

Two paths. If your tool speaks MCP over HTTP with custom headers (Windsurf, Zed, Cline, Continue, LangGraph, the Agents SDKs), point it at https://linkedincarouselmaker.com/mcp with Authorization: Bearer lcm_… and give it the skill text as a system instruction. If it does not, use the REST API: set the key in the environment and let the agent or script call the routes in section 5 with Authorization: Bearer $LCM_API_KEY. This prompt works for any agent that can run shell commands:

Set up the LinkedIn Carousel Maker API for me, then make a carousel.

My API key is in the environment variable LCM_API_KEY. Never ask me to paste it and never print it.

1. Read https://linkedincarouselmaker.com/openapi.yaml for the routes and https://linkedincarouselmaker.com/skills/linkedin-carousel/SKILL.md for the workflow and writing rules. Base URL https://linkedincarouselmaker.com/api/v1, header "Authorization: Bearer $LCM_API_KEY" on every request.
2. Verify with GET /me and tell me my remaining AI generations and edits. If it returns 401, tell me to set LCM_API_KEY from Settings → API keys.
3. Ask me for a topic, pasted text or an article URL. Then: POST /carousels/generate, GET /carousels/{id}, review every slide against the writing rules, fix with POST /carousels/{id}/edit or PUT /carousels/{id}, show me the slide texts and caption, apply my changes, then POST /carousels/{id}/export with {"format":"pdf"} and give me the download link.

Manual steps. With the variable exported, any script can use it:

curl -s https://linkedincarouselmaker.com/api/v1/me -H "Authorization: Bearer $LCM_API_KEY"

Once connected, ask the agent to list its tools. You should see the eleven below. Every MCP call, including initialize and tools/list, counts toward the daily request budget.

3. The tools

ToolInputReturnsCosts
list_layoutsnone{ layouts }: the 13 layouts with allowed kinds, field keys, types, labels and word limitsrequest
list_templatesnone{ templates }: id, name, description, category, slideCountrequest
generate_carouselsource { type: topic | text | url, value }, slides? 5–12, tone?, language?, preset?{ carousel, saved, truncated, usage }request + 1 AI generation
get_carouselid{ id, data, updatedAt }request
edit_carouselid, prompt ≤ 500 chars, mode: slide | carousel, slideId?{ carousel, usage }request + 1 AI edit
update_carouselcarousel, expectedUpdatedAt?{ updatedAt }; 409 conflict if it changed sincerequest
create_carouselcarousel{ id, updatedAt }request
export_carouselid, format: pdf | png{ url, expiresAt }: a temporary downloadrequest
list_carouselsnone{ carousels }: newest firstrequest
delete_carouselid{ ok: true }request
get_menone{ user, usage }request

Errors come back as tool results with isError: true and a body of { error: { code, message } }, the same shape the REST API uses.

4. The flow that works

  1. Generate. generate_carousel with a topic, pasted text or a URL. It writes 5 to 12 slides, picks a layout per slide, sets a palette and font pairing, writes the caption, and saves the carousel. If saved is false the 10-carousel cap is full: delete one and create_carousel with the returned data. If truncated is true the source was over 12,000 characters and only the first part was used.
  2. Read and review. get_carousel returns the full JSON. The skill file below carries the writing rules an agent should check: hook under 8 words, one idea per slide, no clichés, a specific call to action, exactly three hashtags.
  3. Fix. edit_carousel with mode: "slide" for one weak slide or mode: "carousel" for tone, order or flow. Each costs one AI edit. For a typo, a number or a layout swap, change the JSON and call update_carousel instead; that costs no AI credit. Pass expectedUpdatedAt so a concurrent change from the editor returns 409 rather than being overwritten.
  4. Export. export_carousel with pdf for a LinkedIn document post or png for a ZIP of slides. The URL is temporary; download it right away. Carousels also stay in your projects, so you can open one in the editor and download from there.

No AI needed? list_templates then create_carousel starts from one of the 25 templates and costs no credit.

5. REST API

Same operations, same bearer key, base URL https://linkedincarouselmaker.com/api/v1. The OpenAPI 3.1 document is at /openapi.yaml.

RouteMCP equivalent
GET /api/v1/meget_me
GET /api/v1/layoutslist_layouts
GET /api/v1/templateslist_templates
GET /api/v1/carouselslist_carousels
POST /api/v1/carouselscreate_carousel
POST /api/v1/carousels/generategenerate_carousel
GET /api/v1/carousels/{id}get_carousel
PUT /api/v1/carousels/{id}update_carousel
DELETE /api/v1/carousels/{id}delete_carousel
POST /api/v1/carousels/{id}/editedit_carousel
POST /api/v1/carousels/{id}/exportexport_carousel

Generate from a URL

curl -X POST https://linkedincarouselmaker.com/api/v1/carousels/generate \
  -H "Authorization: Bearer $LCM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": { "type": "url", "value": "https://example.com/your-article" },
    "slides": 8,
    "tone": "conversational"
  }'

Export the result

curl -X POST https://linkedincarouselmaker.com/api/v1/carousels/CAROUSEL_ID/export \
  -H "Authorization: Bearer $LCM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "format": "pdf" }'
# → { "url": "https://…/export.pdf", "expiresAt": "…" }

6. The agent skill

Tools tell an agent what it can call. The skill tells it how to make a carousel worth posting. It is one Markdown file, SKILL.md, with a front matter description that lets the agent pick it up when someone asks for a LinkedIn carousel. It covers:

  • Connect: how to ask for the key and add the server, with the REST fallback.
  • Workflow: generate, read, fix, show the person, export; when to spend an AI edit and when to hand-edit.
  • Writing rules: hook, one idea per slide, specifics over generic, layout variety, accent words, the closing call to action, the caption format.
  • Layouts: all 12 with the slide kind, when to use each, and which need an image.
  • Slide counts by content type, limits and error codes with what to tell the person, and a minimal valid carousel JSON.

Install

Each harness section above installs it for you: Claude Code as a skill file, Codex via AGENTS.md, Cursor as a rule, Claude Desktop as project instructions. The skill is tested against the code, so its limits, tool names and layout ids match what the server does. Download it directly:

curl -fsSL -O https://linkedincarouselmaker.com/skills/linkedin-carousel/SKILL.md

7. Limits and errors

Free account: 5 AI generations and 30 AI edits or captions per month, 10 saved carousels, 1 API key, 100 requests per UTC day across the API and MCP combined. Failed AI calls refund their credit. generate_carousel, edit_carousel and get_me return usage, so an agent can check what is left before spending more.

CodeStatusMeaning
invalid_key401The key is wrong or revoked. Create a new one in Settings → API keys.
invalid_body400The body failed validation. The message names the field.
limit_reached402Monthly AI credits used up, or the 10-carousel cap is hit. Delete a carousel or wait for the next month. Hand edits through update_carousel cost no AI credit.
email_unverified403The account email is not verified, so AI generation and edits are blocked. Click the link in the verification email, then retry.
conflict409The carousel changed since you read it. Read it again, re-apply, retry once.
ai_invalid_output422The model returned a carousel that failed validation. Retry once; the credit was refunded.
rate_limited429100 requests today are spent. Retry-After says how many seconds until UTC midnight.
export_unavailable501This deployment has server-side export switched off. Export from the editor instead.
ai_unavailable502The AI provider failed. The credit was refunded; retry once.

8. The carousel JSON

One schema is the contract between the editor, the AI, the API and the export. A carousel has a title, a caption, settings (preset linkedin-4x5 or linkedin-1x1, theme colours, fonts, author, counter, swipe hint, pattern) and 1 to 20 slides. Each slide has a kind (intro, content, outro), a layout id, and fields of the form { type, on, value }. Call list_layouts for the exact field keys and word limits of every layout, and see the skill file for a minimal valid document. Text and list fields also take an optional style object (size, weight, italic, align, colour, font, line height, tracking) that applies to the whole field, never to single words. The canvas layout instead holds up to 24 hand-placed text and icon elements whose x, y, w and size are slide pixels from the top-left corner, inside a content area 72 px from each edge with a 120 px band at the bottom. AI edits only rewrite text: styles, icons, hidden fields and Canvas positions stay as they are, AI never generates Canvas slides, and on a Canvas slide it may change only the text of existing text elements.

What is next

This is the part of the product we keep investing in. The API is versioned at /api/v1 and changes are additive. If your harness needs something the tools do not cover, the editor keeps working on anything the agent saved, so nothing is locked in.