Walkthroughs · Updated · 10 min read

How to Make Instagram Campaigns from Claude Code: the Instagram MCP Walkthrough

How to make Instagram campaigns from Claude Code, step by step: install the Instagram MCP, connect your account, shape the brief, pick a direction, render the grid, and get captions. Two real campaigns ran $2.95 and $15.76.

You make an Instagram campaign from Claude Code by adding Marta, an Instagram MCP server, with one command, then asking for a campaign in plain language. From there I research your real brand, write a brief you can edit, show you four art directions as actual rendered images, price the asset plan before spending anything, then render the grid, preview it inside your real feed, and write the captions in your voice. Two campaigns shipped this way came to $2.95 and $15.76 end to end. You start with 450 free credits, and 1 credit is $0.01, so the first one can cost you nothing.

What you need before you start

  • Claude Code, on a machine where you can run npx.
  • A Marta account. Signing up gives you 450 free credits, which is enough to research a brand, render a set of samples, and see the whole flow work.
  • Something to point me at: a product URL, a codebase, or a plain description of what you sell. A public Instagram handle is not required, but it makes every step better, because it is what I ground the look and the caption voice in.
  • Optional, for video: ffmpeg on your PATH. Images, grids, previews, and captions need nothing extra; reels, pan and zoom clips, and the launch film are assembled locally with ffmpeg.

Step 1: Install the Instagram MCP server and the skill

One command, two halves:

claude mcp add marta -- npx -y heymarta-mcp && npx -y heymarta-mcp install-skill

The first half registers the MCP server, which is the toolbox: 29 tools covering account and credits, brand research, image and video generation, batching, previews, posting, and narration. The second half installs the skill, which is the judgment: the order of operations, the checkpoints, the cost discipline. Tools alone would leave you improvising the process; the skill is what makes the run feel like working with a studio. There is a longer piece on what install-skill actually adds.

Restart Claude Code afterwards so it picks up the new tools.

Step 2: Connect your account

The first time I need your account I run connect_account, and it pairs in the browser so you never copy a key by hand. It works in two phases:

  1. The first call prints a pairing link. Open it, check the page shows the same short code, and click Approve and connect.
  2. Call it again (or just say you approved) and it collects the key and stores it in ~/.marta.

Pairing links expire after 10 minutes, and you can revoke a key from the dashboard at any time. If you would rather do it by hand, mint a key under Dashboard, API keys, and pass it in as MARKETING_AGENT_API_KEY instead.

Two more things get settled here, both free. get_balance reports your credits alongside the live price list, and configure_output sets where files land. The default output base is ~/Documents/marketing-agent, and every project lives under it as <base>/<brand>/<campaign>/.

Step 3: Ask for a campaign in plain language

Then you just ask, the same way you would ask for a refactor:

hey /marta can you help me create a campaign for https://aesop.com/?

That is genuinely enough. There is no requirements form, because inferring the audience, the angle, and the deliverables is the job, not your homework. If you do have constraints, say them in the same sentence: a launch date, a product to feature, a market, "no faces", "keep it typographic". They get folded into the brief instead of interrogated out of you.

Step 4: Let the brand research run

Before anything is generated, I go and look at what you already have. This whole step is free; research spends no credits.

  • Your site. I read it for the product, the positioning, the palette, and the tone. If a plain fetch gets blocked or the site renders in the browser only, that is not a dead end: scrape_web_images drives a real headless browser to pull the actual imagery.
  • Your real Instagram. scrape_instagram saves the recent posts, a contact sheet, your profile photo, and captions.md plus captions.json into <base>/<brand>/brand_identity/instagram/. That folder sits at the brand level, not the campaign level, so every future campaign for you reuses it.
  • Your actual products. add_product saves a real pack shot under a short name, so hero shots can reference the true object instead of a generic stand-in.

I read the contact sheet myself to lock the palette and the medium, and I read the captions to learn how you write. That grounding is the difference between work that looks like your brand and work that looks like a template. There is more on how the research pass works.

Step 5: Shape the brief before anything is generated

Now the project gets scaffolded. init_project creates a date stamped campaign folder with refs/ and out/{explorations,grid,stills,video}, plus the shared brand_identity/ at the brand level. set_brand stores the kit: palette, ink, paper, accent, fonts, narration voice, positioning.

Two fields in that kit do more work than the rest. A style anchor is one canonical reference image that gets attached automatically to every single generation, and a frozen guidance line is one art direction sentence reused verbatim on every tile. Cohesion is engineered, not described: a set reads as one hand because the same anchor and the same words are on every render, not because a prompt asked nicely. That is the mechanic behind a grid that reads as one feed.

Then I write brief.md into the project: the brand read, the campaign angle, the audience I inferred, three or four proposed directions, and a rough sense of deliverables. And then I stop.

This is a real checkpoint, not a formality. Change the angle, cut a direction, correct the audience, tell me the deliverables are wrong. Nothing has been generated and nothing has been charged.

Step 6: Pick a direction from four real samples

When the brief feels right, I offer samples. This is an offer, never an automatic spend: I quote the real cost first by calling estimate for four graphics, and I quote it live from the API rather than from memory, because prices change and a remembered price is a guess.

On your yes, four generate_graphic calls fire in parallel, about a minute for all four, and land in out/explorations/ as sample-*.png, one per direction. Then every sample gets previewed inside your real feed with preview_in_feed, into out/explorations/previews/, so you are not judging a direction on a white background; you are seeing it as the newest tile above your actual posts.

You open the files, and you pick one, or you tell me what to change about it. That is the only question at this stage. What to make comes next.

Step 7: Agree the asset plan and its price

Direction locked, we decide the mix. I propose types, counts, and the reasoning: a grid to seed the feed, a photoreal hero for the pinned post, a reel, and where one image cannot tell the story, a carousel instead of a single tile, which generate_carousel renders as 2 to 10 swipeable slides under one locked style.

You add, cut, and re-count. Only once we agree do I pull the real product shots and put the whole thing on the table as one number: total credits and total dollars for the agreed mix. Then I wait for an explicit yes.

The safety net underneath is a pre-flight check. If the balance cannot cover a call, it refuses before charging anything and tells you what the call needs against what you have, so a run never stalls halfway through having already taken your money.

Step 8: Watch the grid render

Any wave of two or more generations goes through start_batch, which fires them all at once and returns a job id. I then loop batch_status, which blocks until the next job lands, so you get a live line every time something finishes: how many are done out of the total, which asset it was, its full path, and your current balance. No silent multi minute pause.

The wave usually comes in two parts, because motion needs its still first:

  • Wave one, independent. Every final image: grid tiles, hero shots, standalone graphics, all into out/grid/ as 1-name.png, 2-name.png, and so on. A carousel post gets its own folder, out/grid/3-lineup/slide_01.png and up. Text-bearing posts are built from a structured spec, where the exact strings, their placement, the pinned palette, and the medium are all declared, which is what makes typography come out spelled correctly and on brand rather than approximated.
  • Wave two, dependent. animate_still turns a finished still into a short clip with real motion, ken_burns does a slow pan and zoom locally for free, and generate_ugc renders a voiceover led video with captions and an end card. Video is the most expensive thing here, which is why it is always quoted separately.

Step 9: Preview the drop inside your real feed

The moment the posts finish, whatever the count, preview_in_feed renders out/grid/preview.png: your new posts as the newest tiles, your real scraped posts filling the rest of the grid. A three post drop shows as three new plus six real. If there is genuinely no scraped feed, instagram_mockup renders the posts on their own as a fallback.

Two details that matter for quality control. The preview returns a byte size and a short hash, so after a regeneration you compare the stamp instead of squinting at a nine cell grid and guessing whether tile four changed. And contact_sheet montages the set into one labelled sheet, which is how each asset gets scored against the brand and how the misses get regenerated. Both tools are free.

Step 10: Get captions in your brand voice

Every feed post needs a caption, and the voice comes from your own posts, not from a generic template. I read the captions.md that the research step saved and infer the pattern: tone, sentence length, whether you use emoji and which, how many hashtags and where they sit, how you close a post. That profile is saved to brand_identity/voice.md and reused by every later campaign.

Then one caption per post, mapped to the images, written into two files: out/grid/captions.md for you to read, and out/grid/captions.json for the poster to read. Writing is free; captions cost no credits at all.

Step 11: Take delivery, then post if you want to

Delivery is campaign.md in the project root, linking the grid, the captions, the feed preview, and any video, along with every path and the total credits spent on the run.

Publishing is optional and free. instagram_login opens a real browser window where you sign in once yourself; the session is saved locally in your brand folder and never leaves your machine. Then instagram_post with dry_run set to true rehearses the whole thing, uploading and filling the caption but stopping before Share, and the same call without the dry run publishes. You do not paste captions, because they are pulled from captions.json by matching the image filenames. Post one at a time so you can confirm each one, and glance at the app afterwards, since Instagram changes its interface often and any automation against it is best effort.

There is one more optional close: generate_campaign_film cuts your finished assets into a short launch film with title cards and a call to action end card. Silent is free. With music it is a few credits, quoted before it runs.

What a campaign actually costs

Everything is metered to the cent. 1 credit is $0.01, you start with 450 free credits, and generation is the only thing that spends them. Two real campaigns: a small one, meaning brand work, a nine tile grid, a few hero shots, and captions, came to $2.95. A bigger one with more hero shots and a reel came to $15.76.

What is free: all of the research (site reading, feed scraping, product shots), estimate, get_balance, in-feed previews, mockups, contact sheets, pan and zoom clips, captions, the delivery write up, and posting.

What is metered: image generation, carousel slides, logos, image edits, image to video, UGC video, and a scored launch film.

Three guarantees sit around the money. Every spend is quoted with estimate and confirmed before it happens. A generation that fails is refunded automatically, so you are never charged for something that did not land. And prices are read live from the API rather than recalled, so the number you are shown is the number you pay. The line by line cost breakdown walks through where those two totals came from.

What lands on your machine

Everything is a real file in a predictable place, ready to post or hand to someone else:

~/Documents/marketing-agent/
  <brand>/
    brand_identity/
      instagram/        real feed, contact sheet, captions.md, captions.json
      voice.md          the caption voice profile, reused every campaign
      product/          real pack shots
    <YYMMDD_HHMM>_<campaign>/
      brief.md          the brief you shaped
      refs/
      out/
        explorations/   the four direction samples + their in-feed previews
        grid/           the finished posts, preview.png, captions.md, captions.json
        video/          reels, animated stills, launch film
      campaign.md       the delivery note: every path, total credits spent

When something fails in the middle

Nothing here is a dead end, and none of it leaves you charged for work you did not get.

  • A render errors. Failed generations are refunded automatically. Check with get_balance if you want to see it, then retry, optionally with a tweaked prompt.
  • The balance runs short. The pre-flight refuses before charging and tells you the gap. From there you either trim the plan to fit or top_up, which hands you a checkout link for a credit pack.
  • A site or a feed will not load. A 403 usually means one fetch method was blocked, not that your brand is unreachable. The browser backed tools get through most of it, and an empty Instagram scrape is usually a transient rate limit worth one retry.
  • Something stays broken. There is a person at the other end: see help or email hello@heymarta.ai.

Common questions

Do I need an Instagram account connected to make a campaign?

No. Research only reads public posts, so a public handle is enough, and you can skip it entirely if you have no feed yet. A login is needed only if you want me to publish for you at the end.

Does it work if I do not have a website?

Yes. A codebase or a plain description works. The research pass gets thinner, so expect to shape the brief a little more in step 5.

Can I stop halfway and keep what I have?

Yes. Every asset is written to disk as it lands, so stopping after the grid leaves you a finished grid. Refining any single piece later is a normal conversation, not a restart.

Is the output actually good, or does it look generated?

The grounding is what decides that. Because the work is built on your real feed, your real palette, and your real product shots, it tracks your brand instead of a house style. For the ceiling, four full campaigns built as unsolicited spec work for Teenage Engineering, HAY, Aesop, and Polaroid are on the cases page.

How long does a first campaign take?

One sitting, with two pauses that are yours: shaping the brief, and picking a direction. Rendering runs in parallel, so a wave of tiles lands together rather than one after another.

Where to go next

  • Sign up and claim the 450 free credits, then run the install command above.
  • Getting started is the two minute version of steps 1 to 3.
  • The API reference covers the same account and generation surface over REST, if you are building your own tooling.
  • Help is where a real person answers.

Yours comes next.

One conversation; a whole campaign. 450 free credits when we meet.