Instagram Account MCP
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| IG_CONFIRM | No | Approval mode: `public`, `always` or `never`. | public |
| IG_MCP_HOME | No | Data folder for the state database, templates, exports and temp media. | ~/.instagram-account-mcp |
| GROQ_API_KEY | No | Groq API key. Defaults to the value stored in the OS keychain. | |
| IG_AUTH_MODE | No | Authentication mode: `facebook` or `instagram`. | |
| IG_MCP_VAULT | No | `file` to use the encrypted file instead of the OS keychain. | auto |
| IG_S3_BUCKET | No | S3-compatible media host bucket. | |
| IG_S3_REGION | No | S3-compatible media host region. | |
| IG_MCP_APP_ID | No | Your Meta app ID (Instagram app ID for Instagram Login). Defaults to the value stored in the OS keychain. | |
| IG_MEDIA_HOST | No | Media host: `tunnel`, `s3` or `azure`; `auto` prefers a configured bucket. | auto |
| GEMINI_API_KEY | No | Google Gemini API key. Defaults to the value stored in the OS keychain. | |
| IG_CLOUDFLARED | No | Path to `cloudflared`. | auto |
| IG_S3_ENDPOINT | No | S3-compatible media host endpoint. | |
| OPENAI_API_KEY | No | OpenAI API key. Defaults to the value stored in the OS keychain. | |
| IG_REDIRECT_URI | No | Redirect URI. Must match the redirect URI registered in the app. | http://localhost:8765/callback |
| IG_AI_TEXT_MODEL | No | `provider:model` for text jobs. Defaults to the value stored by the `ai` command. | |
| IG_GRAPH_VERSION | No | Graph API version. | v27.0 |
| IG_MCP_CONFIG_ID | No | Facebook Login for Business configuration ID (optional). | |
| IG_REDIRECT_PORT | No | Redirect port. Must match the redirect URI registered in the app. | 8765 |
| ANTHROPIC_API_KEY | No | Anthropic Claude API key. Defaults to the value stored in the OS keychain. | |
| IG_AI_IMAGE_MODEL | No | `provider:model` for image jobs. Defaults to the value stored by the `ai` command. | |
| IG_MCP_APP_SECRET | No | Your Meta app secret (Instagram app secret for Instagram Login). Defaults to the value stored in the OS keychain. | |
| IG_AI_VISION_MODEL | No | `provider:model` for vision jobs. Defaults to the value stored by the `ai` command. | |
| IG_AZURE_CONTAINER | No | Azure Blob media host container name. | |
| IG_MEDIA_TTL_HOURS | No | How long hosted links stay valid at most. | 48 |
| OPENROUTER_API_KEY | No | OpenRouter API key. Defaults to the value stored in the OS keychain. | |
| IG_DAILY_POST_LIMIT | No | Fallback when Meta's live daily post limit cannot be read. | 100 |
| IG_S3_ACCESS_KEY_ID | No | S3-compatible media host access key ID. | |
| AZURE_OPENAI_API_KEY | No | Azure OpenAI resource API key. Defaults to the value stored by the `ai` command. | |
| IG_AZURE_STORAGE_KEY | No | Azure Blob media host storage key. | |
| AZURE_OPENAI_ENDPOINT | No | Azure OpenAI resource endpoint. Defaults to the value stored by the `ai` command. | |
| IG_S3_PUBLIC_BASE_URL | No | S3-compatible media host public base URL. | |
| IG_AI_TRANSCRIBE_MODEL | No | `provider:model` for transcription jobs. Defaults to the value stored by the `ai` command. | |
| IG_S3_SECRET_ACCESS_KEY | No | S3-compatible media host secret access key. | |
| AZURE_OPENAI_API_VERSION | No | Azure OpenAI API version. Defaults to the value stored by the `ai` command. | |
| IG_AZURE_STORAGE_ACCOUNT | No | Azure Blob media host storage account name. | |
| IG_AZURE_CONTAINER_SAS_URL | No | Azure Blob media host container SAS URL. |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
Manage an Instagram professional account (Business or Creator) through Meta's official Instagram API.
Start with auth_status. If no account is connected, call connect_account (it opens the Meta sign-in in the browser). If the browser lands on a page that does not load, ask the user for that page's address and call complete_connect with it.
What you can do:
Publish: publish_photo, publish_reel, publish_carousel (2-20 images/videos), publish_story, publish_trial_reel (shown to non-followers first). Give file_path (this computer) or url. Media is converted to Instagram's specs automatically (prepare_media to check first). Add publish_at to schedule; Instagram has no native scheduling, so this server (or its background service) publishes it. Follow get_publish_status until "published". list_scheduled, reschedule, cancel_scheduled, resume_publish, publish_budget, media_host_status, find_location.
Library: list_media, get_media, list_stories, list_tagged, toggle_comments, delete_media.
Engage: list_comments, reply_to_comment, comment_on_media, hide_comment, delete_comment, private_reply (DM someone who commented, within 7 days), list_mentions, list_conversations, get_conversation, send_dm (only within 24 hours of their last message), triage_comments.
Insights: get_media_insights, get_account_insights, get_audience (demographics), export_insights (CSV).
Grow: analyze_post, find_outliers, best_publish_time, hashtag_research and hashtag_budget (30 unique hashtags per 7 days), benchmark_competitor (any public business/creator account), content_ideas, caption_check.
A/B test: create_ab_test publishes 2-4 trial reel variants (different video, hook, caption or cover) to non-followers and compares them after a set time. Meta's API cannot share a trial reel to followers: the user does that in the Instagram app, or the winner can be republished as a normal reel. get_ab_test, list_ab_tests, stop_ab_test.
Create: generate_caption, generate_hashtags, suggest_carousel, critique_cover, translate_caption, repurpose_video (cut vertical reels from a long video). Templates: list_templates, save_template, delete_template.
AI providers (Claude, OpenAI, Azure OpenAI, Gemini, OpenRouter, Groq, Ollama): see ai_status and set_ai_models. Without one, these tools return the data and a brief so you write the result yourself. They never publish; show drafts to the user.
Facebook Login vs Instagram Login (see auth_status): delete_media, hashtag_research and benchmark_competitor need Facebook Login. Not possible through Meta's API: adding licensed music, filters, story stickers or links, shopping tags, editing a published caption, and posting from personal accounts.
Safety: anything others can see (publishing, scheduling, replies, DMs, hiding comments) or destructive needs the user's approval. If a tool returns CONFIRMATION REQUIRED, show the summary to the user and only call again with the confirmation_token after they say yes. Never invent approval.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": true
} |
| logging | {} |
| prompts | {
"listChanged": true
} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| auth_statusA | Show whether the Meta app is configured, which Instagram accounts are connected (and whether their sign-in is healthy), the default account, the login type, the media host, AI providers and Meta API usage. Call this first in a new conversation. |
| connect_accountA | Start the Meta sign-in to connect (or reconnect) Instagram professional accounts. Opens the browser on this computer and returns the sign-in link. With Facebook Login the user selects the Facebook Page(s) their Instagram account is linked to; every linked account is connected. Waits up to wait_seconds for them to finish. If the browser lands on a page that does not load, ask the user to copy that page's full address and call complete_connect with it. |
| complete_connectA | Finish a connect_account sign-in by giving the full URL the browser landed on after approving (it contains ?code=...&state=...). Use when the callback page did not load or the sign-in was done on another device. |
| list_accountsA | List the Instagram accounts connected to this server. |
| get_profileB | Live profile of a connected account: username, name, biography, website, followers, following, media count, profile picture. |
| set_default_accountA | Choose which connected account is used when a tool call does not name one. |
| disconnect_accountA | Remove a connected account from this server and delete its stored token. With revoke=true (Facebook Login) it also removes this app's permissions from the Facebook user. Scheduled posts for it stop. Needs the user's confirmation. |
| publish_photoA | Publish (or schedule) a single-image feed post. Images are converted to JPEG and fitted into Instagram's 4:5 to 1.91:1 range automatically. Needs the user's confirmation. Runs in the background; follow get_publish_status. |
| publish_reelA | Publish (or schedule) a reel: 3 seconds to 15 minutes, up to 300 MB, 9:16 fills the screen (fit: crop or blur reframes other shapes). Converted to H.264/AAC MP4 when needed. Licensed music can't be added through the API. Needs the user's confirmation; runs in the background. |
| publish_trial_reelA | Publish a trial reel: Instagram shows it to non-followers first, so you can test an idea without your followers seeing it. graduation SS_PERFORMANCE lets Instagram share it with followers automatically if it performs well; MANUAL keeps it trial-only until you share it yourself in the Instagram app (the API has no call to graduate a trial reel). For comparing several versions, use create_ab_test. Needs confirmation. |
| publish_carouselA | Publish (or schedule) a carousel of 2 to 20 images and/or videos (videos 3-60 s). Instagram crops every item to the first item's shape; use fit to control reframing. Alt text and user tags per image. Needs the user's confirmation; runs in the background. |
| publish_storyA | Publish (or schedule) a story from an image or a video (3-60 s, up to 100 MB). Stories last 24 hours. Stickers, links, polls and music can't be added through the API. Needs the user's confirmation. |
| get_publish_statusA | Status of a publishing job: each item's progress (preparing, uploading %, processing), errors with fixes, and the permalink once published. Can wait for changes. |
| list_scheduledB | Upcoming scheduled posts (soonest first), posts being published or waiting, and recent results from this computer. |
| rescheduleA | Move a scheduled, waiting or missed (computer was off) post to a new time. Needs the user's confirmation. |
| cancel_scheduledA | Stop a post that has not been published yet (scheduled, waiting or in progress). Hosted copies are removed. Can be undone with resume_publish. Needs the user's confirmation. |
| resume_publishA | Retry a failed post, continue one paused on an expired sign-in, re-check one waiting for the publishing limit, restore a cancelled one, or publish one that missed its scheduled time (computer was off) right now. Cancelled and missed posts need the user's confirmation again. If a publish may already have gone through, it checks Instagram first and never publishes twice. |
| prepare_mediaA | Inspect an image or video and list what Instagram would reject for a placement (format, codec, aspect ratio, length, size). With convert=true, writes a fixed copy (JPEG / H.264+AAC MP4, reframed with fit) and returns its path. Publishing tools do this automatically. Needs ffmpeg. |
| publish_budgetA | How many API posts are left in Instagram's rolling 24-hour window (Meta's limit; carousels count once), plus posts scheduled for the next 24 hours. |
| media_host_statusA | How local files reach Instagram, and whether it works: tunnel (Cloudflare quick tunnel from this computer), s3 (S3/R2/B2 bucket) or azure (Blob Storage). Facebook-Login accounts upload videos straight to Meta; images always go through the host. |
| find_locationA | Instagram location tags use the Facebook Page ID of a place. Pass a Facebook Page URL or ID to check it (Facebook Login accounts), or a search query (needs Meta's Page Public Metadata Access, which most apps don't have; then look the place up on facebook.com and pass its Page URL). |
| list_mediaA | The account's published posts, reels and carousels, newest first: id, type, caption (shortened), link, time, likes and comments. Use get_media for one post in full and get_media_insights for its numbers. |
| get_mediaB | Full details of one post, reel or carousel: caption, media and thumbnail URLs, link, counts, whether comments are on, and carousel items. |
| list_storiesA | Stories currently live (the last 24 hours). Story insights also disappear after 24 hours. |
| list_taggedB | Media where other accounts tagged this account (photo tags), newest first. |
| toggle_commentsA | Enable or disable comments on one of your posts. Visible to everyone, so the user confirms first. (Captions cannot be edited through Meta's API.) |
| delete_mediaA | Permanently delete a post, reel, story or whole carousel (single carousel items cannot be deleted). Only for accounts connected with Facebook Login (Meta's rule). Cannot be undone; the user confirms first. |
| list_commentsA | Comments with their replies, for one post (media_id) or across the most recent posts. Each comment says whether you already answered. Use unanswered: true to build a reply queue; triage_comments sorts them by priority. |
| reply_to_commentA | Public reply under a top-level comment (Meta does not allow replying to replies or to hidden comments). The user confirms first. |
| comment_on_mediaB | Add a new top-level comment on one of your posts (e.g. a pinned-style note or first comment). Public; the user confirms first. |
| hide_commentA | Hide a comment from everyone except its author (or show it again with hide: false). The user confirms first. |
| delete_commentA | Permanently delete a comment on your post (yours or someone else's). Prefer hide_comment unless it must go. Cannot be undone; the user confirms first. |
| private_replyA | Send one private Direct message to the person who wrote a comment (e.g. the link they asked for). One message per comment, within 7 days of it. The user confirms first. |
| list_mentionsA | Where others mention this account: posts that tagged it, newest first. With comment_id or media_id (from a mention notification) it returns that specific @mention. |
| list_conversationsB | Recent Instagram Direct conversations: who, their last message, and whether you can still reply (Instagram allows replies for 24 hours after their last message). |
| get_conversationB | Messages in one Direct conversation, newest first (Meta returns details for the 20 most recent). |
| send_dmA | Reply in Instagram Direct to someone who messaged this account. Allowed only within 24 hours of their last message (7 days with human_agent if your Meta app has the Human Agent feature). Text up to 1000 bytes. The user confirms first. |
| get_media_insightsA | Lifetime numbers for posts, reels or stories: views, reach, likes, comments, saves, shares, total interactions, follows, profile visits; reels add average watch time (ms), total watch time and skip rate; stories add navigation and replies. Give media_ids, or omit them for the latest posts. Story insights vanish after 24 hours and need 5+ viewers. |
| get_account_insightsB | Account-level numbers. Presets: overview (last N days totals: reach, views, accounts engaged, interactions, likes, comments, saves, shares, follows/unfollows, link taps), daily (reach per day), reach_breakdown (by reels/posts/stories and followers vs non-followers), follows (follows vs unfollows). Or set metrics yourself (reach, views, accounts_engaged, total_interactions, likes, comments, saves, shares, replies, reposts, follows_and_unfollows, profile_links_taps) with period, metric_type, breakdown and since/until (max 30 days). |
| get_audienceA | Who your followers (or the people who engaged) are: age, gender, country and city, with shares in %. Needs at least 100 followers; Meta returns the top 45 values per breakdown. |
| export_insightsA | Writes a CSV (one row per post: date, type, link, caption, views, reach, likes, comments, saves, shares, interactions, follows, profile visits, reel watch time, skip rate) for spreadsheets. Saved in the data folder's exports/ (a bare file name goes there too). Writing anywhere else needs the user's approval. Never overwrites a file: a -1, -2... suffix is added. |
| analyze_postA | How one post, reel or story did against your own recent posts of the same format: outlier score (views vs your median), engagement rate, saves+shares per viewer, reel watch time and skip rate, and plain-language notes. With an AI provider it adds a diagnosis and next steps; without one it returns a brief so you can write it. |
| find_outliersB | Your best and worst recent posts relative to your own median on one metric (views, reach, shares, saved, total_interactions, engagement_rate, save_share_rate, follows...). Shows what to repeat and what to drop. |
| best_publish_timeA | When your own posts performed best, by weekday and 3-hour block in your time zone (each post scored against your median, so one viral post does not decide), plus when followers are online if Meta provides it. |
| hashtag_researchA | For each hashtag: top (or most recent) public posts, their median likes and comments, format mix, related hashtags people use with it, and example posts. Instagram allows 30 different hashtags per 7 days per account (repeats are free); the remaining budget is shown. Facebook Login accounts only. |
| hashtag_budgetA | How many of the 30 hashtag searches per rolling 7 days are left, and which hashtags can be repeated for free. |
| benchmark_competitorA | Public stats of any Business or Creator account (Meta's Business Discovery): followers, posting frequency, format mix, median likes/comments/views, engagement per follower, top hashtags and top posts. Compare with your own using get_account_insights. Facebook Login accounts only. |
| create_ab_testA | Publishes 2-4 versions of a reel (different hook, cut, caption or cover) as trial reels at the same time. Instagram shows trial reels to non-followers first, so each version gets a comparable audience without spamming followers. After decide_after_hours (default 48, 12-168) the background service compares them on the chosen metric with a significance test and reports a winner or "inconclusive". Meta's API cannot graduate trial reels: you share the winner to followers in the Instagram app; with share_winner: "republish" this server instead republishes the winning version as a normal reel. Versions should differ in one thing. Each version counts toward the publishing limit. Asks the user first. |
| get_ab_testA | Shows an A/B test: each version's publishing status, link and latest metrics, the decision time, and (when finished) the verdict with confidence and next step. refresh: true pulls current numbers from Instagram before the decision. |
| list_ab_testsA | All A/B tests, newest first, optionally filtered by status. |
| stop_ab_testA | Stops a test: versions not yet published are cancelled and no decision is made. Trial reels already published stay up (delete them with delete_media or in the app). |
| ai_statusA | Which AI providers are connected (Claude, OpenAI, Azure OpenAI, Gemini, OpenRouter, Groq, Ollama, custom) and which model each job uses: text (captions, analysis), vision (covers, images), image, transcribe. Keys are never shown. |
| set_ai_modelsA | Pick which connected provider and model handle each job, as "provider:model" (Azure: "azure:"), e.g. text "anthropic:claude-opus-5-5", vision "openai:gpt-5.5", transcribe "groq:whisper-large-v3". Pass null to go back to the automatic choice. |
| generate_captionA | Drafts caption options (hook first line, short body, call to action, hashtags, and on-screen hook text for reels) from a description, a transcript file, or the media file itself (images are looked at; videos are transcribed when a transcription model is connected). Applies the template and checks Instagram's limits. Drafts only: nothing is published. Without an AI model it returns a brief so you write them. |
| generate_hashtagsA | Suggests a hashtag set for a post: a mix of broad, niche, community, branded and location tags with reasons, the 5-10 to actually use, and tags to avoid. AI-based; for live data on how active a hashtag is use hashtag_research (Facebook Login only, 30 hashtags per 7 days). |
| suggest_carouselA | Turns text, an article, notes or a transcript into a carousel outline: slide-by-slide headline, body and visual (up to 20 slides), plus caption and hashtags. Design the slides from it, then publish with publish_carousel. |
| critique_coverA | Scores 1-4 cover images (or 4 frames taken from a video) the way people see them: full screen in the reels feed and as a small grid tile. Ranks them and lists fixes. Needs a vision model (Claude, OpenAI, Gemini, Azure). |
| translate_captionA | Drafts the caption in other languages, keeping the hook, @mentions, #hashtags and links. Drafts only. |
| caption_checkA | Checks a caption against Instagram's limits (2,200 characters, 30 hashtags, 20 @mentions) and craft rules (hook length before "more", call to action, hashtag count, links, engagement bait), and previews it with a template applied exactly as it will be published. |
| repurpose_videoA | Finds the best standalone moments in a long local video (transcribed, or from a transcript file) and cuts them into vertical 1080x1920 reels with a hook, on-screen text and caption for each. Or pass clips with start/end seconds to cut exactly those. layout crop fills the frame from the centre; blur fits the whole frame over a blurred fill. Returns file paths ready for publish_reel. Needs ffmpeg. |
| content_ideasA | Next post ideas grounded in this account's recent performance: which formats and topics over- and under-performed (likes and comments vs the account's median), optionally focused on a topic. With an AI model it returns ideas with format, hook, angle, evidence and confidence; otherwise the data for you to reason from. |
| triage_commentsA | Reads recent comments (one post, or the latest posts) and sorts them: questions, praise, feedback, complaints, leads, spam, abuse. Each gets a priority, a suggested action (reply, private reply, hide, delete) and a draft reply, plus post ideas the audience is asking for. Drafts only: nothing is sent. Without an AI model it returns the comments for you to triage. |
| list_templatesB | Caption templates: header/footer, hashtags (in the caption or first comment), mentions, first comment, collaborators, location and the account voice used by the writing tools. Saved as JSON in the templates folder. |
| save_templateB | Creates or replaces a caption template. Use extends to build on another template (hashtags, mentions and collaborators are merged; guidance is appended). |
| delete_templateA | Deletes a saved template file. Asks the user first. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
| publish_post | Guided flow: look at the media → caption and hashtags → preview → publish or schedule. |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
TDQS
Scored across 65 tools
Most tools target a clearly distinct action+resource (publishing, comment moderation, DM, scheduling, analytics), and the descriptions explicitly cross-reference when to prefer one over another (e.g. hide_comment over delete_comment, generate_hashtags vs hashtag_research). The remaining overlaps sit in clusters — get_media_insights / analyze_post / find_outliers / get_account_insights / benchmark_competitor, and list_comments / triage_comments / list_mentions — where an agent must read carefully to pick correctly.
Almost entirely snake_case, with a dominant verb_noun shape (publish_photo, reply_to_comment, get_media_insights, delete_template). A handful of noun/status names break the pattern (publish_budget, auth_status, media_host_status, hashtag_budget, ai_status, content_ideas), but the casing convention never varies, so the set stays predictable.
65 tools is far above what an agent can hold in context comfortably, even for a broad domain. Several analytics tools (get_media_insights, analyze_post, find_outliers, best_publish_time, export_insights) and AI-writing tools (generate_caption, generate_hashtags, suggest_carousel, translate_caption, content_ideas) could be consolidated behind a mode parameter.
The surface covers the full lifecycle: connect/auth, media prep, publish/schedule/cancel/resume/status, media and story listing, comments and DMs, insights and audience, competitor and hashtag research, A/B testing, AI drafting and templates. The only apparent gaps are Meta API restrictions (caption editing, sticker/music on stories), which are documented in the descriptions rather than left as dead ends.