ScaleDM

ScaleDM for AI agents

Instagram automation.
Connected to your AI.

A complete MCP reference for assistants and the people building with them. Connect, discover tools, and manage Instagram automations through conversation.

For ChatGPT, Muse, Claude, and other hosts that support remote MCP with OAuth. Connector availability depends on your host and account.

01 / Connection

One endpoint. Your assistant.

Add ScaleDM in your host’s remote connector settings, choose OAuth, and complete the Instagram authorization flow. A Business or Creator Instagram account is required.

MCP server URLhttps://scaledm.io/mcp
Transport
Streamable HTTP · stateless · JSON responses
Authentication
OAuth authorization code + PKCE (S256)
Manage automations
instagram:read instagram:write
Discovery
initialize → notifications/initialized → tools/list

Use a native connector flow when the host provides one. Otherwise, guide the user to its connector settings. A link to /mcp is not an installed connector; browser navigation returns a connection explanation with HTTP 401. Human setup guide ↗

Copy a setup prompt

02 / Authentication

Discover. Authorize. Connect.

Use the published metadata for endpoint discovery. Public clients use dynamic client registration and no client secret.

Endpoint Purpose
/.well-known/oauth-protected-resource/mcp Resource, issuer and supported scopes
/.well-known/oauth-authorization-server OAuth server metadata
POST /oauth/register Register client name and redirect URIs
GET /oauth/authorize Authorization code flow; PKCE S256
POST /oauth/token Exchange a single-use code with its verifier
  • Use response_type=code, code_challenge_method=S256 and resource https://scaledm.io/mcp. Preserve and validate OAuth state.
  • Registered callbacks must use HTTPS; HTTP localhost callbacks are permitted for desktop clients. Client ID metadata documents are not supported.
  • Send tokens only as Authorization: Bearer <access_token>. Never put tokens in URLs or ask users to paste passwords or tokens into chat.
  • Access tokens expire after 60 days. Refresh tokens are not issued; run authorization again when required.
  • instagram:read permits read tools. Write tools additionally require instagram:write. Request both for Manage automations.

03 / Agent workflow

From intent to an approved automation.

  1. Call get_instagram_account to identify the authorized account. Use list_automations to inspect existing rules.
  2. Use list_instagram_media and get_instagram_media to select real content. Never invent account, media or automation IDs.
  3. Resolve the type, content scope, keywords, message and links. Save with status: "draft" while refining; creation otherwise defaults to live.
  4. Show the exact content, trigger and message. Ask for approval before activating, starting test mode or deleting; only then pass confirmed: true.
  5. Read the returned automation and report its actual status. After an uncertain write, list automations before retrying to avoid duplicates.

Drafts send nothing. Live and test automations can send messages. Editing an already running automation changes its behavior—review the proposed changes with the user.

04 / Tool reference

Eight focused tools.

These are the tools exposed by the public connector. Full argument and response schemas are included below and in the JSON reference. The connected server’s tools/list is authoritative.

get_instagram_account

Read

Identify the connected Instagram account for automation setup. Returns structuredContent and an inline image widget.

No arguments. Pass {}.

Full input and output schemas
{
  "inputSchema": {
    "type": "object",
    "properties": {},
    "required": [],
    "additionalProperties": false
  },
  "outputSchema": {
    "type": "object",
    "properties": {
      "account_id": {
        "type": "string"
      },
      "username": {
        "type": "string"
      },
      "name": {
        "type": [
          "string",
          "null"
        ]
      },
      "account_type": {
        "type": [
          "string",
          "null"
        ]
      },
      "biography": {
        "type": [
          "string",
          "null"
        ]
      },
      "website": {
        "type": [
          "string",
          "null"
        ]
      },
      "has_profile_pic": {
        "type": "boolean"
      },
      "followers_count": {
        "type": [
          "integer",
          "null"
        ]
      },
      "follows_count": {
        "type": [
          "integer",
          "null"
        ]
      },
      "media_count": {
        "type": [
          "integer",
          "null"
        ]
      },
      "preview_url": {
        "type": [
          "string",
          "null"
        ],
        "description": "Profile photo for the image widget."
      }
    },
    "required": [
      "account_id",
      "username"
    ],
    "additionalProperties": false
  }
}

list_instagram_media

Read

Posts and Reels (kind=feed, paginate with after) or active stories (kind=stories). JSON only.

Argument Details
kind feed = posts and Reels (paginated); stories = active 24-hour stories (not paginated).
limit Items per page (feed only).
after pagination.next_cursor from the previous page (feed only).
Full input and output schemas
{
  "inputSchema": {
    "type": "object",
    "properties": {
      "kind": {
        "type": "string",
        "enum": [
          "feed",
          "stories"
        ],
        "description": "feed = posts and Reels (paginated); stories = active 24-hour stories (not paginated).",
        "default": "feed"
      },
      "limit": {
        "type": "integer",
        "minimum": 1,
        "maximum": 50,
        "description": "Items per page (feed only)."
      },
      "after": {
        "type": "string",
        "description": "pagination.next_cursor from the previous page (feed only)."
      }
    },
    "required": [],
    "additionalProperties": false
  },
  "outputSchema": {
    "type": "object",
    "properties": {
      "username": {
        "type": "string"
      },
      "kind": {
        "type": "string",
        "enum": [
          "feed",
          "stories"
        ],
        "description": "feed = posts and Reels (paginated); stories = active 24-hour stories (not paginated)."
      },
      "view": {
        "type": "string",
        "enum": [
          "feed",
          "post",
          "stories"
        ]
      },
      "count": {
        "type": "integer"
      },
      "pagination": {
        "type": "object",
        "properties": {
          "limit": {
            "type": "integer"
          },
          "has_more": {
            "type": "boolean"
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "limit",
          "has_more",
          "next_cursor"
        ],
        "additionalProperties": false
      },
      "media": {
        "type": "array",
        "items": {
          "type": "object",
          "properties": {
            "id": {
              "type": "string"
            },
            "caption": {
              "type": [
                "string",
                "null"
              ]
            },
            "media_type": {
              "type": [
                "string",
                "null"
              ]
            },
            "media_product_type": {
              "type": [
                "string",
                "null"
              ]
            },
            "permalink": {
              "type": [
                "string",
                "null"
              ]
            },
            "timestamp": {
              "type": [
                "string",
                "null"
              ]
            },
            "like_count": {
              "type": [
                "integer",
                "null"
              ]
            },
            "comments_count": {
              "type": [
                "integer",
                "null"
              ]
            },
            "preview_url": {
              "type": [
                "string",
                "null"
              ],
              "description": "Signed Instagram CDN thumbnail for the image widget."
            },
            "children": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "caption": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "media_type": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "media_product_type": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "permalink": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "timestamp": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "like_count": {
                    "type": [
                      "integer",
                      "null"
                    ]
                  },
                  "comments_count": {
                    "type": [
                      "integer",
                      "null"
                    ]
                  },
                  "preview_url": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Signed Instagram CDN thumbnail for the image widget."
                  }
                },
                "required": [
                  "id"
                ],
                "additionalProperties": true
              }
            }
          },
          "required": [
            "id"
          ],
          "additionalProperties": true
        }
      }
    },
    "required": [
      "username",
      "kind",
      "view",
      "count",
      "pagination",
      "media"
    ],
    "additionalProperties": false
  }
}

get_instagram_media

Read

One post by media_id (carousel children included). Returns structuredContent and an inline image widget.

Argument Details
media_id required From list_instagram_media.
Full input and output schemas
{
  "inputSchema": {
    "type": "object",
    "properties": {
      "media_id": {
        "type": "string",
        "description": "From list_instagram_media."
      }
    },
    "required": [
      "media_id"
    ],
    "additionalProperties": false
  },
  "outputSchema": {
    "type": "object",
    "properties": {
      "username": {
        "type": "string"
      },
      "view": {
        "type": "string"
      },
      "count": {
        "type": "integer"
      },
      "media": {
        "type": "array",
        "items": {
          "type": "object",
          "properties": {
            "id": {
              "type": "string"
            },
            "caption": {
              "type": [
                "string",
                "null"
              ]
            },
            "media_type": {
              "type": [
                "string",
                "null"
              ]
            },
            "media_product_type": {
              "type": [
                "string",
                "null"
              ]
            },
            "permalink": {
              "type": [
                "string",
                "null"
              ]
            },
            "timestamp": {
              "type": [
                "string",
                "null"
              ]
            },
            "like_count": {
              "type": [
                "integer",
                "null"
              ]
            },
            "comments_count": {
              "type": [
                "integer",
                "null"
              ]
            },
            "preview_url": {
              "type": [
                "string",
                "null"
              ],
              "description": "Signed Instagram CDN thumbnail for the image widget."
            },
            "children": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "caption": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "media_type": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "media_product_type": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "permalink": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "timestamp": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "like_count": {
                    "type": [
                      "integer",
                      "null"
                    ]
                  },
                  "comments_count": {
                    "type": [
                      "integer",
                      "null"
                    ]
                  },
                  "preview_url": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Signed Instagram CDN thumbnail for the image widget."
                  }
                },
                "required": [
                  "id"
                ],
                "additionalProperties": true
              }
            }
          },
          "required": [
            "id"
          ],
          "additionalProperties": true
        }
      }
    },
    "required": [
      "username",
      "view",
      "count",
      "media"
    ],
    "additionalProperties": false
  }
}

create_automation

Write

Sensitive write. Creates a rule that DMs each person who comments on the chosen posts or Reels (or replies to stories), with an optional opening DM, follow gate, and public reply. It only messages people who comment or reply; never anyone else. status=live (default) or test needs confirmed=true after the user approves; status=draft saves without sending. Rejects overlap with a running automation.

Argument Details
type post = comments on posts and Reels. story = replies to stories (and optionally mentions). message = a direct message containing a keyword (trigger_keywords required, media_ids ["*"]). share = someone sends one of the picked posts or Reels in a direct message (media_ids required).
name required Display name (up to 60 characters).
media_ids required Post/Reel or story IDs from list_instagram_media. ["*"] = every post (not stories; pick story IDs). ["next"] = the next post published after it goes live (posts only).
include_mentions Story automations on every story: also DM people who mention the account.
trigger_keywords Whole-word, case-insensitive keywords (emoji work too). Required when match_mode=keywords.
match_mode keywords = only matching comments; all = every comment or story reply.
comment_reply Public reply under the comment (posts and Reels only). Needs at least 3 different replies; ScaleDM rotates them and @mentions the commenter so replies never look copy-pasted.
opening_dm Optional first DM with one button (posts and Reels only). The link DM is sent when the person taps the button. Taps open the conversation, which helps DMs reach the inbox. Required for ask_to_follow on posts.
ask_to_follow Optional follow gate. People who don't follow the account get this message with an 'Open profile' button and a confirm button; followers get the link straight away. ScaleDM checks the follow and asks up to 3 times.
dm required The link DM (required). type=text: message (or up to 3 messages, picked at random). type=image: a card with title and image (dm_image upload or image_url), plus an optional message sent before it.
dm_image Image uploaded in chat (when supported). Otherwise pass a public https image_url.
image_url Public https image for an image DM when no file is uploaded.
test_usernames Instagram usernames that test mode answers (not the connected account).
status draft = saved, not answering. test = only answers comments from test_usernames (instant, for trying it out). live = answers everyone who matches. paused = stopped, ready to resume.
is_active Legacy shortcut: true = live, false = paused.
confirmed Must be true to go live, start testing, or delete; set only after the user approved.
Full input and output schemas
{
  "inputSchema": {
    "type": "object",
    "description": "Create an Instagram comment-to-DM (or story-reply-to-DM) automation. Defaults to status=live, which needs confirmed=true; pass status=draft to save without sending anything.",
    "properties": {
      "type": {
        "type": "string",
        "enum": [
          "post",
          "story",
          "message",
          "share"
        ],
        "description": "post = comments on posts and Reels. story = replies to stories (and optionally mentions). message = a direct message containing a keyword (trigger_keywords required, media_ids [\"*\"]). share = someone sends one of the picked posts or Reels in a direct message (media_ids required)."
      },
      "name": {
        "type": "string",
        "description": "Display name (up to 60 characters)."
      },
      "media_ids": {
        "type": "array",
        "items": {
          "type": "string"
        },
        "description": "Post/Reel or story IDs from list_instagram_media. [\"*\"] = every post (not stories; pick story IDs). [\"next\"] = the next post published after it goes live (posts only)."
      },
      "include_mentions": {
        "type": "boolean",
        "description": "Story automations on every story: also DM people who mention the account."
      },
      "trigger_keywords": {
        "type": "array",
        "items": {
          "type": "string"
        },
        "maxItems": 20,
        "description": "Whole-word, case-insensitive keywords (emoji work too). Required when match_mode=keywords."
      },
      "match_mode": {
        "type": "string",
        "enum": [
          "keywords",
          "all"
        ],
        "description": "keywords = only matching comments; all = every comment or story reply."
      },
      "comment_reply": {
        "type": "object",
        "description": "Public reply under the comment (posts and Reels only). Needs at least 3 different replies; ScaleDM rotates them and @mentions the commenter so replies never look copy-pasted.",
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "replies": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "minItems": 3,
            "maxItems": 10
          }
        },
        "required": [
          "enabled"
        ],
        "additionalProperties": false
      },
      "opening_dm": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "text": {
            "type": "string",
            "description": "Message text (up to 1000 characters)."
          },
          "button_title": {
            "type": "string",
            "description": "Button label, up to 20 characters."
          }
        },
        "additionalProperties": false,
        "description": "Optional first DM with one button (posts and Reels only). The link DM is sent when the person taps the button. Taps open the conversation, which helps DMs reach the inbox. Required for ask_to_follow on posts."
      },
      "ask_to_follow": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "text": {
            "type": "string",
            "description": "Message text (up to 1000 characters)."
          },
          "button_title": {
            "type": "string",
            "description": "Button label, up to 20 characters."
          }
        },
        "additionalProperties": false,
        "description": "Optional follow gate. People who don't follow the account get this message with an 'Open profile' button and a confirm button; followers get the link straight away. ScaleDM checks the follow and asks up to 3 times."
      },
      "dm": {
        "type": "object",
        "description": "The link DM (required). type=text: message (or up to 3 messages, picked at random). type=image: a card with title and image (dm_image upload or image_url), plus an optional message sent before it.",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "text",
              "image"
            ]
          },
          "message": {
            "type": "string",
            "description": "DM text (up to 1000 characters)."
          },
          "messages": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "maxItems": 3,
            "description": "Up to 3 variations; one is picked at random per person."
          },
          "image_url": {
            "type": "string",
            "description": "Hosted image URL for type=image. Set by the server."
          },
          "title": {
            "type": "string",
            "description": "Card headline, required when type=image."
          },
          "subtitle": {
            "type": "string"
          },
          "buttons": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "title": {
                  "type": "string",
                  "description": "Short label, up to 20 characters (e.g. Get the guide)."
                },
                "url": {
                  "type": "string",
                  "description": "Destination https:// URL. ScaleDM wraps it in a tracked link."
                }
              },
              "required": [
                "title",
                "url"
              ],
              "additionalProperties": false
            },
            "maxItems": 3,
            "description": "Up to 3 link buttons. Clicks are tracked; links typed in the message are not."
          }
        },
        "required": [
          "type"
        ],
        "additionalProperties": false
      },
      "dm_image": {
        "type": "object",
        "description": "Image uploaded in chat (when supported). Otherwise pass a public https image_url.",
        "properties": {
          "download_url": {
            "type": "string"
          },
          "file_id": {
            "type": "string"
          },
          "mime_type": {
            "type": "string"
          },
          "file_name": {
            "type": "string"
          }
        },
        "required": [
          "download_url",
          "file_id"
        ],
        "additionalProperties": false
      },
      "image_url": {
        "type": "string",
        "description": "Public https image for an image DM when no file is uploaded."
      },
      "test_usernames": {
        "type": "array",
        "items": {
          "type": "string"
        },
        "maxItems": 5,
        "description": "Instagram usernames that test mode answers (not the connected account)."
      },
      "status": {
        "type": "string",
        "enum": [
          "draft",
          "test",
          "live",
          "paused"
        ],
        "description": "draft = saved, not answering. test = only answers comments from test_usernames (instant, for trying it out). live = answers everyone who matches. paused = stopped, ready to resume."
      },
      "is_active": {
        "type": "boolean",
        "description": "Legacy shortcut: true = live, false = paused."
      },
      "confirmed": {
        "type": "boolean",
        "description": "Must be true to go live, start testing, or delete; set only after the user approved."
      }
    },
    "required": [
      "name",
      "media_ids",
      "dm"
    ],
    "additionalProperties": false
  },
  "outputSchema": {
    "type": "object",
    "properties": {
      "automation": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "post",
              "story",
              "message",
              "share"
            ],
            "description": "post = comments on posts and Reels. story = replies to stories (and optionally mentions). message = a direct message containing a keyword (trigger_keywords required, media_ids [\"*\"]). share = someone sends one of the picked posts or Reels in a direct message (media_ids required)."
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "test",
              "live",
              "paused"
            ],
            "description": "draft = saved, not answering. test = only answers comments from test_usernames (instant, for trying it out). live = answers everyone who matches. paused = stopped, ready to resume."
          },
          "is_active": {
            "type": "boolean"
          },
          "scope": {
            "type": "string",
            "enum": [
              "specific",
              "any",
              "next"
            ]
          },
          "media_ids": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "include_mentions": {
            "type": "boolean"
          },
          "match_mode": {
            "type": "string"
          },
          "trigger_keywords": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "comment_reply": {
            "type": "object"
          },
          "opening_dm": {
            "type": "object",
            "properties": {
              "enabled": {
                "type": "boolean"
              },
              "text": {
                "type": "string"
              },
              "button_title": {
                "type": "string"
              }
            }
          },
          "ask_to_follow": {
            "type": "object",
            "properties": {
              "enabled": {
                "type": "boolean"
              },
              "text": {
                "type": "string"
              },
              "button_title": {
                "type": "string"
              }
            }
          },
          "dm": {
            "type": "object"
          },
          "test_usernames": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "stats": {
            "type": "object"
          },
          "sent_count": {
            "type": "integer"
          },
          "comment_count": {
            "type": "integer"
          },
          "total_clicks": {
            "type": "integer"
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ]
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "name",
          "type",
          "status",
          "media_ids",
          "trigger_keywords",
          "is_active"
        ],
        "additionalProperties": true
      }
    },
    "required": [
      "automation"
    ],
    "additionalProperties": false
  }
}

update_automation

Write

Sensitive write. Changes one automation; only the fields passed change. Changing posts, keywords, DMs, or replies changes who gets messaged and what they get. status=live or test resumes sending and needs confirmed=true; status=paused stops it. reset_counters=true clears its stats.

Argument Details
automation_id required Type: string
type post = comments on posts and Reels. story = replies to stories (and optionally mentions). message = a direct message containing a keyword (trigger_keywords required, media_ids ["*"]). share = someone sends one of the picked posts or Reels in a direct message (media_ids required).
name Display name (up to 60 characters).
media_ids Post/Reel or story IDs from list_instagram_media. ["*"] = every post (not stories; pick story IDs). ["next"] = the next post published after it goes live (posts only).
include_mentions Story automations on every story: also DM people who mention the account.
trigger_keywords Whole-word, case-insensitive keywords (emoji work too). Required when match_mode=keywords.
match_mode keywords = only matching comments; all = every comment or story reply.
comment_reply Public reply under the comment (posts and Reels only). Needs at least 3 different replies; ScaleDM rotates them and @mentions the commenter so replies never look copy-pasted.
opening_dm Optional first DM with one button (posts and Reels only). The link DM is sent when the person taps the button. Taps open the conversation, which helps DMs reach the inbox. Required for ask_to_follow on posts.
ask_to_follow Optional follow gate. People who don't follow the account get this message with an 'Open profile' button and a confirm button; followers get the link straight away. ScaleDM checks the follow and asks up to 3 times.
dm The link DM (required). type=text: message (or up to 3 messages, picked at random). type=image: a card with title and image (dm_image upload or image_url), plus an optional message sent before it.
dm_image Image uploaded in chat (when supported). Otherwise pass a public https image_url.
image_url Public https image for an image DM when no file is uploaded.
test_usernames Instagram usernames that test mode answers (not the connected account).
status draft = saved, not answering. test = only answers comments from test_usernames (instant, for trying it out). live = answers everyone who matches. paused = stopped, ready to resume.
is_active Legacy shortcut: true = live, false = paused.
confirmed Must be true to go live, start testing, or delete; set only after the user approved.
add_media_ids Type: array
remove_media_ids Type: array
add_trigger_keywords Type: array
remove_trigger_keywords Type: array
reset_counters Permanently clear this automation's stats.
Full input and output schemas
{
  "inputSchema": {
    "type": "object",
    "description": "Change one automation; only the fields passed change.",
    "properties": {
      "automation_id": {
        "type": "string"
      },
      "type": {
        "type": "string",
        "enum": [
          "post",
          "story",
          "message",
          "share"
        ],
        "description": "post = comments on posts and Reels. story = replies to stories (and optionally mentions). message = a direct message containing a keyword (trigger_keywords required, media_ids [\"*\"]). share = someone sends one of the picked posts or Reels in a direct message (media_ids required)."
      },
      "name": {
        "type": "string",
        "description": "Display name (up to 60 characters)."
      },
      "media_ids": {
        "type": "array",
        "items": {
          "type": "string"
        },
        "description": "Post/Reel or story IDs from list_instagram_media. [\"*\"] = every post (not stories; pick story IDs). [\"next\"] = the next post published after it goes live (posts only)."
      },
      "include_mentions": {
        "type": "boolean",
        "description": "Story automations on every story: also DM people who mention the account."
      },
      "trigger_keywords": {
        "type": "array",
        "items": {
          "type": "string"
        },
        "maxItems": 20,
        "description": "Whole-word, case-insensitive keywords (emoji work too). Required when match_mode=keywords."
      },
      "match_mode": {
        "type": "string",
        "enum": [
          "keywords",
          "all"
        ],
        "description": "keywords = only matching comments; all = every comment or story reply."
      },
      "comment_reply": {
        "type": "object",
        "description": "Public reply under the comment (posts and Reels only). Needs at least 3 different replies; ScaleDM rotates them and @mentions the commenter so replies never look copy-pasted.",
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "replies": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "minItems": 3,
            "maxItems": 10
          }
        },
        "required": [
          "enabled"
        ],
        "additionalProperties": false
      },
      "opening_dm": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "text": {
            "type": "string",
            "description": "Message text (up to 1000 characters)."
          },
          "button_title": {
            "type": "string",
            "description": "Button label, up to 20 characters."
          }
        },
        "additionalProperties": false,
        "description": "Optional first DM with one button (posts and Reels only). The link DM is sent when the person taps the button. Taps open the conversation, which helps DMs reach the inbox. Required for ask_to_follow on posts."
      },
      "ask_to_follow": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "text": {
            "type": "string",
            "description": "Message text (up to 1000 characters)."
          },
          "button_title": {
            "type": "string",
            "description": "Button label, up to 20 characters."
          }
        },
        "additionalProperties": false,
        "description": "Optional follow gate. People who don't follow the account get this message with an 'Open profile' button and a confirm button; followers get the link straight away. ScaleDM checks the follow and asks up to 3 times."
      },
      "dm": {
        "type": "object",
        "description": "The link DM (required). type=text: message (or up to 3 messages, picked at random). type=image: a card with title and image (dm_image upload or image_url), plus an optional message sent before it.",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "text",
              "image"
            ]
          },
          "message": {
            "type": "string",
            "description": "DM text (up to 1000 characters)."
          },
          "messages": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "maxItems": 3,
            "description": "Up to 3 variations; one is picked at random per person."
          },
          "image_url": {
            "type": "string",
            "description": "Hosted image URL for type=image. Set by the server."
          },
          "title": {
            "type": "string",
            "description": "Card headline, required when type=image."
          },
          "subtitle": {
            "type": "string"
          },
          "buttons": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "title": {
                  "type": "string",
                  "description": "Short label, up to 20 characters (e.g. Get the guide)."
                },
                "url": {
                  "type": "string",
                  "description": "Destination https:// URL. ScaleDM wraps it in a tracked link."
                }
              },
              "required": [
                "title",
                "url"
              ],
              "additionalProperties": false
            },
            "maxItems": 3,
            "description": "Up to 3 link buttons. Clicks are tracked; links typed in the message are not."
          }
        },
        "required": [
          "type"
        ],
        "additionalProperties": false
      },
      "dm_image": {
        "type": "object",
        "description": "Image uploaded in chat (when supported). Otherwise pass a public https image_url.",
        "properties": {
          "download_url": {
            "type": "string"
          },
          "file_id": {
            "type": "string"
          },
          "mime_type": {
            "type": "string"
          },
          "file_name": {
            "type": "string"
          }
        },
        "required": [
          "download_url",
          "file_id"
        ],
        "additionalProperties": false
      },
      "image_url": {
        "type": "string",
        "description": "Public https image for an image DM when no file is uploaded."
      },
      "test_usernames": {
        "type": "array",
        "items": {
          "type": "string"
        },
        "maxItems": 5,
        "description": "Instagram usernames that test mode answers (not the connected account)."
      },
      "status": {
        "type": "string",
        "enum": [
          "draft",
          "test",
          "live",
          "paused"
        ],
        "description": "draft = saved, not answering. test = only answers comments from test_usernames (instant, for trying it out). live = answers everyone who matches. paused = stopped, ready to resume."
      },
      "is_active": {
        "type": "boolean",
        "description": "Legacy shortcut: true = live, false = paused."
      },
      "confirmed": {
        "type": "boolean",
        "description": "Must be true to go live, start testing, or delete; set only after the user approved."
      },
      "add_media_ids": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "remove_media_ids": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "add_trigger_keywords": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "remove_trigger_keywords": {
        "type": "array",
        "items": {
          "type": "string"
        }
      },
      "reset_counters": {
        "type": "boolean",
        "description": "Permanently clear this automation's stats."
      }
    },
    "required": [
      "automation_id"
    ],
    "additionalProperties": false
  },
  "outputSchema": {
    "type": "object",
    "properties": {
      "automation": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "post",
              "story",
              "message",
              "share"
            ],
            "description": "post = comments on posts and Reels. story = replies to stories (and optionally mentions). message = a direct message containing a keyword (trigger_keywords required, media_ids [\"*\"]). share = someone sends one of the picked posts or Reels in a direct message (media_ids required)."
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "test",
              "live",
              "paused"
            ],
            "description": "draft = saved, not answering. test = only answers comments from test_usernames (instant, for trying it out). live = answers everyone who matches. paused = stopped, ready to resume."
          },
          "is_active": {
            "type": "boolean"
          },
          "scope": {
            "type": "string",
            "enum": [
              "specific",
              "any",
              "next"
            ]
          },
          "media_ids": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "include_mentions": {
            "type": "boolean"
          },
          "match_mode": {
            "type": "string"
          },
          "trigger_keywords": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "comment_reply": {
            "type": "object"
          },
          "opening_dm": {
            "type": "object",
            "properties": {
              "enabled": {
                "type": "boolean"
              },
              "text": {
                "type": "string"
              },
              "button_title": {
                "type": "string"
              }
            }
          },
          "ask_to_follow": {
            "type": "object",
            "properties": {
              "enabled": {
                "type": "boolean"
              },
              "text": {
                "type": "string"
              },
              "button_title": {
                "type": "string"
              }
            }
          },
          "dm": {
            "type": "object"
          },
          "test_usernames": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "stats": {
            "type": "object"
          },
          "sent_count": {
            "type": "integer"
          },
          "comment_count": {
            "type": "integer"
          },
          "total_clicks": {
            "type": "integer"
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ]
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "name",
          "type",
          "status",
          "media_ids",
          "trigger_keywords",
          "is_active"
        ],
        "additionalProperties": true
      }
    },
    "required": [
      "automation"
    ],
    "additionalProperties": false
  }
}

list_automations

Read

Automations for the linked account, newest first, with stats. Filters: type, status, is_active, media_id, name_contains, trigger_keyword, limit. JSON only.

Argument Details
type post = comments on posts and Reels. story = replies to stories (and optionally mentions). message = a direct message containing a keyword (trigger_keywords required, media_ids ["*"]). share = someone sends one of the picked posts or Reels in a direct message (media_ids required).
status draft = saved, not answering. test = only answers comments from test_usernames (instant, for trying it out). live = answers everyone who matches. paused = stopped, ready to resume.
is_active true = live or test; false = draft or paused.
media_id Type: string
name_contains Type: string
trigger_keyword Type: string
limit Type: integer
Full input and output schemas
{
  "inputSchema": {
    "type": "object",
    "properties": {
      "type": {
        "type": "string",
        "enum": [
          "post",
          "story",
          "message",
          "share"
        ],
        "description": "post = comments on posts and Reels. story = replies to stories (and optionally mentions). message = a direct message containing a keyword (trigger_keywords required, media_ids [\"*\"]). share = someone sends one of the picked posts or Reels in a direct message (media_ids required)."
      },
      "status": {
        "type": "string",
        "enum": [
          "draft",
          "test",
          "live",
          "paused"
        ],
        "description": "draft = saved, not answering. test = only answers comments from test_usernames (instant, for trying it out). live = answers everyone who matches. paused = stopped, ready to resume."
      },
      "is_active": {
        "type": "boolean",
        "description": "true = live or test; false = draft or paused."
      },
      "media_id": {
        "type": "string"
      },
      "name_contains": {
        "type": "string"
      },
      "trigger_keyword": {
        "type": "string"
      },
      "limit": {
        "type": "integer",
        "minimum": 1
      }
    },
    "required": [],
    "additionalProperties": false
  },
  "outputSchema": {
    "type": "object",
    "properties": {
      "count": {
        "type": "integer"
      },
      "automations": {
        "type": "array",
        "items": {
          "type": "object",
          "properties": {
            "id": {
              "type": "string"
            },
            "name": {
              "type": "string"
            },
            "type": {
              "type": "string",
              "enum": [
                "post",
                "story",
                "message",
                "share"
              ],
              "description": "post = comments on posts and Reels. story = replies to stories (and optionally mentions). message = a direct message containing a keyword (trigger_keywords required, media_ids [\"*\"]). share = someone sends one of the picked posts or Reels in a direct message (media_ids required)."
            },
            "status": {
              "type": "string",
              "enum": [
                "draft",
                "test",
                "live",
                "paused"
              ],
              "description": "draft = saved, not answering. test = only answers comments from test_usernames (instant, for trying it out). live = answers everyone who matches. paused = stopped, ready to resume."
            },
            "is_active": {
              "type": "boolean"
            },
            "scope": {
              "type": "string",
              "enum": [
                "specific",
                "any",
                "next"
              ]
            },
            "media_ids": {
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            "include_mentions": {
              "type": "boolean"
            },
            "match_mode": {
              "type": "string"
            },
            "trigger_keywords": {
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            "comment_reply": {
              "type": "object"
            },
            "opening_dm": {
              "type": "object",
              "properties": {
                "enabled": {
                  "type": "boolean"
                },
                "text": {
                  "type": "string"
                },
                "button_title": {
                  "type": "string"
                }
              }
            },
            "ask_to_follow": {
              "type": "object",
              "properties": {
                "enabled": {
                  "type": "boolean"
                },
                "text": {
                  "type": "string"
                },
                "button_title": {
                  "type": "string"
                }
              }
            },
            "dm": {
              "type": "object"
            },
            "test_usernames": {
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            "stats": {
              "type": "object"
            },
            "sent_count": {
              "type": "integer"
            },
            "comment_count": {
              "type": "integer"
            },
            "total_clicks": {
              "type": "integer"
            },
            "created_at": {
              "type": [
                "string",
                "null"
              ]
            },
            "updated_at": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          "required": [
            "id",
            "name",
            "type",
            "status",
            "media_ids",
            "trigger_keywords",
            "is_active"
          ],
          "additionalProperties": true
        }
      }
    },
    "required": [
      "count",
      "automations"
    ],
    "additionalProperties": false
  }
}

get_automation

Read

One automation with stats. Returns structuredContent and an inline image widget. The widget shows image DMs.

Argument Details
automation_id required From list_automations.
Full input and output schemas
{
  "inputSchema": {
    "type": "object",
    "properties": {
      "automation_id": {
        "type": "string",
        "description": "From list_automations."
      }
    },
    "required": [
      "automation_id"
    ],
    "additionalProperties": false
  },
  "outputSchema": {
    "type": "object",
    "properties": {
      "automation": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "post",
              "story",
              "message",
              "share"
            ],
            "description": "post = comments on posts and Reels. story = replies to stories (and optionally mentions). message = a direct message containing a keyword (trigger_keywords required, media_ids [\"*\"]). share = someone sends one of the picked posts or Reels in a direct message (media_ids required)."
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "test",
              "live",
              "paused"
            ],
            "description": "draft = saved, not answering. test = only answers comments from test_usernames (instant, for trying it out). live = answers everyone who matches. paused = stopped, ready to resume."
          },
          "is_active": {
            "type": "boolean"
          },
          "scope": {
            "type": "string",
            "enum": [
              "specific",
              "any",
              "next"
            ]
          },
          "media_ids": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "include_mentions": {
            "type": "boolean"
          },
          "match_mode": {
            "type": "string"
          },
          "trigger_keywords": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "comment_reply": {
            "type": "object"
          },
          "opening_dm": {
            "type": "object",
            "properties": {
              "enabled": {
                "type": "boolean"
              },
              "text": {
                "type": "string"
              },
              "button_title": {
                "type": "string"
              }
            }
          },
          "ask_to_follow": {
            "type": "object",
            "properties": {
              "enabled": {
                "type": "boolean"
              },
              "text": {
                "type": "string"
              },
              "button_title": {
                "type": "string"
              }
            }
          },
          "dm": {
            "type": "object"
          },
          "test_usernames": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "stats": {
            "type": "object"
          },
          "sent_count": {
            "type": "integer"
          },
          "comment_count": {
            "type": "integer"
          },
          "total_clicks": {
            "type": "integer"
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ]
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "name",
          "type",
          "status",
          "media_ids",
          "trigger_keywords",
          "is_active"
        ],
        "additionalProperties": true
      }
    },
    "required": [
      "automation"
    ],
    "additionalProperties": false
  }
}

delete_automation

Write

Sensitive write. Permanently deletes one automation, its stats, and its tracked links, and stops its DMs and replies. Cannot be undone. Needs confirmed=true after the user approves.

Argument Details
automation_id required From list_automations.
confirmed required Must be true to go live, start testing, or delete; set only after the user approved.
Full input and output schemas
{
  "inputSchema": {
    "type": "object",
    "properties": {
      "automation_id": {
        "type": "string",
        "description": "From list_automations."
      },
      "confirmed": {
        "type": "boolean",
        "description": "Must be true to go live, start testing, or delete; set only after the user approved."
      }
    },
    "required": [
      "automation_id",
      "confirmed"
    ],
    "additionalProperties": false
  },
  "outputSchema": {
    "type": "object",
    "properties": {
      "automation_id": {
        "type": "string"
      },
      "deleted": {
        "type": "boolean"
      }
    },
    "required": [
      "automation_id",
      "deleted"
    ],
    "additionalProperties": false
  }
}

05 / Examples

Concrete calls. Predictable results.

Examples below are arguments for tools/call. Replace placeholder IDs with values returned by lookup tools.

Save a comment-to-DM draft

{
  "name": "create_automation",
  "arguments": {
    "type": "post",
    "name": "Guide request",
    "media_ids": ["<media_id>"],
    "match_mode": "keywords",
    "trigger_keywords": ["GUIDE"],
    "dm": {
      "type": "text",
      "message": "Here’s your guide!",
      "buttons": [{"title": "Get the guide", "url": "https://example.com/guide"}]
    },
    "status": "draft"
  }
}

Activate after explicit approval

{
  "name": "update_automation",
  "arguments": {
    "automation_id": "<automation_id>",
    "status": "live",
    "confirmed": true
  }
}

Pause an automation

{
  "name": "update_automation",
  "arguments": {"automation_id": "<automation_id>", "status": "paused"}
}

For a custom MCP client, POST JSON-RPC to the endpoint with Content-Type: application/json, Accept: application/json, text/event-stream, the negotiated MCP-Protocol-Version and bearer authorization. Initialize before discovering or calling tools; no persistent session ID is required.

06 / Error recovery

Recover without repeating a write.

HTTP 401 / invalid_token
Read the WWW-Authenticate resource metadata challenge and reconnect through OAuth.
insufficient_scope
Request both scopes for management. Tool authentication challenges can appear in _meta["mcp/www_authenticate"].
Tool isError
Read the returned message. Fix the named field or missing confirmation before calling again.
Automation conflict
Inspect the overlapping rule. Ask whether to pause it or choose different content or keywords.
Unknown automation
Call list_automations and use a current ID.
Timeout / uncertain write
List automations and inspect their state before retrying creation, updates or deletion.

Successful calls include a text summary and structuredContent. Read structured fields for IDs, status and counters; do not infer delivery from a successful configuration change.

07 / Scope & limits

Know what the connector supports.

  • Automation types: post comments, story replies, keyword DMs and shared posts/Reels. Use the published argument schemas and server validation for each type.
  • States: draft, test, live, paused. Test mode answers up to five configured usernames.
  • Feed media is paginated: pass pagination.next_cursor as after; page size is 1–50. Active stories are not paginated.
  • Keyword matching is whole-word and case-insensitive. Text supports up to three variants; link DMs support up to three buttons. Link-button clicks are tracked; plain-text links are not.
  • There are no ScaleDM usage caps. Instagram messaging rules and rate limits still apply.
  • Standalone insights, comment browsing, feedback and account deletion are not exposed by this public connector. Account/media lookup supports automation setup.
  • Plain structured responses work without widgets. Host support for image previews and uploaded files varies; use a public HTTPS image URL when upload integration is unavailable.

Need help? support@scaledm.io