MCPMCP Tools/Posts

Posts

Create, publish, and analyze social posts, including boosted posts.

create_post

Writeposts:write

Create a post for a location (or client) and submit it to the selected platforms. Publishes immediately unless scheduledFor is set or draft is true. A requested platform with no active connection never fails this call — the post is still created (as a draft if nothing resolved), and the response is `{ status: "no_connection", missingPlatforms, scope, post: { id, status } }` instead of the usual `{ id, status }` for whichever platforms couldn't resolve a connection. Compose what to tell the user from that data; do not assume the call failed just because `status` is "no_connection" — the content was saved. Likewise a post that cannot go live yet because a REQUIRED FIELD is absent (an event with no start/end date, a caption-less announcement, Instagram with no image) is saved as a draft and answers `{ status: "incomplete", missingFields, scope, post }`. Both gaps can appear together, in which case `status` is "no_connection" and `missingFields` rides alongside it — tell the user about BOTH at once rather than letting them discover the second after fixing the first. In every one of these cases the content EXISTS as a draft: say what was saved, name what it needs, point at where to fix it, and never report it as a failure. PLATFORM RULES (enforced — violations rejected): Post types: `announcement` works on every platform; `event` and `offer` are Google-only (any social platform ⇒ must be announcement). Caption char limits: google 1500, facebook 30000, instagram 2200, x 280 (X thread mode is exempt from the 280 limit), linkedin 2000, pinterest 500, mastodon 500, bluesky 300. Media (per platform, using each item's `platform`): facebook ≤10 images OR ≤1 video, no mix (carousel = 2–10 images only, per-card headline ≤80 / description ≤200); instagram requires ≥1 media, ≤10 images OR ≤1 video, no image/video mix; x ≤4 images OR ≤1 video, no mix; linkedin ≤5 images OR ≤1 video, no mix; pinterest image-only, exactly 1, required; mastodon ≤4 images OR ≤1 video, no mix. Google event ⇒ eventTitle (≤58 chars) + eventStartAt + eventEndAt (end after start) required. Google offer ⇒ ctaType + ctaUrl required. scheduledFor must be in the future. Drafts (draft=true) skip required-field checks but still enforce all structural checks above.

Parameters
locationIdstringoptional
The location's id (from list_locations).
clientIdstringoptional
Client id (for brand-level posts), from list_clients.
namestringrequired
Internal post name/label. Required, non-empty, ≤255 characters.
postType"announcement" | "event" | "offer"required
Post type. `announcement` is supported by all platforms. `event` and `offer` are GOOGLE-ONLY — if any social platform (facebook, instagram, x, linkedin, pinterest, mastodon, bluesky) is selected, postType must be `announcement`.
platforms("google" | "facebook" | "instagram" | "x" | "linkedin" | "pinterest" | "mastodon" | "bluesky" | "threads" | "tiktok")[]required
Target platforms. Valid values: google, facebook, instagram, x, linkedin, pinterest, mastodon, bluesky. At least one is required; unknown values are rejected. e.g. ["google","facebook","instagram"].
messageGooglestringoptional
Caption for Google. Required when `google` is selected (unless draft). Max 1500 characters.
messageFacebookstringoptional
Shared social caption — used by facebook, instagram, x, linkedin, pinterest, mastodon, bluesky. Required when any of those is selected, unless draft. It is validated against EACH selected platform's character limit: facebook 30000, instagram 2200, x 280 (X thread mode is exempt from the 280 limit), linkedin 2000, pinterest 500, mastodon 500, bluesky 300. The message must fit the smallest limit among the selected social platforms.
ctaType"learn_more" | "sign_up" | "order_online" | "book" | "buy" | "call_now"optional
Call-to-action type. For a Google `offer`, ctaType AND ctaUrl are both required. learn_more/sign_up/order_online/book/buy all require ctaUrl; call_now does not.
ctaUrlstringoptional
Call-to-action URL. Required for a Google offer and for CTA types other than call_now.
mediaUrlsobject[]optional
Media items, one entry per platform attachment: [{ "url", "platform", "type": "image"|"video" }]. The `platform` on each item must be one of the target platforms and controls which per-platform media rules apply. Per-platform limits (violations are rejected): google = no media constraints enforced here; facebook = ≤10 images OR ≤1 video, no mix (carousel: 2–10 image cards, images only); instagram = requires ≥1 item, ≤10 images OR ≤1 video, images and video cannot be mixed; x = ≤4 images OR ≤1 video, no mix; linkedin = ≤5 images OR ≤1 video, no mix; pinterest = image only (no video), exactly 1 image, required; mastodon = ≤4 images OR ≤1 video, no mix.
urlstringoptional
Publicly reachable media URL (http/https).
platform"google" | "facebook" | "instagram" | "x" | "linkedin" | "pinterest" | "mastodon" | "bluesky"optional
Which target platform this media attaches to.
type"image" | "video"optional
Media kind.
eventTitlestringoptional
Event/offer title. For a Google event or offer this is required (unless draft) and must be ≤58 characters.
eventStartAtstringoptional
Event/offer start (ISO timestamp). Required for Google event/offer posts (unless draft).
eventEndAtstringoptional
Event/offer end (ISO timestamp). Required for Google event/offer posts (unless draft); must be after the start.
offerTermsstringoptional
Offer terms (offer posts).
offerCouponCodestringoptional
Offer coupon code.
offerRedeemUrlstringoptional
Offer redemption URL.
scheduledForstringoptional
Schedule for this ISO timestamp (must be in the future; omit to publish now).
draftbooleanoptional
Save as draft without publishing. Drafts skip publish-gating 'required' checks (required message, required media, required event/offer fields) but STILL enforce structural checks: character limits, media counts, media mixing, valid enums, carousel bounds, and date ordering.
Example request
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "create_post",
    "arguments": {
      "name": "string",
      "postType": "announcement",
      "platforms": [
        "google"
      ]
    }
  }
}
Example response
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "..."
      }
    ]
  }
}

Response shape shown for illustration — the actual content depends on the tool and your data.

MCPMCP Tools/Posts/update_post

update_post

Writeposts:write

Update an editable post (draft/scheduled/error/active). Reconciles platform submissions. A requested platform with no active connection never fails this call either (same as create_post) and the response is `{ status: "no_connection", missingPlatforms, scope, post: { id, status } }` instead of the usual `{ id, status }`. PLATFORM RULES (enforced — violations rejected): Post types: `announcement` works on every platform; `event` and `offer` are Google-only (any social platform ⇒ must be announcement). Caption char limits: google 1500, facebook 30000, instagram 2200, x 280 (X thread mode is exempt from the 280 limit), linkedin 2000, pinterest 500, mastodon 500, bluesky 300. Media (per platform, using each item's `platform`): facebook ≤10 images OR ≤1 video, no mix (carousel = 2–10 images only, per-card headline ≤80 / description ≤200); instagram requires ≥1 media, ≤10 images OR ≤1 video, no image/video mix; x ≤4 images OR ≤1 video, no mix; linkedin ≤5 images OR ≤1 video, no mix; pinterest image-only, exactly 1, required; mastodon ≤4 images OR ≤1 video, no mix. Google event ⇒ eventTitle (≤58 chars) + eventStartAt + eventEndAt (end after start) required. Google offer ⇒ ctaType + ctaUrl required. scheduledFor must be in the future. Drafts (draft=true) skip required-field checks but still enforce all structural checks above.

Parameters
postIdstringrequired
Post id (from list_posts or get_post).
namestringoptional
Internal post name/label. Required, non-empty, ≤255 characters.
postType"announcement" | "event" | "offer"optional
Post type. `announcement` is supported by all platforms. `event` and `offer` are GOOGLE-ONLY — if any social platform (facebook, instagram, x, linkedin, pinterest, mastodon, bluesky) is selected, postType must be `announcement`.
platforms("google" | "facebook" | "instagram" | "x" | "linkedin" | "pinterest" | "mastodon" | "bluesky" | "threads" | "tiktok")[]optional
Target platforms. Valid values: google, facebook, instagram, x, linkedin, pinterest, mastodon, bluesky. At least one is required; unknown values are rejected. e.g. ["google","facebook","instagram"].
messageGooglestringoptional
Caption for Google. Required when `google` is selected (unless draft). Max 1500 characters.
messageFacebookstringoptional
Shared social caption — used by facebook, instagram, x, linkedin, pinterest, mastodon, bluesky. Required when any of those is selected, unless draft. It is validated against EACH selected platform's character limit: facebook 30000, instagram 2200, x 280 (X thread mode is exempt from the 280 limit), linkedin 2000, pinterest 500, mastodon 500, bluesky 300. The message must fit the smallest limit among the selected social platforms.
ctaType"learn_more" | "sign_up" | "order_online" | "book" | "buy" | "call_now"optional
Call-to-action type. For a Google `offer`, ctaType AND ctaUrl are both required. learn_more/sign_up/order_online/book/buy all require ctaUrl; call_now does not.
ctaUrlstringoptional
Call-to-action URL. Required for a Google offer and for CTA types other than call_now.
mediaUrlsobject[]optional
Media items, one entry per platform attachment: [{ "url", "platform", "type": "image"|"video" }]. The `platform` on each item must be one of the target platforms and controls which per-platform media rules apply. Per-platform limits (violations are rejected): google = no media constraints enforced here; facebook = ≤10 images OR ≤1 video, no mix (carousel: 2–10 image cards, images only); instagram = requires ≥1 item, ≤10 images OR ≤1 video, images and video cannot be mixed; x = ≤4 images OR ≤1 video, no mix; linkedin = ≤5 images OR ≤1 video, no mix; pinterest = image only (no video), exactly 1 image, required; mastodon = ≤4 images OR ≤1 video, no mix.
urlstringoptional
Publicly reachable media URL (http/https).
platform"google" | "facebook" | "instagram" | "x" | "linkedin" | "pinterest" | "mastodon" | "bluesky"optional
Which target platform this media attaches to.
type"image" | "video"optional
Media kind.
eventTitlestringoptional
Event/offer title. For a Google event or offer this is required (unless draft) and must be ≤58 characters.
eventStartAtstringoptional
Event/offer start (ISO timestamp). Required for Google event/offer posts (unless draft).
eventEndAtstringoptional
Event/offer end (ISO timestamp). Required for Google event/offer posts (unless draft); must be after the start.
offerTermsstringoptional
Offer terms (offer posts).
offerCouponCodestringoptional
Offer coupon code.
offerRedeemUrlstringoptional
Offer redemption URL.
scheduledForstringoptional
Schedule for this ISO timestamp (must be in the future; omit to publish now).
draftbooleanoptional
Save as draft without publishing. Drafts skip publish-gating 'required' checks (required message, required media, required event/offer fields) but STILL enforce structural checks: character limits, media counts, media mixing, valid enums, carousel bounds, and date ordering.
Example request
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "update_post",
    "arguments": {
      "postId": "string"
    }
  }
}
Example response
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "..."
      }
    ]
  }
}

Response shape shown for illustration — the actual content depends on the tool and your data.

MCPMCP Tools/Posts/get_post

get_post

Readposts:read

Get a post with per-platform submission performance (agency-scoped).

Parameters
postIdstringrequired
Post id (from list_posts).
Example request
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "get_post",
    "arguments": {
      "postId": "string"
    }
  }
}
Example response
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "..."
      }
    ]
  }
}

Response shape shown for illustration — the actual content depends on the tool and your data.

MCPMCP Tools/Posts/list_posts

list_posts

Readposts:read

List posts for a location with per-platform state and aggregate stats (agency-scoped).

Parameters
locationIdstringrequired
The location's id (from list_locations).
platform"google" | "facebook" | "instagram" | "x" | "linkedin" | "pinterest" | "mastodon" | "bluesky" | "threads" | "tiktok"optional
Filter by platform.
type"announcement" | "event" | "offer"optional
Filter by post type.
status"draft" | "scheduled" | "error" | "active" | "incomplete"optional
Filter by status.
fromstringoptional
Created from (ISO).
tostringoptional
Created to (ISO).
searchstringoptional
Name contains (case-insensitive).
limitnumberoptional
Max rows to return (1–200, default 50).
Example request
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "list_posts",
    "arguments": {
      "locationId": "string"
    }
  }
}
Example response
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "..."
      }
    ]
  }
}

Response shape shown for illustration — the actual content depends on the tool and your data.

MCPMCP Tools/Posts/delete_post

delete_post

Writeposts:write

Delete a post and unpublish it from its platforms. Unpublishes every platform first, then archives the post ONLY IF every platform unpublish succeeded — this never permanently deletes the row; it just stops appearing anywhere in the API. If even one platform fails to unpublish, nothing is archived — the call still succeeds (no throw) but returns `ok: false` with a `failed` list; check `ok` rather than assuming the post is gone.

Parameters
postIdstringrequired
Post id (from list_posts).
Example request
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "delete_post",
    "arguments": {
      "postId": "string"
    }
  }
}
Example response
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "..."
      }
    ]
  }
}

Response shape shown for illustration — the actual content depends on the tool and your data.

MCPMCP Tools/Posts/publish_post_now

publish_post_now

Writeposts:write

Force-submit a draft/errored post now (retries pending/errored platform submissions). Throws if the post is scheduled for a future time — cancel or wait for the schedule instead. A no-op (no error, nothing retried) if there's nothing pending or errored to retry.

Parameters
postIdstringrequired
Post id (from list_posts).
Example request
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "publish_post_now",
    "arguments": {
      "postId": "string"
    }
  }
}
Example response
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "..."
      }
    ]
  }
}

Response shape shown for illustration — the actual content depends on the tool and your data.

MCPMCP Tools/Posts/get_post_analytics

get_post_analytics

Readposts:read

See how posts are performing — engagement, views, clicks, impressions over time. Read-only analytics rollup across a client's brand connections (summary, byPlatform, trends, top posts).

Parameters
clientIdstringrequired
Client id (from list_clients).
fromstringoptional
From (ISO).
tostringoptional
To (ISO).
Example request
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "get_post_analytics",
    "arguments": {
      "clientId": "string"
    }
  }
}
Example response
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "..."
      }
    ]
  }
}

Response shape shown for illustration — the actual content depends on the tool and your data.

MCPMCP Tools/Posts/get_posts_client_rollup

get_posts_client_rollup

Readposts:read

Posts "All locations" rollup for a client — the stat cards + location health breakdown shown when a client is selected with no specific location. Returns locationCount, healthCounts (errors / notSetUp / new / silent / quiet / active — mutually exclusive per-location classification based on connection errors, posting recency, and engagement), stats for the last 30 days (totalPosts, totalEngagement, totalImpressions, totalClicks, avgPostsPerWeek) with prevStats for the prior 30 days (for delta display), and missingBrandPlatforms (brand-level social platforms not yet connected for this client). Pass locationId to narrow the stat cards to one location while still reporting health counts for the whole client. Distinct from get_post_analytics (that one is trend charts/top posts); this is the health/rollup view.

Parameters
clientIdstringrequired
The client to roll up (required, from list_clients).
locationIdstringoptional
Narrow the stat cards to one location (from list_locations), while healthCounts still covers the whole client.
Example request
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "get_posts_client_rollup",
    "arguments": {
      "clientId": "string"
    }
  }
}
Example response
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "..."
      }
    ]
  }
}

Response shape shown for illustration — the actual content depends on the tool and your data.

MCPMCP Tools/Posts/create_post_boost

create_post_boost

Writeposts:write

Boost a post with paid ad spend through a connected ad account — this spends real money. dailyBudget (minor currency units, e.g. cents) and durationDays are ALWAYS required, regardless of whether you also pass boostConfigId; if boostConfigId is given, only its adAccountId/targeting/publisherPlatforms/delayHours are used as defaults for whatever you don't specify — its own saved budget is never used silently. Pass postSubmissionId to boost an ALREADY-PUBLISHED post's live submission (spends immediately). Pass postId (+ platform or connectionId) instead to pre-configure a boost on a post that hasn't published yet — it stays queued (no spend) and only starts once that post's submission goes live. adAccountId must belong to a connected account (see list_ad_accounts); use select_ad_account first if none is selected.

Parameters
postSubmissionIdstringoptional
An already-published post's submission id — boosts it immediately. Use this OR postId, not both.
postIdstringoptional
A not-yet-published post's id — pre-configures a deferred boost. Requires platform or connectionId.
platformstringoptional
Which platform submission to boost, when using postId (e.g. "facebook").
connectionIdstringoptional
The exact connection to boost, when using postId. Preferred over platform when the post has multiple submissions on the same platform.
boostConfigIdstringoptional
A saved boost config (from list_boost_configs) to source adAccountId/targeting/publisherPlatforms/delayHours defaults from. Its budget/duration are NOT used — pass dailyBudget/durationDays explicitly regardless.
adAccountIdstringoptional
The ad account to spend from (from list_ad_accounts). Required unless boostConfigId supplies one.
targetingobjectoptional
Ad targeting. All fields optional — omitted ones use the platform's defaults / broad targeting.
ageMinnumberoptional
Minimum age.
ageMaxnumberoptional
Maximum age.
gendersnumber[]optional
Platform gender codes to target.
geoLocationsobjectoptional
Geographic targeting.
countriesstring[]optional
ISO country codes.
regionsstring[]optional
Region/state names or ids.
citiesstring[]optional
City names or ids.
zipsstring[]optional
Postal/ZIP codes.
interestsobject[]optional
Interest targeting.
idstringoptional
namestringoptional
publisherPlatformsstring[]optional
Platform surfaces to run on, e.g. ["facebook", "instagram"].
dailyBudgetnumberrequired
Daily budget in minor currency units (cents), e.g. 2500 for $25.00/day. REQUIRED. Must be positive and no more than 500000 (this MCP tool's own safety cap — not enforced anywhere else in the app, including the dashboard UI).
durationDaysnumberrequired
How many days the boost runs for. REQUIRED. Must be between 1 and 90.
delayHoursnumberoptional
Hours to wait after the post goes live before spend starts. Defaults to 0 (or the boostConfig's, if given).
publisherPlatformsstring[]optional
Platform surfaces to run on, e.g. ["facebook", "instagram"].
scheduledStartstringoptional
An exact ISO datetime to start spend at, instead of delayHours from publish time.
Example request
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "create_post_boost",
    "arguments": {
      "dailyBudget": 0,
      "durationDays": 0
    }
  }
}
Example response
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "..."
      }
    ]
  }
}

Response shape shown for illustration — the actual content depends on the tool and your data.

MCPMCP Tools/Posts/stop_post_boost

stop_post_boost

Writeposts:write

Stop a LIVE boost that's already spending on the platform — halts real in-flight ad spend. This cannot be resumed; a new boost would need to be created. To cancel a boost that hasn't gone live yet (still queued, awaiting the post to publish, no spend yet), use cancel_deferred_boost instead. Identify the boost by its adRunId — there is currently no tool to list/look one up; the only way to learn it is from create_post_boost's own response when the boost was created.

Parameters
adRunIdstringrequired
The id of the live ad run to stop (required).
Example request
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "stop_post_boost",
    "arguments": {
      "adRunId": "string"
    }
  }
}
Example response
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "..."
      }
    ]
  }
}

Response shape shown for illustration — the actual content depends on the tool and your data.

MCPMCP Tools/Posts/cancel_deferred_boost

cancel_deferred_boost

Writeposts:write

Cancel a deferred boost that hasn't gone live yet (its post hasn't published, so no money has been spent). To stop a boost that's already live and spending, use stop_post_boost instead. Identify it by its adCampaignId — there is currently no tool to list/look one up; the only way to learn it is from create_post_boost's own response when the deferred boost was created.

Parameters
adCampaignIdstringrequired
The id of the deferred boost's ad campaign to cancel (required).
Example request
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "cancel_deferred_boost",
    "arguments": {
      "adCampaignId": "string"
    }
  }
}
Example response
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "..."
      }
    ]
  }
}

Response shape shown for illustration — the actual content depends on the tool and your data.