instagram-mcp
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-mcppublish a photo to my 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-ai β Instagram MCP Server
A locally-run, TypeScript Model Context Protocol
server that exposes an Instagram professional account (Business/Creator) over
the official Meta Graph API (graph.instagram.com / graph.facebook.com) β
content publishing, media management, comment moderation, insights and discovery,
as safe, well-annotated MCP tools. It talks only to official Meta endpoints:
no scraping, no instagram-private-api-style clients, no cookie/session reuse. It
ingests media by public HTTPS URL only. Credentials live in a local env file
and can be obtained/refreshed with a built-in CLI.
Status: implementation complete and tested β not yet published to npm. The read path (account, media, insights), the write path (content publishing, comment moderation) and discovery are all implemented, unit-tested and CI-green across Linux/macOS/Windows on Node 22 and 24. The published npm package and the live badges follow once
npm publishruns. The documents underdocs/are the source of truth for the design.
Contents: What it does Β· Requirements Β· Quickstart Β· Setup Β· Configure credentials Β· Run / debug Β· Write safety Β· Package profiles Β· Tools Β· Configuration Β· Security notes Β· Project documentation Β· Support
Built and maintained in my own time β a GitHub Sponsors tip keeps it going.
What it does
The server exposes an Instagram professional account through 28 MCP tools grouped into six packages:
Content publishing β feed images, 2β10 image carousels, Reels and Stories via the container β publish flow, plus one-call helpers (
instagram_post_image/_reel/_story) and publishing-limit reporting.Media management β list/read own media (including album children) and toggle whether a post accepts comments.
Comment moderation β list threads, reply, hide/unhide (reversible, preferred over delete) and delete; read tagged media.
Insights β account and media metrics on the post-2025
views-based metric set, audience demographics and online-follower distribution.Discovery β hashtag search, hashtag top/recent media and public business/competitor discovery. (Path B /
fb-loginonly β see below.)Account β profile, linked Facebook Pages / IG accounts, and a token-status report (auth path, expiry, days-left, refresh warning).
Every tool carries MCP annotations (readOnlyHint, destructiveHint,
idempotentHint) so clients apply the right confirmation UX, and every mutation
passes through a preview-by-default write gate. All Graph URLs
are pinned to a single API version (v25.0).
Why build it
The Meta ads niche is saturated β including Meta's own hosted Ads MCP
(mcp.facebook.com/ads, ads-only) β while the organic Instagram side has
only thin coverage. The existing TypeScript servers ship without tool
annotations, structured output, token security or tests. A well-engineered
TypeScript Instagram MCP server with proper token security, rate-limit
compliance and honest Graph semantics fills that gap. It is a sibling of the
planned facebook-mcp (Pages) server and shares the layered architecture of the
production servicenow-mcp-ai.
The #1 constraint to know up front: Instagram ingests media by public URL β
image_url/video_urlmust be reachable by Meta's servers. Publishing a local file means hosting it somewhere public first; v1 accepts URLs only.
Related MCP server: instagram-mcp
Requirements
Node.js β₯ 22 (Node 20 is EOL). Enforced by
enginesand a runtime guard in the CLI launcher with a clear message. CI runs the full gate on Node 22 and 24 across Linux, macOS and Windows.
Quickstart
Register the server with an MCP client (Claude Desktop, VS Code Chat, the
Inspectorβ¦) by pointing the command at npx and supplying one auth path's
credentials:
// claude_desktop_config.json / .mcp.json
{
"mcpServers": {
"instagram": {
"command": "npx",
"args": ["-y", "instagram-mcp-ai"],
"env": {
"IG_ACCESS_TOKEN": "<long-lived ig-login token>",
"IG_ACCOUNT_ID": "<ig professional account id>"
}
}
}
}That is Path A (Instagram Login). For the token, the simplest path is the
built-in login command β see Configure credentials.
Everything else is optional tuning; the full list is under
Configuration.
Setup
From source (for development):
npm install
npm run buildOr run the published package directly, without cloning:
npx instagram-mcp-aiCredentials are read from ~/.config/instagram-mcp-ai/.env (XDG), the project
.env, or real environment variables (which always win) β see below.
Configure credentials
All settings are environment variables with the uniform IG_ prefix; the
canonical copy with inline comments is .env.example. Choose
exactly one of the two Meta auth paths (set IG_AUTH_MODE only when both
tokens are present):
Path |
| Token var | Host | Notes |
A β Instagram Login |
|
|
| Token-only; |
B β Facebook Login |
|
|
| Page/system-user token; requests carry an |
When only one token is set the mode is auto-detected. Discovery tools are capability-filtered to Path B, so on Path A they are not registered at all.
login β obtain a long-lived token
A live login needs a registered Meta app (an app id/secret and a redirect URI whitelisted in the app's OAuth settings). With those in place:
# Path A (Instagram Login)
IG_APP_ID=... IG_APP_SECRET=... npx instagram-mcp-ai login --path ig
# Path B (Facebook Login)
IG_APP_ID=... IG_APP_SECRET=... npx instagram-mcp-ai login --path fbIt opens the browser, captures the loopback redirect, exchanges the code for a
long-lived (~60-day) token and writes it to the env file (chmod 0600 on POSIX).
No token or secret is ever printed. Run npx instagram-mcp-ai login --help for
all options (--profile, --account-id, --scopes, --redirect-uri). See
docs/auth.md for the full token model, scopes and app setup.
Run / debug
The published instagram-mcp-ai binary (run it directly or via npx) has three
subcommands; with no subcommand it starts the MCP server on the configured
transport. All connection settings come from environment variables / the env file.
Command | What it does |
| Starts the MCP server. Transport is |
| One-time browser OAuth to obtain and persist a long-lived token (see above). |
| Read-only health check for the active profile: config, token/auth, and one reachability GET. Exit |
| Refresh the active profile's long-lived token and write it back ( |
stdio (default) β for local MCP clients.
stdoutis the protocol channel; all diagnostics go tostderr.Streamable HTTP β opt in with
IG_TRANSPORT=http. Loopback-bound (127.0.0.1:3000by default viaIG_HTTP_HOST/IG_PORT); setIG_HTTP_TOKENto require anAuthorization: Bearer <token>header (constant-time compared).
Write safety
Every mutating tool passes through a single write gate (design gate D3):
Preview by default. A write returns a non-mutating preview describing exactly what would change; nothing is sent to Meta.
Apply explicitly. Pass
apply: trueon the call, or setIG_WRITE_MODE=applyfor standing consent, to actually perform the write.Destructive ops are double-gated. Irreversible actions (e.g.
instagram_delete_comment) additionally requireIG_ALLOW_DESTRUCTIVE=true.Journaled. Every applied write is appended to a local, append-only JSONL journal (
~/.local/state/instagram-mcp-ai/writes.jsonl, orIG_WRITE_JOURNAL) for auditing β best-effort, so a broken journal never fails an authorized write.
Package profiles
Tools are grouped into packages so you can expose only what a client needs (fewer
tools keep the model focused). Set IG_TOOL_PACKAGES to a profile name or an
explicit comma list of packages:
Profile |
| Packages | Tools |
|
| the everyday read + publish + moderate set | 25 |
|
| read, insights and discovery (Path B for discovery) | 21 |
|
| publish and moderate | 21 |
| every package | the full surface | 28 |
The six packages are account, media, insights, publishing, comments
and discovery. Two more knobs refine a selection: IG_PACKAGES_DENY removes
packages after the profile resolves, and IG_PACKAGES_READONLY forces a
package's write tools off (its read tools stay). Auth-path capability filtering
runs on top β a reader profile on Path A drops the three fb-login-only
discovery tools.
Tools
The full v1 tool surface, generated from the tool registry β do not edit the
table by hand; run npm run gen:readme. Auth paths is the login path a tool
is valid for (both when unrestricted); Access is Read for read-only tools
and Write for mutating ones (writes preview by default β see
Write safety).
Tool | Package | Auth paths | Access | Summary |
| account | both | Read | Fetch the profile of the operated Instagram professional account: username, display name, biography, website, profile-picture URL, and follower / following / media counts. |
| account | fb-login | Read | Enumerate the Facebook Pages this token can act on and the Instagram business account linked to each (GET /me/accounts). |
| account | both | Read | Report the active credential: auth path (A = ig-login / B = fb-login), whether a token is configured, the resolved account ID, and β on Path B, via debug_token β validity, granted scopes, absolute expiry and days-left (with a refresh warning as the threshold nears). |
| media | both | Read | Fetch a single media object by id, including its carousel children (album items) under |
| media | both | Read | List the operated account's own media (feed posts, reels, stories, albums), newest first, cursor-paginated. |
| media | both | Write | Toggle whether a media object accepts new comments (POST /{media-id}?comment_enabled=true|false). |
| insights | both | Read | Account-level insights for the operated Instagram professional account (GET /{ig-id}/insights). |
| insights | both | Read | Follower / engaged-audience demographics for the operated account (GET /{ig-id}/insights with metric_type=total_value). |
| insights | both | Read | Insights for a single media object (GET /{media-id}/insights). |
| insights | both | Read | Hourly distribution of when the account's followers are online (GET /{ig-id}/insights?metric=online_followers&period=lifetime). |
| publishing | both | Write | Phase 1 of publishing: create a media container that Instagram ingests from a public HTTPS URL. |
| publishing | both | Read | Read a media container's processing state: status_code is IN_PROGRESS, FINISHED, ERROR, EXPIRED, or PUBLISHED. |
| publishing | both | Read | Report the account's content-publishing usage against its rolling-window quota. |
| publishing | both | Write | Publish a single feed image, or a 2β10 image carousel, in one call: create the container(s), wait for processing, then publish. |
| publishing | both | Write | Publish a reel in one call: create the REELS container, wait for processing (reels can take a while), then publish. |
| publishing | both | Write | Publish a photo or video story in one call: create the STORIES container, wait for processing, then publish. |
| publishing | both | Write | Phase 2 of publishing: publish a media container that has finished processing, returning the new media id. |
| comments | both | Write | Post a new top-level comment on a media object (POST /{media-id}/comments). |
| comments | both | Write | Permanently delete a comment (DELETE /{comment-id}). |
| comments | both | Read | Fetch a single comment by id, including its moderation state (hidden), parent/media context, and inline replies. |
| comments | both | Write | Hide a comment (POST /{comment-id}?hide=true) β reversible moderation, preferred over delete. |
| comments | both | Read | List the top-level comments on a media object, newest first, cursor-paginated, with threaded replies expanded inline under |
| comments | both | Read | List media the operated account has been TAGGED IN (the /tags edge), newest first, cursor-paginated. |
| comments | both | Write | Post a threaded reply under an existing comment (POST /{comment-id}/replies). |
| comments | both | Write | Unhide a previously hidden comment (POST /{comment-id}?hide=false). |
| discovery | fb-login | Read | Fetch another business/creator's PUBLIC profile and recent media by handle via GET /{ig-id}?fields=business_discovery.username(<handle>){followers_count,media_count,media{...}}. |
| discovery | fb-login | Read | List PUBLIC media under a hashtag id via GET /{hashtag-id}/top_media or /{hashtag-id}/recent_media (choose via |
| discovery | fb-login | Read | Resolve a hashtag name to its Instagram hashtag id(s) via GET /ig_hashtag_search?user_id={ig-id}&q=<hashtag> (the returned id feeds instagram_get_hashtag_media). |
Configuration
All settings are environment variables with the uniform IG_ prefix; the
canonical copy with inline comments is .env.example, and the
table below is generated from it β do not edit it by hand; run
npm run gen:readme. Real environment variables always take precedence over the
file. Writes preview by default; set IG_WRITE_MODE=apply (and
IG_ALLOW_DESTRUCTIVE=true for deletes) to perform them.
Variable | Default | Description |
| ig-login | fb-login (auto-detected when only one token is set) | |
| Path A long-lived IG-login token (secret) | |
| Path B page/system-user token (secret) | |
| IG professional-account ID (skip a lookup / disambiguate) | |
| Meta app id (token exchange/refresh, appsecret_proof, debug_token) | |
| Meta app secret (secret) | |
| Env-file location override (default: XDG path) | |
|
| Profile used when a tool call passes no |
|
| core | reader | publisher | all, or an explicit list |
| Packages to remove after profile resolution | |
| Packages forced read-only | |
|
| preview | apply (standing consent for writes) |
|
| Second gate for irreversible ops (delete_comment) |
|
| stdio | http |
|
| |
|
| |
| HTTP bearer token (secret; constant-time compare) | |
|
| Per-host concurrency semaphore |
|
| fetchAll hard item cap |
|
| Path-A auto-refresh threshold |
|
| Per-request timeout for Graph calls |
|
| debug | info | warn | error |
|
| Pretty-print JSON results |
Project identity
Item | Value |
npm package |
|
GitHub repository | |
MCP registry name |
|
Language / runtime | TypeScript (ESM), Node.js β₯ 22 |
MCP SDK |
|
Transports | stdio (default), Streamable HTTP (opt-in, loopback-bound) |
Env var prefix |
|
Graph API version | pinned |
License | MIT |
Note on names: the npm package and MCP registry entry use
instagram-mcp-ai(the unscopedinstagram-mcpwas already squatted on npm); the GitHub repository and the local working folder areinstagram-mcp. The difference is cosmetic and does not affect the build or runtime.
Non-goals
Ads / Marketing API β covered by Meta's official Ads MCP; out of scope permanently.
Unofficial APIs β no
instagram-private-api-style clients, no cookie/session reuse, no scraping. Official Graph API only.Consumer (personal) accounts β the Instagram Platform API only serves professional (Business/Creator) accounts; this server does not work around that.
Multi-tenant SaaS hosting β this is a personal, locally-run server (single operator, one or few accounts). Streamable HTTP stays loopback-bound.
Security notes
The env file is git-ignored and written owner-only (
0600) β it holds plaintext tokens/secrets; do not commit real credentials.The server uses the stdio transport by default and only logs to
stderr. Access tokens, app secrets andappsecret_proofHMACs are masked by a secret redactor before anything reaches a log sink; thelogin/refresh/doctorcommands never print a token or secret.SSRF guard: Graph calls are restricted to the two allowlisted hosts (
graph.instagram.com,graph.facebook.com) with the API version pinned, so a redirected or mistyped host cannot silently receive a token.Media ingestion is URL-only and by public HTTPS URL β no local files are uploaded, so the server never exfiltrates local content.
Writes are preview-by-default, applied writes are journaled, and irreversible ops need a second explicit gate (
IG_ALLOW_DESTRUCTIVE). See Write safety and docs/security.md.
Project documentation
Document | Contents |
Layered architecture, tool registry, transports, config, testing strategy | |
The two Instagram auth paths, token types & lifetimes, scopes, app setup | |
Full tool catalog specification (names, annotations, inputs, Graph calls) | |
End-to-end setup walkthrough | |
Common failures and fixes | |
Token storage, redaction, SSRF policy, write safety, supply chain | |
Rate limits, retry/backoff, pagination, error taxonomy, versioning | |
Stability contract and versioning policy | |
Corner-case catalog ( | |
Implementation roadmap: design gates D1βD3, phases M0βM6 with exit gates | |
Parallel work plan: agent-sized tasks, file ownership, dependency graph | |
Pre-publish release checklist | |
Six role-based senior design reviews β start with the consolidated summary |
The rendered documentation site mirrors these documents.
Support
This project is built and maintained in my own time. If it saves you or your team time, please consider supporting its continued development β sponsorship directly funds new tools, bug fixes and keeping pace with Meta's Graph surface.
GitHub Sponsors β one-off or recurring, with no platform fee taken out (the preferred option).
Ko-fi β quick one-off support; it also accepts PayPal, so it's the fallback for anyone without a GitHub account.
Donate (Donatree) β a no-account donation page (card, PayPal and more) for a one-off tip.
Trademark
Instagram and Meta are trademarks of Meta Platforms, Inc. This project is independent and not affiliated with or endorsed by Meta. The marks are used only nominatively β to identify the platform this software interoperates with. This project is licensed under the MIT License; that license covers the source code and grants no rights to use the Instagram or Meta trademarks.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
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/IvanBBaev/instagram-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server