instagram-mcp
Enables publishing photos, reels, and stories to Instagram, managing comments, viewing media insights, and scheduling reels through the Instagram Graph API.
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-mcpPost the photo at /tmp/sunset.jpg to my Instagram feed"
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-mcp
An MCP server that wraps the Instagram API (Instagram Login flow): publish photos, reels, and stories (from a URL, a local file, or — via the included subagent — a local file hosted through Google Drive); read comments and performance insights; moderate comments; draft on-brand captions using MCP sampling; and schedule reels for later.
Built as a learning project after Anthropic's "Introduction to Model Context Protocol" course, to turn the course concepts into a real, working integration — not just tools, but resources, prompts, sampling, logging, progress notifications, and a Claude Code subagent on top.
For the full story — the Meta developer setup process and every problem hit
along the way, plus a deeper design writeup of every MCP concept used and
why — see docs/01-meta-developer-setup.md
and docs/02-mcp-server-design.md.
Quick start
npm install
npm run buildThen set two environment variables (IG_USER_ID, IG_ACCESS_TOKEN) in your
MCP client config — see Setup below for how to get them, and
Connect it to Claude for where they go.
Related MCP server: meta-mcp
What's in this project
Path | What it is |
| The actual Instagram API client — auth, GET/POST helpers, publishing flows, resumable upload. No MCP-specific code. |
| The MCP layer — registers everything in |
| A Claude Code subagent scoped to just this server (+ Google Drive), with judgment calls baked into its system prompt. |
| Narrative of the Meta app / token setup process, including every blocker hit and how it was resolved. |
| Design writeup: problem statement, architecture, and an explanation of every MCP concept this project uses. |
Setup
1. Account & app requirements
Your Instagram account must be a Business or Creator account. This project uses Instagram API with Instagram Login — the account authorizes the app directly, no Facebook Page needed.
Create a Meta app at https://developers.facebook.com/apps (Business type), add the Instagram product, and inside it choose "API setup with Instagram login."
Under App roles → Roles, add your Instagram account as an Instagram Tester, then accept the invite from inside the Instagram app itself (Settings → Apps and Websites → Tester Invites). The app can't authorize your account until this is accepted.
On the "API setup with Instagram login" page, step 1 lists required permissions:
instagram_business_basic,instagram_business_manage_comments,instagram_business_manage_messages. Add two more via "Go to permissions and features":instagram_business_content_publish(needed forpost_image/post_reel/post_story) andinstagram_business_manage_insights(needed forget_media_insights).
See docs/01-meta-developer-setup.md if any of this goes sideways — it
documents the specific errors this project hit (business portfolio
blockers, "insufficient developer role," permission-name renames) and how
each was fixed.
2. Get your credentials
On the same "API setup with Instagram login" page, under "2. Generate access tokens":
Click Add account, log in as your Instagram account, and approve the permissions. This adds a row showing your account and its Instagram User ID (e.g.
17841471531885841) — that's yourIG_USER_ID.Click Generate token in that row to get a token. If it's issued as long-lived (60 days) you're done. If it's short-lived, exchange it:
GET https://graph.instagram.com/access_token ?grant_type=ig_exchange_token &client_secret={instagram-app-secret} &access_token={short-lived-token}
Long-lived tokens expire after 60 days — for real use you'd add a refresh job; not included here to keep this a learning-sized project.
If you add permissions after already generating a token, regenerate the token. A token only carries whatever permissions existed at the moment it was created — adding scopes afterward does nothing until you get a fresh one.
3. Configure environment variables
The server reads IG_USER_ID and IG_ACCESS_TOKEN from the environment —
set these in your MCP client config (below), not in a committed .env file.
Connect it to Claude
Claude Desktop / Claude Code — add to your MCP config
(claude_desktop_config.json or .mcp.json):
{
"mcpServers": {
"instagram": {
"command": "node",
"args": ["/absolute/path/to/instagram-mcp/dist/index.js"],
"env": {
"IG_USER_ID": "your-instagram-scoped-user-id",
"IG_ACCESS_TOKEN": "your-long-lived-token"
}
}
}
}Restart Claude Desktop / Claude Code after saving. You should see the
instagram server's tools available in a new conversation.
Note on config file locations: newer Claude Desktop builds may manage
connectors through the in-app Settings UI instead of a hand-edited file, or
may only expose custom-connector fields for remote (https://) servers, not
local stdio ones like this. If you don't see a claude_desktop_config.json
being read, look for a Developer settings section with an Edit
Config button — that's the one that accepts this JSON.
Tools exposed
Tool | Description |
| Recent posts/reels with basic counts |
| Reach, likes, comments, saves, (video) shares/views |
| Comments on a media item |
| Public reply to a comment |
| Hide/unhide a comment |
| Permanently delete a comment |
| Publish a single photo (public URL) |
| Publish a Reel from a public URL or a local file (handles the container → upload/poll → publish flow, reports progress) |
| Publish a 24h story (public URL) |
| Queue a Reel to publish at a future time (see Scheduling) |
| List queued reels and their status |
| Cancel a pending scheduled reel |
| Uses MCP sampling to ask the connected client's model for 3 caption options, grounded in the account's recent captions |
Resources exposed
URI | Description |
| The account's most recent media, as a browsable resource (not just a tool call) |
| Comments on a specific media item, addressed by URI |
| The current in-memory queue of scheduled reels |
Prompts exposed
Prompt | Description |
| A ready-made prompt (optionally takes |
MCP concepts this project demonstrates
Beyond basic tools, this server exercises the rest of the MCP surface:
Resources —
instagram://mediaandinstagram://media/{id}/commentslet a client browse/attach Instagram data directly, the same way it would browse a file, rather than only getting data back from a tool call.Prompts —
weekly_engagement_reviewis a reusable prompt template the client can surface (e.g. as a slash command) instead of the user having to type out the same multi-step instruction each time.Sampling —
suggest_captioncallsserver.server.createMessage(...), which asks the client's model (whatever Claude the person is running) to generate text, using account context this server already has. The server never calls its own separate LLM API key — it borrows the client's model via the protocol.Logging & progress notifications — every mutating tool call sends structured log messages via
sendLoggingMessage.post_reeladditionally sendsnotifications/progressupdates while it polls Instagram's video processing status (which can take 30s–2min), so a client that supports progress UI can show real-time status instead of a silent hang.
See docs/02-mcp-server-design.md for the full writeup of why each of these
was built the way it was.
Local file uploads (post_reel with video_path)
post_reel accepts either video_url (public URL) or video_path (an
absolute path to a file on this machine). For a local file, the server
uploads the raw bytes directly to Meta's servers via the resumable
upload flow (rupload.facebook.com) — no need to host the file publicly
yourself.
One honest caveat: Meta's docs describe this resumable path as intended for
apps using "Facebook Login for Business," and this project uses Instagram
Login instead. In practice it works for most Instagram Login apps too, but
if post_reel with video_path fails with a permission or host error, the
fallback is to host the file somewhere public and use video_url instead
(see the Drive-based workflow below for one way to do that without leaving
the conversation).
post_image and post_story don't have a local-file option — Instagram's
photo/story publishing API has no resumable-upload equivalent for images, so
these two tools still require a public image_url/video_url.
Local assets for any post type: the instagram-manager subagent
For a workflow where you just hand over a local file — photo, reel, or story — and don't want to think about hosting at all, use the included Claude Code subagent instead of calling the tools directly:
.claude/agents/instagram-manager.mdThis subagent has access to both mcp__instagram (this server) and a
Google Drive connector, and is instructed to: upload the local file to
Drive → set it to link-shareable → build a direct-download URL → call the
matching Instagram tool with that URL. It also knows to fall back to
post_reel's video_path if a Drive-hosted reel fails (large video files
can hit Google's virus-scan interstitial, which serves an HTML warning page
instead of raw bytes).
To use it: copy the file into ~/.claude/agents/ (available in every
project) or your project's own .claude/agents/, then check that the
mcp__google-drive name in its frontmatter matches whatever your Drive
connector is actually named in your Claude Code config (claude mcp list).
See docs/02-mcp-server-design.md §6–7 for the full reasoning behind this
design (why it's a subagent concern and not server code).
Scheduling (schedule_reel)
Instagram's API has no native "publish later" — real scheduling of organic
posts only exists inside Meta's own Business Suite UI, not the API. So
schedule_reel holds the job in this server's memory and fires it with a
timer at the right time.
This means scheduled posts only fire while this MCP server process stays alive — i.e. while Claude Desktop (or whatever client launched it) stays open. Quitting the app cancels anything still pending. It's fine for same-session or same-day scheduling ("post this in 2 hours"); it is not a durable schedule you can set and then close your laptop on.
For real "survive a reboot, fire while I'm asleep" scheduling, you'd want a
system-level mechanism instead — a cron job or macOS launchd task that
invokes a small standalone script (reusing src/instagram.ts's postReel)
at the target time, independent of Claude Desktop's process lifecycle. Not
implemented here, to keep this project at learning-project scope.
Notes / gotchas carried over from the Graph API itself
post_image/post_storystill need a public URL — no local-file option for those two (see above).post_reelis the exception, viavideo_path.Reels take time to process.
post_reelpolls the container'sstatus_codeuntil it'sFINISHEDbefore publishing (Meta recommends polling for up to ~5 minutes; most reels finish in 30s–2min).Rate limit: 25 published posts per rolling 24h window, shared across photos/reels/stories.
Reel eligibility for the Reels tab needs 9:16 aspect ratio and 5–90s duration; longer/differently-shaped video still publishes but as a regular video post.
Metric names have drifted. Instagram merged
impressions/playsinto a singleviewsmetric — if insights calls ever start failing across every post consistently, suspect a metric-name mismatch before assuming it's a permissions issue.
Next steps to extend this
Real persistent scheduling via a generated cron/launchd job.
A
create_carousel_posttool (multi-image, same container/publish pattern aspost_imagebut withchildrenparams).Native local-file support for
post_image/post_storyin server code (would still need some public-hosting step, since Instagram has no resumable upload for photos — possibly a short-lived local HTTP endpoint via a tunnel, as an alternative to the subagent's Drive-based approach).Account-level insights (follower count, profile views) via a resource.
Token refresh handling instead of manual 60-day renewal.
An automatic retry/fallback wrapper around Drive-hosted
post_reelcalls, instead of relying on the subagent's prompt-level instruction to notice and react to a failure.Swap the manual env vars for a proper OAuth flow if you want other people to connect their own accounts to this server.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceEnables AI assistants to manage Instagram Business accounts by automating content publishing, scheduling posts, and analyzing performance metrics. Supports posts, stories, reels, and carousels with detailed audience insights and hashtag discovery.
- AlicenseAqualityCmaintenanceEnables AI assistants to manage Instagram and Threads accounts — publish content, handle comments, view insights, search hashtags, and manage DMs through the Meta Graph API.594610MIT
- AlicenseNot gradedqualityBmaintenanceEnables reading, publishing, commenting, direct messaging, and pulling insights from Instagram Business or Creator accounts via the Graph API.6MIT
- AlicenseAqualityAmaintenanceConnects Claude Desktop and other MCP clients to the Instagram Graph API for reading analytics, managing comments, and publishing photos, carousels, and reels.1183MIT
Related MCP Connectors
Instagram for AI agents: publish, read comments and DMs, insights, and engage from your account.
Social media MCP: publish, schedule & analyze posts on TikTok, Instagram, YouTube, LinkedIn & X
Create, schedule and publish social posts to TikTok, Instagram, Facebook and YouTube.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- 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/JainAditi09/personal-insta-manager'
If you have feedback or need assistance with the MCP directory API, please join our Discord server