mcpField
I
instagram

instagram

github.com/acedatacloudMarketing & growth1748 installsUpdated 1d ago
Repository

About instagram

instagram is a skill for publishing images, videos, Reels, and carousels through the Instagram Graph API. It guides account resolution, media processing, publishing, and recording a confirmed output permalink.

Key features

  1. 01Resolve a linked professional account
  2. 02Publish images and videos
  3. 03Create Reels and carousels
  4. 04Check media processing status
  5. 05Record published permalink

Use cases

  1. 01Publish a captioned image
  2. 02Publish a Reel after processing
  3. 03Post a carousel of multiple items

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/acedatacloud/skills --skill instagram

After installing, type/instagramin Claude Code to confirm it loaded.

Details

From the project README

Call the Instagram Graph API (graph.facebook.com) with curl + jq. The connector injects $INSTAGRAM_ACCESS_TOKEN (a token with instagram_content_publish + pages_read_engagement; a Facebook Page token or an Instagram-Login user token) and optionally $INSTAGRAM_IG_USER_ID. Never echo them.

Instagram publishes only images / videos / reels to a professional (Business or Creator) account linked to a Facebook Page. There are no text-only posts.

Resolve the Instagram account id

If $INSTAGRAM_IG_USER_ID is set, use it. Otherwise derive it from the token — try the Page-token path first (/me is the Page), then fall back to the user-token path (/me/accounts → linked Page → IG account), so either token type the connector accepts resolves cleanly:

if [ -n "$INSTAGRAM_IG_USER_ID" ]; then
  IGID="$INSTAGRAM_IG_USER_ID"
else
  # Page access token: /me IS the Page, read its linked IG account directly
  IGID=$(curl -sS "https://graph.facebook.com/v21.0/me?fields=instagram_business_account&access_token=$INSTAGRAM_ACCESS_TOKEN" | jq -r '.instagram_business_account.id // empty')
  if [ -z "$IGID" ]; then
    # User access token: list the managed Page, then its linked IG account
    PAGE=$(curl -sS "https://graph.facebook.com/v21.0/me/accounts?access_token=$INSTAGRAM_ACCESS_TOKEN" | jq -r '.data[0].id // empty')
    IGID=$(curl -sS "https://graph.facebook.com/v21.0/$PAGE?fields=instagram_business_account&access_token=$INSTAGRAM_ACCESS_TOKEN" | jq -r '.instagram_business_account.id // empty')
  fi
fi
echo "ig_user_id=$IGID"

Errors are JSON with error.message / error.code — show them verbatim. 401 / OAuthException → token expired or missing scope; a null IGID → the token isn't linked to a professional IG account / Page (see Gotchas). Reconnect if needed.

Publish a single image (two-step: create container → publish)

Confirm the caption + image with the user first. The image_url must be a public JPEG URL (Instagram server-side cURLs it):

CID=$(curl -sS -X POST "https://graph.facebook.com/v21.0/$IGID/media" \
  -d "image_url=https://cdn.acedata.cloud/xxxx.jpg" \
  --data-urlencode "caption=One endpoint → posters, cards, mockups. #AI #API" \
  -d "access_token=$INSTAGRAM_ACCESS_TOKEN" | jq -r .id)
echo "container=$CID"

curl -sS -X POST "https://graph.facebook.com/v21.0/$IGID/media_publish" \
  -d "creation_id=$CID" -d "access_token=$INSTAGRAM_ACCESS_TOKEN" | jq .
# → {"id":"<IG_MEDIA_ID>"}

Get the permalink to hand back to the user:

curl -sS "https://graph.facebook.com/v21.0/<IG_MEDIA_ID>?fields=permalink&access_token=$INSTAGRAM_ACCESS_TOKEN" | jq -r .permalink

Reels / video

Create with media_type=REELS + a public video_url, then poll the container status until FINISHED before publishing (video processing takes time):

CID=$(curl -sS -X POST "https://graph.facebook.com/v21.0/$IGID/media" \
  -d "media_type=REELS" -d "video_url=https://cdn.acedata.cloud/xxxx.mp4" \
  --data-urlencode "caption=..." -d "access_token=$INSTAGRAM_ACCESS_TOKEN" | jq -r .id)

# poll until the video finishes processing (up to ~5 min) BEFORE publishing —
# publishing an IN_PROGRESS container is rejected:
for i in $(seq 1 60); do
  ST=$(curl -sS "https://graph.facebook.com/v21.0/$CID?fields=status_code&access_token=$INSTAGRAM_ACCESS_TOKEN" | jq -r .status_code)
  echo "status=$ST"; [ "$ST" = "FINISHED" ] && break
  [ "$ST" = "ERROR" ] || [ "$ST" = "EXPIRED" ] && { echo "container failed: $ST"; break; }
  sleep 5
done

curl -sS -X POST "https://graph.facebook.com/v21.0/$IGID/media_publish" \
  -d "creation_id=$CID" -d "access_token=$INSTAGRAM_ACCESS_TOKEN" | jq .

Carousel (2–10 items)

Create each child with is_carousel_item=true, then a media_type=CAROUSEL container with children=<ID1>,<ID2>,... + caption, then publish the carousel id.

Gotchas

  • No text-only posts — Instagram requires an image or video. Use a public JPEG for images (PNG/other formats are rejected; extended JPEG like MPO/JPS too).
  • Professional account required — a Business/Creator IG account linked to a Facebook Page. If instagram_business_account is null, the account isn't a professional account or isn't linked; the user must fix that in IG / Page settings.
  • Media must be a public URL on a server Instagram can reach; local files won't work. Host on cdn.acedata.cloud first.
  • Rate limit: 100 API-published posts per 24h (a carousel counts as 1). Check via GET /$IGID/content_publishing_limit.
  • Page Publishing Authorization (PPA): some Pages must complete PPA before API publishing works — surface the API error verbatim if it mentions PPA.
  • API version: keep the vXX.0 path current if you hit a version/deprecation error.

Record the output

After you successfully publish and obtain the live permalink, call the built-in publish_artifact tool ONCE so the user can track it in My Outputs:

publish_artifact(kind="image", channel="instagram", title="<title>", url="<the REAL permalink>", status="delivered")

Use the real returned URL — never fabricate one. Call it once per published item, only after delivery is confirmed; skip it (or use status="failed") if publishing failed. See _shared/artifacts.md.

Comments

Markdown supported