Google Search Console integration for Model Context Protocol (MCP)
Instagram is installed from its publisher's own source and answers where it runs, so this marketplace is not in the path of a single call. There is no address here to send one to, and a panel that pretended otherwise would be showing you an answer we made up. Install it and call it from your own client — the Installation tab has the entry for each one.
What it does
Instagram via Meta's official Graph API: publishing, comments, DMs, insights and discovery.
Quickstart
# 1 — add it to Claude Code
claude mcp add --scope user --env 'IG_ACCESS_TOKEN=${IG_ACCESS_TOKEN}' --transport stdio qaassimq-instagram-mcp '--' npx -y @qaassim/instagram-mcp-server
# 2 — ask your agent for something these tools do
# instagram_publish_image, instagram_publish_reel, instagram_publish_story and 39 more
It needs IG_ACCESS_TOKEN: this reads it from your environment, so export it first.
Instagram costs nothing on mcprush: there is no plan to choose here, no cap to set and nothing mcprush can bill you for.
Collected from a public index. Nobody has claimed this account, so nothing here was written by its author — claim it if it is yours.
Where are you running it?
Every route below installs the same thing and ends at the same approval screen. This one runs on your machine: your client starts Instagram as a process under your own user, with your files and your network, so the tool surface below is what it can do to your computer rather than to a server somewhere else. Its scan result is on the Security tab — read the surface before you approve it.
This is a public server: you run it yourself and this marketplace is not in the path. You need Node.js — the current LTS (24) is the safe choice; npx comes with it. Claude Code registers it in one command; --scope user makes it available in every project. Claude Code reads IG_ACCESS_TOKEN (Long-lived Instagram access token: an IGAA... token on instagram_login, or a long-lived Page or User token with the instagram_* scopes on facebook_login) from your environment each time it starts the server, so the value stays out of its config: export it in your shell profile (macOS, Linux), or run setx IG_ACCESS_TOKEN … and open a new terminal (Windows). The '--' is in quotes so that PowerShell passes it on.
claude mcp add --scope user --env 'IG_ACCESS_TOKEN=${IG_ACCESS_TOKEN}' --transport stdio qaassimq-instagram-mcp '--' npx -y @qaassim/instagram-mcp-serverReconnect, or start a new session, and the tools appear in the model’s tool list.
It reaches a system of yours, so it needs your own credential rather than the publisher’s: IG_ACCESS_TOKEN — Long-lived Instagram access token: an IGAA... token on instagram_login, or a long-lived Page or User token with the instagram_* scopes on facebook_login.. You set it in your own client’s config, on your machine — this marketplace never holds it.
One config entry your client uses to start the process locally. A local server runs with your file system and your network, which is why it is priced without metering.
42 tools, with what each one reads, writes and reaches shown before you agree — the same list on every route above. Read the tool surface.
Tool surface
What the model actually sees. Descriptions are diffed on every release — see version history.
Read from its source code. A server that builds its tool list when it starts can list more tools than this.
Publish a single image to the Instagram feed. The image must be a JPEG served from a public HTTPS URL that returns the file directly — no redirects, no authentication, no HTML wrapper. Meta fetches it server-side, so a local path or a signed URL that expires will fail. For two or more images in…
| Parameter | Type | Required | Notes |
|---|---|---|---|
| image_url | string | yes | Public HTTPS URL of a JPEG image |
| caption | string | no | — |
| alt_text | string | no | Accessibility alt text. Supported on image posts only, not reels or stories. |
| location_id | string | no | Facebook Page ID of a location to tag |
| user_tags | array | no | — |
| collaborators | array | no | Up to 3 public usernames invited as collaborators |
| is_ai_generated | boolean | no | Mark the content as AI-generated. Set it when the image was AI-created. |
| account_id | string | no | Instagram professional account ID. Omit to use the token's own account. |
Publish a video as a Reel. Reels are the only way to publish video to the feed — Instagram converted standalone feed video to Reels. The video must be at a public HTTPS URL; Meta downloads and transcodes it, which takes time, so this tool waits for processing before publishing. If processing…
| Parameter | Type | Required | Notes |
|---|---|---|---|
| video_url | string | yes | Public HTTPS URL of an MP4 or MOV video |
| caption | string | no | — |
| cover_url | string | no | Public HTTPS URL of a custom cover image. Overrides thumb_offset. |
| thumb_offset | integer | no | Milliseconds into the video to use as the thumbnail |
| share_to_feed | boolean | no | Whether the reel also appears in the main feed grid. Defaults to Instagram's setting. |
| location_id | string | no | Facebook Page ID of a location to tag |
| user_tags | array | no | — |
| collaborators | array | no | Up to 3 public usernames invited as collaborators |
| audio_name | string | no | Name for the audio track attributed to this reel |
| is_ai_generated | boolean | no | Mark the content as AI-generated |
| wait_seconds | integer | no | — |
| account_id | string | no | Instagram professional account ID. Omit to use the token's own account. |
Publish an image or video story. Stories expire after 24 hours. Supply exactly one of image_url or video_url. Stickers, polls, links and music cannot be added through the API — Meta exposes none of those on the publishing endpoint.
| Parameter | Type | Required | Notes |
|---|---|---|---|
| image_url | string | no | Public HTTPS URL of a JPEG for an image story |
| video_url | string | no | Public HTTPS URL of an MP4/MOV for a video story |
| wait_seconds | integer | no | — |
| account_id | string | no | Instagram professional account ID. Omit to use the token's own account. |
Publish a carousel of …-… images and/or videos as one post. This creates a child container per item, waits for any video children to process, then creates and publishes the carousel container. The whole carousel counts as a single post against the publishing quota. Example: "post these three…
| Parameter | Type | Required | Notes |
|---|---|---|---|
| items | array | yes | Ordered carousel items, …-… of them |
| caption | string | no | — |
| location_id | string | no | Facebook Page ID of a location to tag |
| collaborators | array | no | Up to 3 collaborator usernames |
| is_ai_generated | boolean | no | Mark the carousel as AI-generated |
| wait_seconds | integer | no | — |
| account_id | string | no | Instagram professional account ID. Omit to use the token's own account. |
Low-level escape hatch: create a media container with arbitrary parameters, without publishing it. Prefer instagram_publish_image / _reel / _story / _carousel, which run the whole flow. Use this when you need a parameter those tools do not expose, or when assembling a carousel from children that…
| Parameter | Type | Required | Notes |
|---|---|---|---|
| media_type | string | no | Omit for a single image; Instagram infers IMAGE |
| image_url | string | no | — |
| video_url | string | no | — |
| caption | string | no | — |
| children | array | no | Child container IDs, for media_type=CAROUSEL |
| is_carousel_item | boolean | no | True when this container is a carousel child |
| extra_params | object | no | — |
| account_id | string | no | Instagram professional account ID. Omit to use the token's own account. |
Check whether a media container is ready to publish. status_code is one of: ${Object.entries(CONTAINER_STATUS) .map(([code, meaning]) =>
| Parameter | Type | Required | Notes |
|---|---|---|---|
| container_id | string | yes | Container ID returned when the container was created |
Publish a media container that is already FINISHED. Use this to complete a publish that was interrupted, or after assembling a carousel with instagram_create_container. Publishing a container that is still IN_PROGRESS fails; check instagram_get_container_status first.
| Parameter | Type | Required | Notes |
|---|---|---|---|
| container_id | string | yes | Container ID to publish |
| account_id | string | no | Instagram professional account ID. Omit to use the token's own account. |
Get the authenticated Instagram professional account's profile, and the server's active capabilities. Returns username, account type, follower/following/media counts, bio and website, plus which Meta auth mode this server is running in and what that mode cannot do. Call this first in a new…
| Parameter | Type | Required | Notes |
|---|---|---|---|
| account_id | string | no | — |
| response_format | yes | — |
Check how much of the 100-post / 24-hour API publishing quota the account has used. Meta counts a carousel as one post. Call this before a bulk publish run, and after a publish failure that might be quota exhaustion rather than a bad request.
| Parameter | Type | Required | Notes |
|---|---|---|---|
| account_id | string | no | — |
| response_format | yes | — |
Inspect the configured access token: its type, scopes, and expiry. On the facebook_login path this calls debug_token and needs IG_APP_ID and IG_APP_SECRET. On the instagram_login path Meta exposes no debug endpoint, so this verifies the token by reading the account and reports what it can. Use…
| Parameter | Type | Required | Notes |
|---|---|---|---|
| response_format | yes | — |
Extend the configured long-lived access token and return the new one. instagram_login: refreshes an Instagram long-lived token for another 60 days. The token must be at least 24 hours old and not yet expired. facebook_login: exchanges the token for a fresh long-lived one; needs IG_APP_ID and…
No parameter schema on file.
List the Facebook Pages this token administers, with the Instagram professional account linked to each. Use it to find the Instagram account ID to set as IG_USER_ID. Only available on the facebook_login path, where accounts are reached through a Page.
| Parameter | Type | Required | Notes |
|---|---|---|---|
| response_format | yes | — |
List top-level comments on one of the account's media objects. Replies are nested one level deeper — use instagram_list_comment_replies for a specific thread. Hidden comments are included with hidden=true. Example: "what are people saying on our latest post" -> first instagram_list_media, then…
| Parameter | Type | Required | Notes |
|---|---|---|---|
| media_id | string | yes | Media ID whose comments to read |
| limit | integer | no | Maximum comments per page. Max 100. |
| after | string | no | Pagination cursor from a previous call's next_cursor. |
| response_format | yes | — |
Get one comment by ID, including its text, author, like count and hidden state.
| Parameter | Type | Required | Notes |
|---|---|---|---|
| comment_id | string | yes | Comment ID |
| response_format | yes | — |
List the replies to one top-level comment. Instagram supports exactly one level of nesting, so replies have no replies of their own.
| Parameter | Type | Required | Notes |
|---|---|---|---|
| comment_id | string | yes | Top-level comment ID |
| limit | integer | no | Maximum comments per page. Max 100. |
| after | string | no | Pagination cursor from a previous call's next_cursor. |
| response_format | yes | — |
Post a new top-level comment on one of the account's own media objects. To answer someone else's comment use instagram_reply_to_comment instead — a reply threads under theirs and notifies them.
| Parameter | Type | Required | Notes |
|---|---|---|---|
| media_id | string | yes | Media ID to comment on |
| message | string | yes | Comment text. Instagram rejects repeated identical text as spam. |
Reply to a comment, threaded underneath it. Only top-level comments accept replies — Instagram allows a single level of nesting. Replying to a reply fails; reply to its parent_id instead.
| Parameter | Type | Required | Notes |
|---|---|---|---|
| comment_id | string | yes | Top-level comment ID to reply to |
| message | string | yes | Comment text. Instagram rejects repeated identical text as spam. |
Hide a comment from public view, or unhide one. Hiding is reversible and leaves the comment visible to its author — prefer it to deletion for borderline content. Use instagram_delete_comment only for comments on the account's own media that should be gone for good.
| Parameter | Type | Required | Notes |
|---|---|---|---|
| comment_id | string | yes | Comment ID |
| hide | boolean | no | true hides the comment, false unhides it |
Permanently delete a comment. Works on comments the account authored, and on comments by others on the account's own media. This cannot be undone — instagram_hide_comment is the reversible alternative.
| Parameter | Type | Required | Notes |
|---|---|---|---|
| comment_id | string | yes | Comment ID to delete permanently |
Turn commenting on or off for one of the account's media objects. Disabling hides the whole comment thread and blocks new comments. Existing comments return when it is re-enabled.
| Parameter | Type | Required | Notes |
|---|---|---|---|
| media_id | string | yes | Media ID |
| enabled | boolean | yes | true allows comments, false disables them |
Read a comment in which the account was @mentioned, by comment ID. Meta provides no endpoint that lists mentions — they are delivered to your app through the "mentions" webhook field, and this tool reads one once you have its ID. If you have no webhook configured, you cannot discover mentions…
| Parameter | Type | Required | Notes |
|---|---|---|---|
| comment_id | string | yes | Comment ID from a mentions webhook payload |
| account_id | string | no | Instagram professional account ID. Omit to use the token's own account. |
| response_format | yes | — |
Read a media object whose caption @mentions the account, by media ID. As with mentioned comments, Meta delivers these through the "mentions" webhook rather than a list endpoint. Photo tags are a different edge — use instagram_list_tagged_media for those, which does support listing.
| Parameter | Type | Required | Notes |
|---|---|---|---|
| media_id | string | yes | Media ID from a mentions webhook payload |
| account_id | string | no | Instagram professional account ID. Omit to use the token's own account. |
| response_format | yes | — |
Reply to a mention of the account on someone else's media. Pass comment_id to reply to the specific comment that mentioned you; omit it to leave a new top-level comment on the media instead. The media's owner must allow comments.
| Parameter | Type | Required | Notes |
|---|---|---|---|
| media_id | string | yes | Media ID the mention appears on |
| message | string | yes | Reply text |
| comment_id | string | no | Comment ID to thread the reply under. Omit to comment on the media itself. |
| account_id | string | no | Instagram professional account ID. Omit to use the token's own account. |
Resolve a hashtag name to its Instagram hashtag ID. The ID is what instagram_get_hashtag_media needs. Pass the name without the leading #. Hard limit: Meta allows an account to query 30 UNIQUE hashtags in any rolling 7-day window. Repeating a hashtag you already queried in that window is free,…
| Parameter | Type | Required | Notes |
|---|---|---|---|
| hashtag | string | yes | Hashtag name without the # — e.g. 'coffee' |
| account_id | string | no | Instagram professional account ID. Omit to use the token's own account. |
List public media carrying a hashtag — either the top-performing posts or the most recent ones. Resolve the hashtag ID with instagram_search_hashtag first. Meta returns only public media from professional accounts, caps the window at the last 24 hours for 'recent', and never returns…
| Parameter | Type | Required | Notes |
|---|---|---|---|
| hashtag_id | string | yes | Hashtag ID from instagram_search_hashtag |
| edge | string | no | 'top_media' ranks by engagement; 'recent_media' returns the last 24 hours chronologically |
| limit | integer | no | Maximum posts to return |
| account_id | string | no | Instagram professional account ID. Omit to use the token's own account. |
| response_format | yes | — |
Look up another public Instagram professional account by username: follower count, media count, bio, and recent posts with engagement. This is the competitor-research endpoint. It works only for public professional (Business or Creator) accounts — personal and private accounts return an error. It…
| Parameter | Type | Required | Notes |
|---|---|---|---|
| username | string | yes | Public professional account username, without the @ |
| media_limit | integer | no | How many recent posts to include. 0 returns profile figures only. |
| account_id | string | no | Instagram professional account ID. Omit to use the token's own account. |
| response_format | yes | — |
List every insight metric this server can request, which surface it applies to, and which breakdowns each one accepts. Makes no API call. Read this before calling instagram_get_account_insights or instagram_get_media_insights with custom metrics — an unsupported metric or an invalid…
| Parameter | Type | Required | Notes |
|---|---|---|---|
| response_format | yes | — |
Get account-level insights: reach, views, interactions, likes, comments, shares, saves, follows and profile link taps. Defaults to the full interaction metric set for the last 7 days as totals. Narrow with metrics, or split a metric with breakdown (one metric at a time when using a breakdown).…
| Parameter | Type | Required | Notes |
|---|---|---|---|
| metrics | array | no | — |
| since | string | no | Start date, YYYY-MM-DD. Defaults to 7 days ago. Meta allows at most 30 days per call. |
| until | string | no | End date, YYYY-MM-DD. Defaults to today. |
| metric_type | string | no | — |
| breakdown | string | no | — |
| account_id | string | no | Instagram professional account ID. Omit to use the token's own account. |
| response_format | yes | — |
Get per-post insights for one media object. The valid metric set depends on the media type, so pass media_product_type and the right defaults are used: FEED for posts and carousels, REELS for reels, STORY for stories. Carousel albums report only whole-post figures — Meta serves no per-child…
| Parameter | Type | Required | Notes |
|---|---|---|---|
| media_id | string | yes | Media ID to read insights for |
| media_product_type | string | no | Which metric set to request. Check the media's media_product_type with instagram_get_media. |
| metrics | array | no | Override the default metric set for this media type. See instagram_list_metric_catalog. |
| response_format | yes | — |
Get the follower or engaged-audience breakdown by age, city, country or gender. These are lifetime metrics and a breakdown is mandatory. Meta withholds demographics for accounts under roughly 100 followers, which comes back as an empty result rather than an error. Example: "where are our…
| Parameter | Type | Required | Notes |
|---|---|---|---|
| metric | string | no | — |
| breakdown | string | yes | Dimension to break the audience down by |
| timeframe | string | no | — |
| account_id | string | no | Instagram professional account ID. Omit to use the token's own account. |
| response_format | yes | — |
Read insights for every story currently live on the account, in one call. Stories vanish after 24 hours and their insights go with them, so this is the tool for catching a day's story performance before it is lost. Equivalent to instagram_list_stories followed by instagram_get_media_insights on…
| Parameter | Type | Required | Notes |
|---|---|---|---|
| account_id | string | no | Instagram professional account ID. Omit to use the token's own account. |
| response_format | yes | — |
List the account's published media, newest first. Returns one page with a cursor. Covers feed posts, reels and carousels; stories are separate (instagram_list_stories) because they expire. Use this to find media IDs for instagram_get_media_insights, instagram_list_comments, or…
| Parameter | Type | Required | Notes |
|---|---|---|---|
| limit | integer | no | Maximum items to return in this page. Default 25, max 100. |
| after | string | no | Pagination cursor from a previous call's next_cursor. Omit for the first page. |
| fields | array | no | — |
| account_id | string | no | Instagram professional account ID. Omit to use the token's own account. |
| response_format | yes | — |
Get one media object by ID, with caption, type, engagement counts and permalink. Use instagram_list_media to find IDs. For a carousel, instagram_get_media_children lists the individual photos and videos inside it.
| Parameter | Type | Required | Notes |
|---|---|---|---|
| media_id | string | yes | Instagram media ID |
| fields | array | no | — |
| response_format | yes | — |
List the individual images and videos inside a carousel post. Only meaningful for media whose media_type is CAROUSEL_ALBUM. Note that Meta serves no per-child insights — insights exist only for the carousel as a whole.
| Parameter | Type | Required | Notes |
|---|---|---|---|
| media_id | string | yes | Carousel media ID |
| response_format | yes | — |
List the account's currently live stories. Stories expire 24 hours after posting, so this returns only what is live right now. Story insights come from instagram_get_media_insights with media_product_type="STORY".
| Parameter | Type | Required | Notes |
|---|---|---|---|
| account_id | string | no | Instagram professional account ID. Omit to use the token's own account. |
| response_format | yes | — |
List media published by other accounts in which this account was tagged. Different from mentions: this is the photo-tag edge, not @mentions in captions or comments. Use instagram_list_mentions for those.
| Parameter | Type | Required | Notes |
|---|---|---|---|
| limit | integer | no | Maximum items to return in this page. Default 25, max 100. |
| after | string | no | Pagination cursor from a previous call's next_cursor. Omit for the first page. |
| account_id | string | no | Instagram professional account ID. Omit to use the token's own account. |
| response_format | yes | — |
Permanently delete one of the account's own posts, reels or stories. This cannot be undone and the media is removed from Instagram. Requires the instagram_manage_contents permission. Confirm the media ID with instagram_get_media before calling.
| Parameter | Type | Required | Notes |
|---|---|---|---|
| media_id | string | yes | Media ID to delete permanently |
List Instagram Direct conversations in the account's inbox, most recently updated first. Each entry carries the participant IGSIDs needed to send a message. Requires the messaging permission with Advanced Access. Example: "any new DMs?" -> limit=10, then instagram_get_conversation on the ones…
| Parameter | Type | Required | Notes |
|---|---|---|---|
| limit | integer | no | Maximum conversations per page |
| after | string | no | Pagination cursor from a previous call |
| account_id | string | no | Instagram professional account ID. Omit to use the token's own account. |
| response_format | yes | — |
Read the messages in one conversation, newest first. Note the 24-hour rule before replying: a standard reply is only allowed within 24 hours of the user's most recent message. Check the newest created_time to see whether the window is still open.
| Parameter | Type | Required | Notes |
|---|---|---|---|
| conversation_id | string | yes | Conversation ID from instagram_list_conversations |
| limit | integer | no | Maximum messages to return |
| response_format | yes | — |
Send a text message to an Instagram user. Meta allows this only within 24 hours of that user's last message to the account. Outside the window, set tag="HUMAN_AGENT" to use the 7-day human-agent allowance; unsolicited messages are not possible at all. Requires the messaging permission with…
| Parameter | Type | Required | Notes |
|---|---|---|---|
| recipient_id | string | yes | — |
| text | string | yes | Message text, up to 1000 characters |
| tag | string | no | Set HUMAN_AGENT to reply up to 7 days out, when a human is handling the thread |
| account_id | string | no | Sending account ID; omit for the token's own |
Send an image, video, or audio attachment as a direct message. The URL must be public HTTPS; Meta fetches it server-side. The same 24-hour window applies as for text messages.
| Parameter | Type | Required | Notes |
|---|---|---|---|
| recipient_id | string | yes | — |
| media_url | string | yes | Public HTTPS URL of the file to send |
| media_type | string | no | Attachment type Meta should treat the URL as |
| account_id | string | no | Sending account ID; omit for the token's own |
Mark the conversation with a user as read, which clears its unread badge. Use it after processing an inbox so the same messages are not reprocessed as new.
| Parameter | Type | Required | Notes |
|---|---|---|---|
| recipient_id | string | yes | — |
| account_id | string | no | Account ID; omit for the token's own |
- Every tool, no call limit
- No card, and mcprush charges nothing for it
- Source published under MIT
- Runs on your machine — nothing of it reaches our gateway
- Nothing to cap, because mcprush bills nothing
What counts against your monthly calls
| Tool | Unit | Calls used | Out of the allowance |
|---|
Nothing here is billable: mcprush charges nothing to install Instagram or to call it, at any volume.
Two independent axes, because powerful and malicious are different questions. The grade is threat only. The capability level is blast radius, and it is never a penalty on the grade — it is priced as one subtract-only term in the score, where you can see it.
| Term | Level | What it prices | Points |
|---|---|---|---|
| capability-exposure | high | capability blast radius (high) — client exposure if the model is manipulated | −6 |
| verification-discount | repo | publisher verification (public source) — no provenance, but the source is public and inspectable | −1 |
| coverage-honesty | source | inspection depth (source) — how much of the target the scan could see | −0 |
What the scan could actually read
A grade is only as meaningful as its coverage, so the scanner publishes its own depth before it publishes its result.
Tools were statically extracted from the published source (42 recovered), not enumerated from a running server. Tool-poisoning, Unicode-smuggling, capability and toxic-flow analysis ran on this inferred surface, but a mis-parsed registration could be missed or mis-attributed, so tool-derived findings are capped below “confirmed”. To grade the real runtime surface, scan the running server: --command "npx -y <package>".
1 of the 42 recovered tools are registered only when graph.supportsDiscovery holds (dist/tools/account.js:223) — typically when a key or option is configured. They are part of the server's surface and were analysed; a server started without that configuration exposes only the other 37.
3 of the 42 recovered tools are registered only when !graph.supportsDiscovery is false (dist/tools/discovery.js:99) — typically when a key or option is configured. They are part of the server's surface and were analysed; a server started without that configuration exposes only the other 37.
1 of the 42 recovered tools are registered only when graph.supportsDiscovery holds (dist/tools/media.js:171) — typically when a key or option is configured. They are part of the server's surface and were analysed; a server started without that configuration exposes only the other 37.
Capability — what it could do if the model were manipulated
Tags derived from each tool’s schema and the implementation, not from what the tool calls itself. high is the level these add up to.
37 tools are registered unconditionally · (1) 1 more only when graph.supportsDiscovery holds (dist/tools/account.js:223) · (2) 3 more only when !graph.supportsDiscovery is false (dist/tools/discovery.js:99) · (3) 1 more only when graph.supportsDiscovery holds (dist/tools/media.js:171) — typically when a key or option is configured. All 42 are in the table below and were analysed; the conditional ones are marked.
| Tool | Capability tags | Why the tag was assigned |
|---|---|---|
| instagram_get_account | untrusted-input | untrusted-input: declares openWorldHint: true (interacts with entities outside the server) |
| instagram_get_publishing_limit | untrusted-input | untrusted-input: declares openWorldHint: true (interacts with entities outside the server) |
| instagram_get_token_info | sensitive-sourceuntrusted-input | sensitive-source: keyword "get_token"; untrusted-input: declares openWorldHint: true (interacts with entities outside the server) |
| instagram_refresh_token | external-sink | external-sink: declares readOnlyHint: false, openWorldHint: true |
| instagram_list_pages conditional (1) | untrusted-input | untrusted-input: declares openWorldHint: true (interacts with entities outside the server) |
| instagram_list_comments | untrusted-input | untrusted-input: declares openWorldHint: true (interacts with entities outside the server) |
| instagram_get_comment | untrusted-input | untrusted-input: declares openWorldHint: true (interacts with entities outside the server) |
| instagram_list_comment_replies | untrusted-input | untrusted-input: declares openWorldHint: true (interacts with entities outside the server) |
| instagram_create_comment | external-sink | external-sink: keyword "create_comment", declares readOnlyHint: false, openWorldHint: true, handler sends an HTTP POST (graph.request({ path: ${media_id}/comments, method: "POST", body: { message }, signal: c…) at dist/tools/comments.js:112 |
| instagram_reply_to_comment | external-sink | external-sink: declares readOnlyHint: false, openWorldHint: true, handler sends an HTTP POST (graph.request({ path: ${comment_id}/replies, method: "POST", body: { message }, signal: …) at dist/tools/comments.js:132 |
| instagram_hide_comment | external-sink | external-sink: declares readOnlyHint: false, openWorldHint: true, handler sends an HTTP POST (graph.request({ path: comment_id, method: "POST", body: { hide }, signal: ctx.mcpReq.signa…) at dist/tools/comments.js:152 |
| instagram_delete_comment | external-sink | external-sink: declares readOnlyHint: false, destructiveHint: true, openWorldHint: true, handler sends an HTTP DELETE (graph.request({ path: comment_id, method: "DELETE", signal: ctx.mcpReq.signal, hint: `dele…) at dist/tools/comments.js:171 |
| instagram_toggle_media_comments | external-sink | external-sink: declares readOnlyHint: false, openWorldHint: true, handler sends an HTTP POST (graph.request({ path: media_id, method: "POST", body: { comment_enabled: enabled }, signal…) at dist/tools/comments.js:190 |
| instagram_get_mentioned_comment | external-sinkuntrusted-input | external-sink: keyword "webhook"; untrusted-input: declares openWorldHint: true (interacts with entities outside the server) |
| instagram_get_mentioned_media | external-sinkuntrusted-input | external-sink: keyword "webhook"; untrusted-input: declares openWorldHint: true (interacts with entities outside the server) |
| instagram_reply_to_mention | external-sink | external-sink: declares readOnlyHint: false, openWorldHint: true, handler sends an HTTP POST (graph.request({ path: ${ref}/mentions, method: "POST", body: { media_id, message, commen…) at dist/tools/discovery.js:90 |
| instagram_search_hashtag conditional (2) | untrusted-input | untrusted-input: declares openWorldHint: true (interacts with entities outside the server) |
| instagram_get_hashtag_media conditional (2) | untrusted-input | untrusted-input: declares openWorldHint: true (interacts with entities outside the server) |
| instagram_business_discovery conditional (2) | untrusted-input | untrusted-input: declares openWorldHint: true (interacts with entities outside the server) |
| instagram_list_metric_catalog | no tags | |
| instagram_get_account_insights | untrusted-input | untrusted-input: declares openWorldHint: true (interacts with entities outside the server) |
| instagram_get_media_insights | untrusted-input | untrusted-input: declares openWorldHint: true (interacts with entities outside the server) |
| instagram_get_audience_demographics | untrusted-input | untrusted-input: declares openWorldHint: true (interacts with entities outside the server) |
| instagram_get_story_insights | untrusted-input | untrusted-input: declares openWorldHint: true (interacts with entities outside the server) |
| instagram_list_media | untrusted-input | untrusted-input: declares openWorldHint: true (interacts with entities outside the server) |
| instagram_get_media | untrusted-input | untrusted-input: declares openWorldHint: true (interacts with entities outside the server) |
| instagram_get_media_children | untrusted-input | untrusted-input: declares openWorldHint: true (interacts with entities outside the server) |
| instagram_list_stories | untrusted-input | untrusted-input: declares openWorldHint: true (interacts with entities outside the server) |
| instagram_list_tagged_media | untrusted-input | untrusted-input: declares openWorldHint: true (interacts with entities outside the server) |
| instagram_delete_media conditional (3) | external-sink | external-sink: declares readOnlyHint: false, destructiveHint: true, openWorldHint: true, handler sends an HTTP DELETE (graph.request({ path: media_id, method: "DELETE", signal: ctx.mcpReq.signal, hint: `deleti…) at dist/tools/media.js:189 |
| instagram_list_conversations | untrusted-input | untrusted-input: declares openWorldHint: true (interacts with entities outside the server) |
| instagram_get_conversation | untrusted-input | untrusted-input: declares openWorldHint: true (interacts with entities outside the server) |
| instagram_send_message | external-sink | external-sink: keyword "send_message", declares readOnlyHint: false, openWorldHint: true, handler sends an HTTP POST (graph.request({ path: ${ref}/messages, method: "POST", body: { recipient: JSON.stringify…) at dist/tools/messaging.js:128 |
| instagram_send_media_message | external-sink | external-sink: declares readOnlyHint: false, openWorldHint: true, handler sends an HTTP POST (graph.request({ path: ${ref}/messages, method: "POST", body: { recipient: JSON.stringify…) at dist/tools/messaging.js:158 |
| instagram_mark_seen | external-sink | external-sink: declares readOnlyHint: false, openWorldHint: true, handler sends an HTTP POST (graph.request({ path: ${ref}/messages, method: "POST", body: { recipient: JSON.stringify…) at dist/tools/messaging.js:182 |
| instagram_publish_image | external-sink | external-sink: declares readOnlyHint: false, openWorldHint: true, handler sends an HTTP POST (graph.request({ path: ${accountRef}/media, method: "POST", body, signal, hint: creating…) at dist/tools/publishing.js:41, handler sends an HTTP POST (graph.request({ path: ${accountRef}/media_publish`, method: "POST", body: { creation_id: …) at dist/tools/publishing.js:83 |
| instagram_publish_reel | external-sink | external-sink: declares readOnlyHint: false, openWorldHint: true, handler sends an HTTP POST (graph.request({ path: ${accountRef}/media, method: "POST", body, signal, hint: creating…) at dist/tools/publishing.js:41, handler sends an HTTP POST (graph.request({ path: ${accountRef}/media_publish`, method: "POST", body: { creation_id: …) at dist/tools/publishing.js:83 |
| instagram_publish_story | external-sink | external-sink: declares readOnlyHint: false, openWorldHint: true, handler sends an HTTP POST (graph.request({ path: ${accountRef}/media, method: "POST", body, signal, hint: creating…) at dist/tools/publishing.js:41, handler sends an HTTP POST (graph.request({ path: ${accountRef}/media_publish`, method: "POST", body: { creation_id: …) at dist/tools/publishing.js:83 |
| instagram_publish_carousel | external-sink | external-sink: declares readOnlyHint: false, openWorldHint: true, handler sends an HTTP POST (graph.request({ path: ${accountRef}/media, method: "POST", body, signal, hint: creating…) at dist/tools/publishing.js:41, handler sends an HTTP POST (graph.request({ path: ${accountRef}/media_publish`, method: "POST", body: { creation_id: …) at dist/tools/publishing.js:83 |
| instagram_create_container | external-sink | external-sink: declares readOnlyHint: false, openWorldHint: true, handler sends an HTTP POST (graph.request({ path: ${accountRef}/media, method: "POST", body, signal, hint: `creating…) at dist/tools/publishing.js:41 |
| instagram_get_container_status | untrusted-input | untrusted-input: declares openWorldHint: true (interacts with entities outside the server) |
| instagram_publish_container | external-sink | external-sink: declares readOnlyHint: false, openWorldHint: true, handler sends an HTTP POST (graph.request({ path: ${accountRef}/media_publish, method: "POST", body: { creation_id: …) at dist/tools/publishing.js:83 |
Toxic-flow graph
The lethal trifecta, checked as a graph rather than as a checklist: untrusted input, a sensitive source and an external sink have to meet before there is a path worth worrying about.
Supply chain and provenance
This is the first scan of this surface here, so there is nothing yet to compare it against.
Every result on this tab comes from one deterministic pass over the published package — offline, rule by rule, and auditable line by line above. Same methodology version, same bytes, same score.
Release history
Always latest — the install command names no version, so it installs the newest release when it runs; the current release on file is 1.0.0. Pin a release below and the command asks for exactly that one.
No release note was published with this version.
One review per account, from a signed-in account that does not publish this listing. Nothing else is asked — you can say what you think before you install it. Publishers can reply once per review, and a review can be edited or deleted by whoever wrote it.
Any signed-in account that does not publish Instagram can review it, once — before installing it or after. A review from an account that has installed it is marked as one.
Nobody has reviewed this listing. The rating on the card is the mean of the reviews written here and nothing else, so there is no rating until somebody writes the first — which takes a signed-in account that does not publish it, and nothing else.