Tools
Every MCP tool exposed by the IMMA AI MCP server, its arguments, an example call and result, and the rules it enforces.
Preview
Preview: the API and MCP server are in private beta; details may change.
Each tool below mirrors a REST API resource one to one (see MCP reference for the full mapping table), so argument names match the REST request bodies in the API reference. A key's scopes control which tools appear in tools/list; a tool that needs a scope your key does not have is simply not offered to the agent.
list_accounts
When to use it: Call this first in almost any workflow. It lists connected social accounts with platform, username, connection status and remaining daily posting quota, so the agent can find the right account IDs before doing anything else.
Scope: accounts:read
Input
| Field | Type | Required | Description |
|---|---|---|---|
profile_id | string | No | Restrict to one profile's accounts |
platform | string | No | Filter to tiktok, instagram, facebook or threads |
Output
{
"accounts": [
{ "id": "acc_tt_01J...", "platform": "tiktok", "username": "dapursekar", "status": "active", "quota_remaining": 12 },
{ "id": "acc_ig_01J...", "platform": "instagram", "username": "dapursekar", "status": "active", "quota_remaining": 87 }
]
}
Notes: status is one of active, needs_reconnect, revoked or error (see docs/architecture/data-model.md); a value other than active flags a connection that needs attention, see Troubleshooting.
get_account_capabilities
When to use it: Before building a post for an account you have not used yet, especially TikTok, to learn what is actually allowed: privacy options, max video length, and whether comment, duet and stitch can be toggled at all.
Scope: accounts:read
Input
| Field | Type | Required | Description |
|---|---|---|---|
account_id | string | Yes | The account to inspect |
Output
{
"account_id": "acc_tt_01J...",
"platform": "tiktok",
"privacy_level_options": ["PUBLIC_TO_EVERYONE", "MUTUAL_FOLLOW_FRIENDS", "SELF_ONLY"],
"max_video_post_duration_sec": 180,
"comment_disabled_by_creator": false,
"duet_disabled_by_creator": false,
"stitch_disabled_by_creator": true
}
Notes: This calls TikTok's creator_info live, not a cache, so it reflects the creator's current settings. It never returns a privacy_level for the agent to use directly: privacy is always chosen by the account owner, see create_post below.
upload_media
When to use it: Before referencing media in create_post or create_posts_batch. Accepts a public URL for any media type. Inline base64/data URL upload is images only, for an image the agent's own AI just generated (ADR-20: IMMA AI does not generate images itself, it only stores and validates what the agent produced). Video must be supplied as a URL.
Scope: posts:write
Input
| Field | Type | Required | Description |
|---|---|---|---|
url | string | One of url/data | Public URL IMMA AI downloads |
data | string | One of url/data | Raw base64 or a data URL (data:image/png;base64,...) |
profile_id | string | Yes | Owning profile |
Output
{ "id": "med_01J...", "status": "processing", "type": "image" }
Notes: Same size limit and MIME whitelist as a dashboard upload: images (JPEG, PNG, WebP, HEIC) up to 20MB. Video is not supported through the inline data path, send a url or use the presigned upload flow instead. Referencing a media ID that is still processing in create_post does not fail the call, the target simply waits for the media to become ready. An oversized payload returns payload_too_large; an unrecognized MIME type returns unsupported_format.
validate_post
When to use it: Before create_post or create_posts_batch, especially for a first-time account or an unfamiliar caption format. Dry runs the same validation without creating anything, so the agent can fix problems before committing.
Scope: posts:write
Input: same shape as create_post, below.
Output
{ "valid": false, "issues": [
{ "target_id": "tgt_1", "field": "media[0]", "code": "media_too_long", "message": "Video is longer than this account allows (180s)." }
] }
Notes: Nothing is persisted by this call, it is safe to call repeatedly while iterating on a draft.
create_post
When to use it: To create and schedule a single post across one or more accounts.
Scope: posts:write
Input
| Field | Type | Required | Description |
|---|---|---|---|
profile_id | string | Yes | The profile this post belongs to |
caption | string | Yes | Post text |
media | array | Yes | Media IDs from upload_media, one entry per target's media |
targets | array | Yes | One entry per account: { account_id, instagram?, tiktok? }, same shape as POST /posts |
scheduled_at | string | No | ISO 8601 with a UTC offset; omit to post as soon as approved |
approval | object | No | { mode: "link" | "none", notify? }, defaults to "link" |
ai_generated | boolean | No | Defaults to true for MCP-created posts |
Output
{
"id": "post_01J...",
"status": "awaiting_approval",
"approval": { "id": "apr_...", "url": "https://getimma.com/approve/k8Fq2...", "expires_at": "..." },
"targets": [
{ "id": "tgt_1", "account_id": "acc_ig_...", "status": "awaiting_approval" },
{ "id": "tgt_2", "account_id": "acc_tt_...", "status": "awaiting_approval" }
],
"warnings": []
}
Notes: Never choose a privacy level for the user. For TikTok targets, create_post does not accept privacy_level or interaction toggles from the agent; if sent, they are ignored and the result includes a warning ("Privacy is chosen by the account owner on the approval page"). Use the default hosted approval link (recommended, works from any client) or tiktok.mode: "inbox" to send a draft to the creator's TikTok inbox. See Platform rules for why this cannot be skipped. create_post applies idempotency automatically, based on a hash of the arguments, for 10 minutes, so an agent that retries the same call does not create a duplicate post (same rule as reply_comment, see M14 FR-M14-12).
create_posts_batch
When to use it: To create up to 31 scheduled drafts or posts in one call, for example a month of content, instead of calling create_post in a loop.
Scope: posts:write
Input
| Field | Type | Required | Description |
|---|---|---|---|
profile_id | string | Yes | The profile these posts belong to |
items | array (max 31) | Yes | Each item has the same shape as create_post's input (caption, media, targets, scheduled_at, approval, ai_generated) |
Output
{ "results": [
{ "index": 0, "status": "awaiting_approval", "id": "post_01J...", "approval": { "url": "https://getimma.com/approve/..." } },
{ "index": 1, "status": "error", "error": { "code": "quota_exceeded_for_day", "message": "TikTok daily quota is full for 2026-10-02." } }
] }
Notes: Each item is validated and returned independently, one bad item does not block the rest. Idempotency applies per item, not per call. Every TikTok item still goes through approval or inbox mode, with no batch-level shortcut. Daily platform quota is checked per target day from that item's scheduled_at, not just against the whole batch, so one full day does not reject the rest of the month.
get_calendar
When to use it: Before calling create_posts_batch, to see what is already scheduled, published or drafted, so the agent avoids clashing with existing posts and can fill empty days.
Scope: posts:read
Input
| Field | Type | Required | Description |
|---|---|---|---|
from | string | Yes | Start date (ISO 8601) |
to | string | Yes | End date, at most 90 days after from |
profile_id | string | Yes | The profile to read the calendar for |
Output
{ "timezone": "Asia/Jakarta", "slots": [
{ "post_id": "post_01J...", "scheduled_at": "2026-10-01T18:30:00+07:00", "status": "scheduled",
"platforms": ["instagram", "tiktok"], "caption_preview": "Rendang 1 kg, pre-order..." }
] }
Notes: Times are in the workspace's own timezone. Results are summarized (not the full post detail) to keep the response small. A range longer than 90 days is rejected so the result stays useful in a limited context window.
get_post
When to use it: To check a specific post's status per target, its permalink once published, or a plain-language error if a target failed.
Scope: posts:read
Input
| Field | Type | Required | Description |
|---|---|---|---|
post_id | string | Yes | The post to look up |
Output
{ "id": "post_01J...", "status": "published", "targets": [
{ "id": "tgt_2", "account_id": "acc_tt_...", "status": "published", "permalink": "https://www.tiktok.com/@dapursekar/video/..." }
] }
list_posts
When to use it: To see recent or upcoming posts, for example to summarize what is scheduled this week.
Scope: posts:read
Input
| Field | Type | Required | Description |
|---|---|---|---|
status | string | No | Filter by status |
from | string | No | Start date |
to | string | No | End date |
Output
{ "data": [
{ "id": "post_01J...", "status": "scheduled", "scheduled_at": "2026-10-01T18:30:00+07:00" }
], "cursor": { "next": null, "has_more": false } }
Notes: Same { data, cursor } shape as GET /posts, see Pagination. 20 items per page, so a large history does not fill up the agent's context.
update_post
When to use it: To change a post's caption or schedule before it starts publishing.
Scope: posts:write
Input
| Field | Type | Required | Description |
|---|---|---|---|
post_id | string | Yes | The post to update |
caption | string | No | New caption |
scheduled_at | string | No | New schedule time |
Output
{ "id": "post_01J...", "status": "scheduled", "caption": "Updated caption text", "scheduled_at": "2026-10-01T19:00:00+07:00" }
Notes: Only works while the post has not yet moved into publishing. A TikTok target already awaiting_approval keeps its existing approval link; changing the caption does not silently re-approve it.
cancel_post
When to use it: To stop a scheduled or draft post before it publishes.
Scope: posts:write
Input
| Field | Type | Required | Description |
|---|---|---|---|
post_id | string | Yes | The post to cancel |
Output
{ "id": "post_01J...", "status": "canceled" }
Notes: Same restriction as update_post: only works before publishing starts.
get_analytics
When to use it: To report performance, either for one post or for an account over a date range.
Scope: analytics:read
Input
| Field | Type | Required | Description |
|---|---|---|---|
post_id | string | One of post_id/account_id | Metrics for a single post |
account_id | string | One of post_id/account_id | Metrics for an account |
from | string | No | Start date (account queries) |
to | string | No | End date (account queries) |
Output
{ "account_id": "acc_ig_...", "from": "2026-09-01", "to": "2026-09-27",
"views": 48210, "reach": 31022, "likes": 2104, "comments": 88, "shares": 41, "follower_trend": [ { "date": "2026-09-27", "followers": 4120 } ] }
list_comments
When to use it: To read recent comments on an account so the agent can triage or draft replies.
Scope: inbox:write
Input
| Field | Type | Required | Description |
|---|---|---|---|
account_id | string | No | Filter to one connected account |
status | string | No | open, replied or hidden |
Output
{ "comments": [
{ "id": "cmt_01J...", "account_id": "acc_ig_...", "text": "Harga berapa untuk 1kg?", "author_handle": "@pembeli123", "created_at": "..." }
] }
Notes: Instagram, Facebook and Threads only. TikTok comments are not available through the API.
reply_comment
When to use it: To reply to a specific comment found through list_comments.
Scope: inbox:write
Input
| Field | Type | Required | Description |
|---|---|---|---|
comment_id | string | Yes | Comment to reply to |
text | string | Yes | Reply text |
Output
{ "id": "cmt_reply_01J...", "status": "sent" }
Notes: Instagram, Facebook and Threads only, same as list_comments. Idempotency is applied automatically based on a hash of the arguments for 10 minutes, so a retried call does not send a duplicate reply.
generate_caption
When to use it: To draft captions and hashtags using IMMA AI's own light built-in assistant. This is mainly for dashboard-only users without their own AI subscription; an agent connected through MCP usually already writes captions itself and does not need this tool.
Input
| Field | Type | Required | Description |
|---|---|---|---|
brief | string | Yes | What the post should be about |
language | string | Yes | en or id |
platforms | array | Yes | Target platforms, affects tone and length |
Output
{ "captions": [
{ "platform": "instagram", "text": "Rendang 1 kg, pre-order sampai Jumat.", "hashtags": ["#rendang", "#preorder"] }
] }
Notes: The user must be able to edit the draft before it is posted; a tool call alone never publishes it.
Common workflows
Post to TikTok and Instagram with approval
Prompt: "Post this video to TikTok and Instagram tomorrow at 18:30, and ask the owner to approve it first."
list_accountsfinds the TikTok and Instagram account IDs.upload_mediauploads the video byurl(inline base64 upload only works for images).validate_postchecks for problems before creating anything.create_postwithapproval: { mode: "link" }returnsapproval.url.- The agent replies with the approval link to send to the account owner.
A month of Ramadan content, with images, sent for approval
Prompt (Indonesian): "Buatkan kalender konten Ramadan sebulan untuk toko kue saya, dengan gambar, jadwalkan jam 19.00 WIB, kirim ke saya untuk approval."
Prompt (English): "Build a 30 day Ramadan content calendar for my cake shop, with images, schedule for 7pm local time, and send it to me for approval."
list_accountsfinds the TikTok and Instagram account IDs.get_calendarfor the target month shows which slots are already taken, so the new posts do not clash.- The agent writes a daily brief itself (Ramadan themes, relevant dates) and drafts a caption per day with its own writing ability, then generates an image per post with its own image generation ability. IMMA AI does not generate images itself, see MCP reference.
upload_mediais called once per image with inlinedata, returning a media ID each time.validate_postchecks a few sample items before sending the whole batch (optional but recommended).create_posts_batchsends all items (up to 31) withapproval: { mode: "link" }andai_generated: true. The response'sresults[]includes anapproval.urlper TikTok target.- The agent replies with a summary: the drafts are scheduled and waiting for approval, with the link(s) to send the owner.
Weekly performance summary
Prompt: "Summarize this week's performance across all my accounts."
list_accountslists every connected account.get_analyticsis called per account withfrom/tocovering the last 7 days.- The agent summarizes views, reach and engagement trends in plain language.