Skip to main content
Glama
instagram-mcp

instagram-mcp

by OraCool

instagram-mcp

MCP server for the Instagram API with Instagram Login — let Claude (or any MCP client) work with your Instagram Business or Creator account:

Unofficial. A community project, not affiliated with or endorsed by Meta or Instagram. It uses the official Graph API with your own access token — no password, no scraping, no private API.

  • Profile & media — profile stats, posts, reels, stories, carousel children, media you're tagged in.

  • Insights — account metrics (views, reach, engagement, followers, demographics) and per-post metrics.

  • Comments — read, reply, comment, hide/unhide, delete, enable/disable comments.

  • Publishing — images, reels, stories and carousels (2–10 items) from public URLs; daily quota check.

  • Direct messages — list conversations, read recent messages, send text/image DMs and private replies to comments.

Tools

Tool

Purpose

ig_token_status

Which account the token belongs to, token source and expiry, whether writes are enabled

ig_refresh_token

Extend the long-lived token by 60 days (saved to IG_TOKEN_CACHE_PATH)

ig_get_profile

Username, bio, followers/follows/media counts

ig_list_media

Posts and reels with likes and comment counts (cursor paging)

ig_get_media

One media item, incl. carousel children

ig_list_stories

Currently live stories

ig_list_tagged_media

Media in which the account is tagged

ig_account_insights

Account metrics for a period, with breakdowns

ig_media_insights

Metrics of one post/reel/story (defaults by media type)

ig_list_comments / ig_list_replies

Comments of a post, replies of a comment

ig_reply_comment / ig_comment_on_media ✍️

Reply to a comment / comment on own media

ig_hide_comment / ig_delete_comment ✍️

Hide/unhide or delete a comment

ig_set_comments_enabled ✍️

Turn comments on/off for a post

ig_publish_image / ig_publish_reel / ig_publish_story / ig_publish_carousel ✍️

Publish from public media URLs

ig_get_container_status / ig_publish_container ✍️

Check and finish a publish that was still processing

ig_publishing_limit

API posts used in the last 24 h (limit 100)

ig_list_conversations / ig_get_messages

DM threads and their latest 20 messages

ig_send_message ✍️

Send a DM (text or image) or a private reply to a comment

✍️ = changes your account; refused unless IG_ENABLE_WRITES=true.

Related MCP server: Instagram → ChatGPT MCP Server

Setup

Requires Node.js 20+ and an Instagram Business or Creator account. Three ways to get a token — details in docs/credentials.md:

  • Paste a token from your own Meta app's dashboard into IG_ACCESS_TOKEN.

  • Option 1 — login with your own app: IG_APP_ID=... IG_APP_SECRET=... npx -y github:OraCool/instagram-mcp login

  • Option 2 — login through an app owner's login server (worker/, Cloudflare Worker), for team members/clients added to that app: IG_AUTH_SERVER=https://... npx -y github:OraCool/instagram-mcp login

login saves the token to ~/.config/instagram-mcp/token.json, which the server picks up automatically.

Register with Claude Code:

claude mcp add instagram -- npx -y github:OraCool/instagram-mcp            # after `login`
claude mcp add instagram -e IG_ACCESS_TOKEN=IGAA... -- npx -y github:OraCool/instagram-mcp   # pasted token

Claude Desktop (claude_desktop_config.json):

{
  "mcpServers": {
    "instagram": {
      "command": "npx",
      "args": ["-y", "github:OraCool/instagram-mcp"],
      "env": {
        "IG_ENABLE_WRITES": "false"
      }
    }
  }
}

From a clone: npm install && npm run build, then use node /path/to/instagram-mcp/dist/index.js as the command.

Several accounts

Run one server entry per account. IG_ACCOUNT gives each its own token file (~/.config/instagram-mcp/<name>.token.json); login always asks which Instagram account to connect and prints the connected @username.

npx -y github:OraCool/instagram-mcp login --account brand.one     # log in as @brand.one
npx -y github:OraCool/instagram-mcp login --account brand.two     # log in as @brand.two

claude mcp add instagram-brand-one -s user -e IG_ACCOUNT=brand.one -- npx -y github:OraCool/instagram-mcp
claude mcp add instagram-brand-two -s user -e IG_ACCOUNT=brand.two -- npx -y github:OraCool/instagram-mcp

Each account must be a professional account added to the Meta app (as an Instagram tester if you don't own it). Turn on IG_ENABLE_WRITES per entry only where posting is wanted.

Configuration

Variable

Default

Meaning

IG_ACCESS_TOKEN

—

Long-lived Instagram User access token (not needed after login)

IG_USER_ID

from GET /me

Professional account id

IG_API_VERSION

v25.0

Graph API version

IG_ACCOUNT

—

Account name for several accounts: token file becomes ~/.config/instagram-mcp/<name>.token.json

IG_TOKEN_CACHE_PATH

~/.config/instagram-mcp/token.json

Token saved by login/refresh; takes precedence over IG_ACCESS_TOKEN

IG_APP_ID, IG_APP_SECRET

—

Option 1: your own Meta app, for login

IG_REDIRECT_URI

https://oracool.github.io/instagram-mcp/callback/

Option 1: redirect URI registered in your app

IG_AUTH_SERVER

—

Option 2: URL of a hosted login server (worker/)

IG_ENABLE_WRITES

false

Allow publishing, comment moderation and sending DMs

Good to know

  • Publishing — media must be at a public URL (Meta downloads it); images must be JPEG. Video processing can take minutes: when it's not done within wait_seconds (default 60), the tool returns a pending container_id for ig_publish_container. Containers expire after 24 h. Max 100 API posts per rolling 24 h.

  • Messages — you can reply only within 24 hours of the person's last message; text max 1000 bytes; only the 20 most recent messages of a thread are readable.

  • Insights — about 90 days of history; some metrics need 100+ followers; missing data comes back empty.

  • Not supported by this API — personal accounts, ads, hashtag search, other accounts' stats (Business Discovery), and anything requiring Facebook Login.

Development

npm install
npm test            # vitest, fake Graph API — no network
npm run typecheck
npm run build
npm run inspect     # MCP Inspector against dist/ with .env

License

MIT

Available Tools

26 tools
ig_account_insightsInstagram account insightsA
Read-onlyIdempotent

Account-level metrics (views, reach, engagement, followers, demographics). Instagram keeps about 90 days of data; some metrics need 100+ followers. Metrics without data come back empty, not as 0. Demographic metrics (follower_demographics, engaged_audience_demographics) need period=lifetime, metric_type=total_value, a timeframe and a breakdown (age, city, country, gender).

Inputs: since, until, period, metrics, +3 more.

ig_comment_on_mediaComment on own mediaA

Adds a top-level comment to one of the account's posts or reels. Requires IG_ENABLE_WRITES=true.

Inputs: message (required), media_id (required).

ig_delete_commentDelete a commentB
DestructiveIdempotent

Permanently deletes a comment on the account's media. Cannot be undone. Requires IG_ENABLE_WRITES=true.

Inputs: comment_id (required).

ig_get_container_statusGet media container statusB
Read-onlyIdempotent

Processing status of a media container: IN_PROGRESS, FINISHED, PUBLISHED, ERROR or EXPIRED.

Inputs: container_id (required).

ig_get_mediaGet Instagram mediaC
Read-onlyIdempotent

One post, reel or story by media id, including carousel children.

Inputs: media_id (required).

ig_get_messagesGet DM messagesA
Read-onlyIdempotent

Messages of one conversation with sender, recipient and text. Instagram only returns the 20 most recent messages.

Inputs: conversation_id (required).

ig_get_profileGet Instagram profileA
Read-onlyIdempotent

Profile of the connected professional account: username, name, bio, followers, follows and media counts.

Inputs: no named parameters.

ig_hide_commentHide or unhide a commentA
DestructiveIdempotent

Hides a comment from the public (or shows it again with hide=false). Requires IG_ENABLE_WRITES=true.

Inputs: comment_id (required), hide.

ig_list_commentsList comments on mediaB
Read-onlyIdempotent

Top-level comments on one of the account's posts or reels, with author, likes and hidden flag.

Inputs: media_id (required), after, limit.

ig_list_conversationsList DM conversationsB
Read-onlyIdempotent

Direct-message conversations of the account, most recently updated first. With user_id (an Instagram-scoped id) returns only the conversation with that person. Request-folder threads inactive for 30 days are not returned.

Inputs: after, limit, user_id.

ig_list_mediaList Instagram mediaA
Read-onlyIdempotent

Posts and reels of the connected account, newest first, with likes and comment counts. Pass next_cursor back as after for the next page.

Inputs: after, limit.

ig_list_repliesList replies to a commentC
Read-onlyIdempotent

Replies to a comment on the account's media.

Inputs: comment_id (required), after, limit.

ig_list_storiesList Instagram storiesA
Read-onlyIdempotent

Currently live stories of the connected account (stories disappear from the API after 24 hours).

Inputs: no named parameters.

ig_list_tagged_mediaList media the account is tagged inC
Read-onlyIdempotent

Media from other accounts in which the connected account has been tagged.

Inputs: after, limit.

ig_media_insightsInstagram media insightsA
Read-onlyIdempotent

Metrics for one post, reel or story. Without metrics, a default set for the media type is used (FEED / REELS / STORY). Only media of the connected account is supported.

Inputs: media_id (required), metrics.

ig_publish_containerPublish a pending containerA

Finishes publishing a container returned as pending by an ig_publish_* tool. Requires IG_ENABLE_WRITES=true.

Inputs: container_id (required), wait_seconds.

ig_publish_imagePublish an image postA

Publishes a single-image feed post from a public JPEG URL. Requires IG_ENABLE_WRITES=true.

Inputs: image_url (required), caption, alt_text, wait_seconds.

ig_publishing_limitPublishing quotaA
Read-onlyIdempotent

How many posts the account has published via the API in the last 24 hours (limit: 100; a carousel counts as one).

Inputs: no named parameters.

ig_publish_reelPublish a reelA

Publishes a reel from a public video URL. Video processing can take minutes: if it is not ready within wait_seconds, a pending container_id is returned for ig_publish_container. Requires IG_ENABLE_WRITES=true.

Inputs: video_url (required), caption, cover_url, thumb_offset, +2 more.

ig_publish_storyPublish a storyA

Publishes a story from a public image (JPEG) or video URL. Captions are not supported on stories. Requires IG_ENABLE_WRITES=true.

Inputs: image_url, video_url, wait_seconds.

ig_refresh_tokenRefresh Instagram tokenA

Refreshes the long-lived access token for another 60 days (the token must be at least 24 hours old and not expired). The new token is saved to IG_TOKEN_CACHE_PATH; without it the new token only lives until the server restarts.

Inputs: no named parameters.

ig_reply_commentReply to a commentB

Posts a public reply to a comment. Requires IG_ENABLE_WRITES=true.

Inputs: message (required), comment_id (required).

ig_send_messageSend a direct messageA

Sends a DM with text or one image. Instagram only allows it within 24 hours of the person's last message. recipient_comment_id sends a private reply to a commenter instead (one per comment). Requires IG_ENABLE_WRITES=true.

Inputs: text, image_url, recipient_id, recipient_comment_id.

ig_set_comments_enabledEnable or disable commentsA
Idempotent

Turns comments on or off for one of the account's posts. Requires IG_ENABLE_WRITES=true.

Inputs: enabled (required), media_id (required).

ig_token_statusInstagram token statusA
Read-onlyIdempotent

Checks the configured access token: which account it belongs to, where it comes from (env or refreshed cache), and its expiry when known. Also reports whether write actions are enabled.

Inputs: no named parameters.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.5/5.0

    Scored across 26 tools

    Disambiguation5/5

    Each tool targets a distinctly bounded action: media publishing is split cleanly by type (image/reel/story/carousel), comment operations are separated (list, reply, top-level comment, hide, delete, toggle), and container/status tools are clearly delineated from the publish tools. The only mildly adjacent pair (ig_reply_comment vs ig_comment_on_media) is explicitly distinguished in the descriptions.

    Naming Consistency5/5

    Every tool uses the ig_ prefix followed by a consistent verb_noun pattern (ig_list_comments, ig_get_profile, ig_publish_reel, ig_delete_comment). No camelCase or stylistic deviations appear across the full set of 26 tools.

    Tool Count4/5

    26 tools is on the heavy side and slightly exceeds the comfortable range, but the domain is genuinely broad (posts, reels, stories, carousels, comments, insights, DMs, token lifecycle), so nearly every tool earns its place. There is little obvious redundancy to trim.

    Completeness4/5

    The surface covers full lifecycle for the main resources: publishing, retrieval, listing, insights, comment moderation, DM read/send, and token management. Minor gaps exist (e.g., no media deletion or edit, which the Instagram API largely disallows anyway), but core workflows have no dead ends.

    Maintenance

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      C
      maintenance
      Enables MCP clients to manage a Meta-linked Instagram professional account, including comments, replies, and messages, using Meta's official APIs with deterministic permissions and audit state.
      MIT
    • F
      license
      Not graded
      quality
      A
      maintenance
      Enables authenticated interaction with Instagram accounts to send messages, manage direct-message threads, download media, and retrieve user, story, follower, and post data through MCP-compatible clients.
      -