Antwork
Server Details
Draft, schedule, and publish social posts for your workspace straight from your AI.
- Status
- Healthy
- Uptime
- 100.0% over the last 24 hours
- OAuth
- Works in Glama
- Last Tested
- Transport
- Streamable HTTP · MCP 2025-11-25
- URL
- Repository
- polynode-co/antwork
- GitHub Stars
- 1
- ChatGPT
- –
- Claude
- –
TDQS
Scored across 24 tools
Most tools have clearly distinct resource+action targets, and the descriptions actively disambiguate the risky pairs (add_media appends vs attach_media sets the exact list; get_connection_urls connects vs list_social_accounts reads). The one soft zone is the analytics/read cluster — get_post, get_performance, list_posts and fetch_platform_posts all return posts and metrics, and telling them apart requires reading the long descriptions rather than the names. Boundaries are defensible but not instantly obvious.
Every tool is snake_case with a leading verb and a resource noun (add_media, create_post, schedule_post, publish_post, delete_media, list_workspaces, update_workspace). Even the outliers — get_more_tools, report_issue, set_default_workspace — follow the verb-first convention. No camelCase or naming-style mixing anywhere in the set.
24 tools sits at the upper end but is justified by a genuinely broad domain: multi-platform publishing, media library, accounts/OAuth, workspaces, analytics, routines, comments and error reporting. Each tool maps to a real operation and there is little dead weight, though a few (set_default_workspace, get_more_tools) are thin relative to the rest. Slightly heavy rather than mismatched.
Post lifecycle is fully covered (create, update, delete, schedule, publish, list, get, retry via publish_post), along with media CRUD, workspace CRUD minus delete, account listing/connecting and performance reading. Minor gaps remain: no disconnect/remove social account, no delete_workspace, and comment coverage is read+reply only with no delete or moderation. These are workaroundable rather than blocking.
Publisher details
- Operator
- Polynode Technologies · Publisher source
- Operator website
- https://antwork.io · Publisher source
- Vendor relationship
- First-party
- Documentation
- https://antwork.io/docs/mcp · Publisher source
- Trust center
- Not available
- Restrictions
- Free for 2 connected social accounts; each additional account is paid. Free accounts have daily post caps. Instagram requires a Professional (Business or Creator) account. No custom OAuth app or admin approval needed. · Publisher source
Available Tools
24 toolsadd_mediaAInspect
Store files in the media library and append them to posts, in one call.
Exactly one source: file, url / urls, upload, or media_ids /
media_urls (already in the library, from list_media).
attach_to_post_ids lists every post it goes on; nothing already there is
removed (attach_media sets the exact list). The result names the posts
that got it (attached), those that did not and why (notAttached), and
those that still cannot publish (publishBlockers). A file is never read
into the call as base64.
PNG, JPEG, GIF, WebP, AVIF images up to 10 MB (converted to the platform's
format at publish, so never re-export one); MP4, MOV, WebM video and PDF up
to 1 GB by upload, 100 MB by url or file.
Shorts, Reels, TikToks and stories are vertical (9:16) video, made vertical from the start: a landscape video shrunk onto a blurred or padded vertical frame reads as a repost, so make a vertical cut instead. On YouTube only a vertical or square video of three minutes or less is a Short.
Args:
file: A file the user attached to a ChatGPT conversation. ChatGPT
fills it in and Antwork downloads it; it is never synthesized.
ChatGPT's mobile apps send no usable file, which the result says.
url: Public HTTPS URL of the file (e.g. an AI-generated image already
hosted), or a Google Drive, Docs, Slides, Dropbox or OneDrive share
link as the user copied it. Antwork downloads it.
urls: Up to 10 such links in one call, e.g. a carousel's slides, in
order; results has one entry per link. If any fails, none is
attached (stored ones are in results).
upload: A file in a shell or code-execution sandbox: {} returns a
one-time uploadUrl (10 minutes), and
curl -sS -X PUT --data-binary @<path> '<uploadUrl>' stores and
attaches it; that response is the result. mime_type and
byte_size are optional.
media_ids: Library media ids to add to the posts.
media_urls: Library media URLs to add to the posts.
attach_to_post_ids: Every post to add the media to.
workspace_id: Workspace ID or name. Optional if the user has only one.
fit: "crop" (centre) or "pad" (blurred background): each image on
attach_to_post_ids whose aspect ratio the post's platform
refuses is replaced by a copy at the nearest ratio it takes (the
original stays in the library; fitted lists the copies).
Images only. With no source, it fits the posts' current media.
Inputs: fit, url, file, urls, +8 more. Returns: _mcp_instructions
attach_mediaADestructiveInspect
Set the exact media list on a post: reorder, remove or clear.
Replaces the post's media with media_urls in that order; an empty list
removes all of it. Appending is add_media. PDFs render only on LinkedIn
(document posts). Leaving a post without media its platform requires
still saves, with a publishBlocker in the result. updates sets up to
25 posts' lists in one call, each answered in posts.
Args: post_id: The post ID to set media on. media_urls: Media URLs from list_media (or this workspace's storage). workspace_id: Workspace ID or name. Optional if user has only one workspace. updates: Instead: [{post_id, media_urls | media_ids}], each that post's exact list.
Inputs: context, post_id, updates, llm_model, +3 more. Returns: _mcp_instructions
create_postAInspect
Save drafts. Nothing is sent: schedule_post or publish_post does that.
One account: text + account_id; variants adds up to 3 alternative
versions for that account, each its own draft. Several accounts: posts,
one entry per draft, each with its own copy. Entries on different
accounts are one post with a version per account (sent together with
post_ids); entries repeating an account are separate posts. The result carries characterCount /
characterLimit (overLimit when the text cannot publish), and, when
they apply: mediaRequired (TikTok and YouTube need a video, Instagram
and Pinterest an image or video), derivedTitle (YouTube takes the first
100 characters unless platform_options.title is set), settingsRequired
(TikTok: the user's choices to ask, tiktokChoices),
pinterestBoard, and similarRecent: this account's posts from the last
30 days that read nearly the same, which the user hears about before it
goes out (no need to list posts to check for duplicates). The same text
and media as an unsent post of the account is not saved again: the result
is that post (duplicateOf, created: false), to use instead.
Args:
text: Post copy; may be empty with media on X, Facebook, Instagram and Threads. @handle links by itself on X, Threads, Instagram (max 20 per caption), TikTok, YouTube, Bluesky (full handle, e.g. @name.bsky.social), Mastodon (@name on the same server, @name@server elsewhere) and Telegram channels; on Facebook, Pinterest, Discord, Google Business Profile and Slack it stays plain text; on LinkedIn it links only with user_tags.
account_id: Social-account id (from list_social_accounts), not a platform name.
hashtags: Appended to the text as #tags, counted in its limit (YouTube: video tags, unless platform_options.tags). A list, or a string split on commas (on spaces if it has none).
goal: e.g. "Educate", "Engage", "Promote", "Entertain".
scheduled_for: ISO 8601. Proposes a time on the draft; only schedule_post schedules. proposedTimeConflict in the result means the account's daily cap refuses that time; propose its nextFreeAt.
campaign_id: The campaignId of a post made with posts: this draft becomes one more account's version of it.
user_tags: LinkedIn company: [{company: ""}] with "@" in the text; Antwork finds the Page and links its exact name. LinkedIn people can't be looked up, only the user's own connected accounts. Instagram people on the media: [{username, platform: "instagram", type: "photo_tag", x, y (0-1 from left/top), mediaIndex (carousel photo, 0-based)}]; a photo needs x/y (centre if omitted), a reel takes the username only, a story either. Tagged accounts must be public; recentTags in get_post_context lists handles tagged before. The result's tagChecks shows each handle as found on Instagram or unchecked (personal accounts can't be looked up; still taggable).
pinterest_board_id: Pinterest only, from boards in get_post_context. Omitted = the account's first board.
slack_channel: Slack only: a channel id or #name from slackChannels in get_post_context. Omitted = the account's last channel (defaultSlackChannel); with none the post cannot publish.
platform_options: Only what the user asked for. Instagram: publishType ("timeline" | "story"; a reel is "timeline" with a video; a story with several media_urls drafts one story per file, in order, as one set), postToGrid, coverUrl (a Reel's cover image, https). Facebook: publishType ("timeline" | "story"; a story is one photo or one video, its text is not shown). Pinterest: pinTitle (≤100), link (the pin's destination URL, https). YouTube: privacyStatus ("public" | "unlisted" | "private"), title (≤100), categoryId (e.g. "22", "28"), madeForKids, containsSyntheticMedia (realistic content made or altered with AI), thumbnailUrl (custom thumbnail, JPEG/PNG under 2 MB, https; needs a phone-verified channel), tags (list of video tags viewers do not see, ≤500 chars in all; used instead of hashtags). LinkedIn, Facebook, Instagram, Threads, YouTube, Bluesky, Mastodon: firstComment, a comment Antwork posts on the post right after it goes live (not on a story; links in YouTube Shorts comments are not clickable). TikTok settings are set by the user at settingsUrl, not here.
variants: Up to 3 alternative versions for the same account.
workspace_id: Workspace ID or name. Optional if user has only one workspace.
media_urls: Media for the draft (every draft, with posts): library URLs, or public https links to a file, fetched into the library first as add_media(url=...) does. Saves the add_media call when moving posts in from another tool.
posts: Up to 25 drafts in one call, instead of text + account_id: [{"account_id": str, "text": str}], each entry optionally with hashtags, goal, user_tags, pinterest_board_id, slack_channel, platform_options. Each account's copy is written in its own voice; there is no shared body.
allow_duplicate: Save a second copy of a post the account already has unsent, only when the user asks for one.
routine_id: The Autopilot routine this run is for (get_post_context(routine_id)): its accounts and post limit apply.
Inputs: goal, text, posts, context, +15 more. Returns: _mcp_instructions
create_workspaceAInspect
Create a new workspace owned by the authenticated user.
Use this when the user wants a separate brand / client / project space —
each workspace has its own connected social accounts,
posts, and media library. Subsequent tool calls can target the new
workspace by passing workspace_id (its returned ID or its name).
Args: name: Workspace name (required, 1–60 characters).
Inputs: name (required), context, llm_model, conversation_id. Returns: _mcp_instructions
delete_mediaADestructiveInspect
Delete a media item from the workspace media library.
This removes the Firestore record. The file in storage may still exist
but will no longer appear in the media library. media_ids deletes up
to 50 in one call, each answered in media; one still on a post answers
media_in_use with its usedInPosts and the rest still go.
Args: media_id: The media item ID to delete. workspace_id: Workspace ID or name. Optional if user has only one workspace. media_ids: Several media items to delete, instead of media_id.
Inputs: context, media_id, llm_model, media_ids, +2 more. Returns: _mcp_instructions
delete_postADestructiveInspect
Delete a post. Drafts and scheduled posts are removed; a published post is hidden but keeps its metrics history unless preserve_analytics=false.
post_ids deletes up to 50 with the same options in one call; each
answers in posts, and one that fails does not stop the rest.
Args: post_id: The post ID to delete. delete_from_platforms: True also deletes it from every platform it was published to; a list of platform names limits that to those. TikTok has no delete API. Omitted, the live posts stay. preserve_analytics: Published posts only; defaults to true. workspace_id: Workspace ID or name. Optional if user has only one workspace. post_ids: Several posts to delete, instead of post_id.
Inputs: context, post_id, post_ids, llm_model, +4 more. Returns: _mcp_instructions
fetch_platform_postsARead-onlyInspect
Posts read straight from a platform, with metrics and permalinks: the account's own, or other people's public posts.
source="own" (default): the connected accounts' own posts, Antwork's or
not, one entry per account in accounts, so two LinkedIn accounts come
back side by side. It includes posts made on the platform directly, which
get_performance (Antwork-published posts only) does not; a duplicate check
before drafting is create_post's similarRecent. LinkedIn personal profiles cannot be read this way (LinkedIn
closed that API): they come back unsupported: true with a reason.
Antwork-published posts on them still have metrics in get_performance
and get_post.
An account that could not be read has fetchError (reason,
message): its empty posts is not an empty account, so say it could
not be read, never that it has no posts. X answers carrying cachedAt
come from a read kept up to a week (X bills per post read). A post's
mediaUrls (Instagram, Facebook, Threads, Pinterest, Mastodon, Bluesky
images) go to add_media(url=...) to repost the file; they expire.
source="search" (query) or "account" (handle): public posts by
anyone on platform, read with a connected account's sign-in and sorted
by outlierScore, how many times its usual a post did (1 is typical;
scoreBasis says against what: engagement per follower across the
results, or a creator against their own median). Each post has text,
url, author, format, metrics and traits (length bucket, first
line, hashtag count, link, question). X, YouTube, Bluesky and Mastodon,
plus Instagram creators only (source="account", public Business or
Creator accounts, read with a Unified Login account; an Instagram Login one
answers instagram_reconnect_for_discovery with the reconnect link). Any
other platform, or an Instagram search, answers unsupported with the way
around it.
Paid plans; X searches have a weekly limit. A read is reused for a day.
Studying what went viral, in order: get_post_context for the user's account (the voice to write in); this tool for the outliers; the 2 or 3 patterns they share (hook, format, length, angle) named for the user, rather than their topics; a plan of variations on the user's own business, agreed before any create_post. A variation takes the structure, never the source's wording, and a quote names its creator.
Args:
platform: One platform, e.g. "linkedin". Omitted = every connected one (own only; required otherwise).
account_id: One connected account; with search/account, whose sign-in makes the read.
max_posts: Own posts per account (1-25, default 10); with search/account, the same as limit.
workspace_id: Workspace ID or name. Optional if user has only one workspace.
source: "own" (default), "search" or "account".
query: Keywords or a #hashtag, with source="search".
handle: A creator's handle, with source="account" (on Mastodon user@server).
since_days: How far back with search/account, 1-30 (default 7 for search, 30 for account; X search reaches 7).
limit: Posts returned with search/account (1-25, default 10); with own, the same as max_posts.
Inputs: limit, query, handle, source, +8 more. Returns: _mcp_instructions
get_connection_urlsARead-onlyInspect
Get the links to connect or re-auth social accounts.
Returns an OAuth connect URL per platform, for the user to open. This is
the tool for MANAGING connections — connecting a new account,
reconnecting a stale one, or seeing the connect options. For reading
what's already connected, list_social_accounts is the lighter call.
Args: workspace_id: Workspace ID or name. Optional if user has only one workspace.
Inputs: context, llm_model, workspace_id, conversation_id. Returns: _mcp_instructions
get_more_toolsARead-onlyIdempotentInspect
Check for additional tools whenever your task might benefit from specialized capabilities - even if existing tools could work as a fallback.
Inputs: context (required), llm_model, conversation_id.
get_performanceARead-onlyInspect
How published posts are doing: one table per post, the per-day and follower tables, and findings.
rows: one per post Antwork published in the last days (posts made on
the platform directly: fetch_platform_posts), with likes, comments,
shares, impressions, reach, saves, clicks, bookmarks, linkClicks,
profileVisits, follows, watchTimeSeconds, avgWatchTimeSeconds and
totalEngagement (likes+comments+shares), plus platformTotals.
impressions counts a different thing per platform, named by
reachBasis, so different bases never add or compare; reach never adds.
A null is a metric not measured or not reported, never a zero.
coverage says what the numbers count (only posts published through
Antwork, the window, posts not measured yet per platform, and per account
notThroughAntwork when a stored read shows posts made elsewhere): quote
it before comparing these totals with the platform or with daily.
daily: engagement per (date, platform) plus an "all" row per date,
and changeTotals, the window's daily growth summed (not lifetime);
followers: per (date, account).
findings, computed from those numbers, in the workspace timezone:
comparison (each platform against the previous window of equal length),
ranking (top and bottom posts by engagement rate and the traits the top
ones share, or enoughData: false), bestWindows (from the account's
own posts, else labelled fallbacks), followers (change over the
window), postAgainToday (the last and next 24 hours against the
account's usual count and daily cap), growth (the posts that brought
followers where the platform reports follows per post; growth.days on
every platform: the stretches between follower counts that grew most, the
posts in them, and growth with posts vs without, quoting its basis) and
digest: the window as a report, with lines ready to
show. A weekly or monthly report is days=7 or days=30 and its
digest.
With post_id, that one post's per-day history instead (cumulative* and
daily* columns); without days, its whole history.
format="table" answers only flat rows for a sheet or dashboard: per post
(postId, account, platform, publishedAt, url, likes, comments, shares,
impressions, reach, saves, clicks) and per account (followers, change).
Args: days: The window, ending today (1-365, default 30). platform: Restrict to one platform. account_id: Restrict to one connected account. post_id: One post's history instead of the workspace's. limit: Max post rows (default 30, max 50). workspace_id: Workspace ID or name. Optional if user has only one workspace. format: "table" for the compact rows above, nothing else.
Inputs: days, limit, format, context, +6 more. Returns: _mcp_instructions
get_postARead-onlyInspect
One post in full: text, account, status, schedule, media, links, and for a published post its lifetime metrics.
A published post nothing has read yet (15 minutes or older) is read
from its network once, before answering.
metricCells holds each metric (likes, comments, shares, impressions,
reach, saves, clicks, bookmarks, linkClicks, profileVisits, follows,
watchTimeSeconds) with whether it was measured (a 0 the platform
reported vs a field it does not report). The text is current
even if the user edited it in the web composer (editUrl; mediaUrl
and settingsUrl open its media picker and platform settings).
mediaUrls are library files: create_post(media_urls=...) reuses them
to repost on another account. Per-day history is get_performance(post_id=...).
approval (approval workspaces): state, decidedBy, decidedAt, and
requestedFor while pending. A draft with state changes_requested was
sent back: make the change its note asks, then schedule_post it again.
post_ids reads up to 25 posts in one call: posts has one entry per id,
each this shape or that id's error; with include_comments, up to 5.
Args:
post_id: The post ID.
workspace_id: Workspace ID or name. Optional if user has only one workspace.
include_comments: Published posts only: add comments, the latest 20
read live from the network (newest first, replies one level
deep, each with the id reply_to_comment takes), and
commentReply (whether this network takes replies). A network
that shares no comments answers commentsUnavailable instead;
commentsNote says the list misses older replies (X: 7 days).
post_ids: Several posts to read at once, instead of post_id.
Inputs: context, post_id, post_ids, llm_model, +3 more. Returns: _mcp_instructions
get_post_contextARead-onlyInspect
The drafting bundle for one account, or several: workspace, account, and the account's recent posts.
workspace: name, website, logoUrl (the brand logo, for visuals), brandVersion, timezone, preferredTimes, tagOutboundLinks.account: id, name, handle, token health,postsLeftTodayandnextFreeAt(room left and the earliest time a post fits: no need to count recent posts; they hold the owner's own per-account limit when lower,limitSource: "owner"),dailyPostCap(posts per rolling 24h on the owner's plan, scheduled ones included), with posting slots itsqueue(slots, taken, how many more posts fit in the next 7 days,nextFree), for Pinterest itsboards, for Slack itsslackChannelsanddefaultSlackChannel, for InstagramrecentTags(handles it tagged).recentPosts: up to 15 of the account's published posts with their metrics. They are the account's voice. Empty means no history.performance: what performed, from Antwork's measured metrics over 90 days:topPosts(posts published through Antwork, best first byrankedBy, the metric that matters on that platform: saves on Instagram, link clicks on Pinterest, watch time on YouTube...) andfollowers(count, change). Lean on what the top posts share (topic, hook, format) when choosing what to write. Absent when nothing is measured yet.
Args:
platform: "linkedin", "x", "facebook", "instagram", "threads",
"tiktok", "youtube", "pinterest", "bluesky", "discord", "mastodon",
"telegram", "google_business" or "slack". Implied by account_id.
With neither, the error lists the connected platforms and accounts.
account_ids: Several accounts at once (one post per account): an accounts
list, each with its own recent posts (fewer per account).
Overrides platform / account_id.
account_id: One account. Needed when the platform has several:
otherwise error: "account_ambiguous" lists them.
workspace_id: Workspace ID or name. Optional if user has only one
workspace.
routine_id: Run an Autopilot routine the user saved in Antwork (a scheduled
task's prompt names it). Adds routine: its brief, mode, post
limit, what is already queued and instructions to follow. With no
account named, reads the routine's accounts.
Inputs: context, platform, llm_model, account_id, +4 more. Returns: _mcp_instructions
list_mediaARead-onlyInspect
The workspace media library: images, videos and PDFs, with URLs to attach.
libraryUrl is the library page in the web app. nextCursor, when not
null, is passed back as cursor for the next page.
Args:
media_type: "image", "video", "document" (PDFs), or omitted for all.
limit: Max items per page (default 30, max 100).
workspace_id: Workspace ID or name. Optional if user has only one workspace.
cursor: nextCursor from the previous page.
Inputs: limit, cursor, context, llm_model, +3 more. Returns: _mcp_instructions
list_postsARead-onlyInspect
List the workspace's posts, optionally filtered, or laid out by day.
Not needed to find duplicates before drafting: create_post answers
similarRecent for that. Pages run newest scheduled time first; each is
sorted scheduled (soonest first), then draft, published, failed. hasMore
means more posts: pass nextCursor back as cursor.
get_post(post_id) returns one in full. A draft whose
approval.state is changes_requested carries the reviewer's note. group_by_day=true is the
calendar view: calendar maps each date (YYYY-MM-DD) to that day's posts
by time, calendarUrl is the calendar page, and the range defaults to the
Monday of this week through 30 days ahead.
Args:
status: "draft", "scheduled", "published", "failed", or "pending_approval" (waiting for a person to approve).
query: Keyword matched against post text, case-insensitive.
platform: e.g. "linkedin", "x".
campaign_id: Only the versions of one post (its campaignId from create_post with posts).
date_from: Scheduled on or after this date (ISO 8601, e.g. "2026-03-01").
date_to: Scheduled on or before this date (ISO 8601).
limit: Max posts to return (default 50, max 50). Ignored by group_by_day.
group_by_day: Group the posts by date instead of listing them.
workspace_id: Workspace ID or name. Optional if user has only one workspace.
recurring: Instead, the repeating and evergreen posts (set with update_post's repeat / evergreen): rule, next time, posts made, last skip.
attention: Instead, what needs the user, in one call: failed (last three days, with advice), pendingApproval, drafts (stale, mediaRequired) and upcoming, five each, with attentionCounts.
cursor: nextCursor from the previous page, with the same filters.
Inputs: limit, query, cursor, status, +11 more. Returns: _mcp_instructions
list_social_accountsARead-onlyInspect
The workspace's connected social accounts: the ids account_id takes.
One entry per active connection: id, platform, name, handle, token health
and a reauthUrl that refreshes its OAuth token. platformHold (with
advice) means the platform is holding a working connection, e.g. an
Instagram checkpoint: its posts fail until the owner acts in the
platform's app, and reconnecting does not help. Accounts waiting on
payment are listed apart in pendingPaymentAccounts. Connecting a new
account is get_connection_urls.
followers is the latest daily count (count, asOf) and its net
change since changeSince over the last 30 days; a null count comes
with a state/reason (e.g. awaiting_permission), never a 0.
connectAttempts: the last day's latest connect per platform (outcome, reason, nextStep).
Args: workspace_id: Workspace ID or name. Optional if user has only one workspace.
Inputs: context, llm_model, workspace_id, conversation_id. Returns: _mcp_instructions
list_workspacesBRead-onlyInspect
The user's workspaces, their Antwork account (plan, post quota), and the active workspace's connected accounts.
isDefault marks the workspace every tool uses when workspace_id is
omitted. isOwner: false is a workspace the user was invited to; its
owner pays for its accounts. account.quota.posts.remaining is what the
plan still allows this cycle.
account.billing.billingUrl is the page where the plan is changed or
cancelled. foundingOffer is a discount (percentOff off the first year
of a yearly plan) that ends at endsAt; unlimitedPostsUntil is the
date after which Free allows postsPerMonthAfter posts a month. A
comped account is free and has nothing to change. account.trialNotice
appears in a trial's last days and the week after: state (ending or
ended), the plan tried, endsAt, and free, what the Free plan
keeps.
Inputs: context, llm_model, conversation_id. Returns: _mcp_instructions
manage_routineADestructiveInspect
Autopilot: routines your AI runs on a schedule (e.g. "every Monday at 9, write 2 posts about X and schedule them").
action: list | get | create | update | pause | resume | delete | run_now.
create needs name, brief (what each run posts), account_ids, cadence and
mode; update takes any of them. Every answer carries the routine's
sentence (read it back to the user), setup and autopilotUrl.
Who starts each run (trigger.kind):
own_scheduler (default): the AI's own scheduled task runs it. Put
setup.promptin a recurring task on the cadence (ChatGPT Tasks, Grok Automations, Claude Code /schedule…);setup.stepssays where.claude_routine: Antwork starts the user's Claude routine. Needs its
fire_urlandtoken, which only the user can create (claude.ai/code/routines → Add trigger → API → Generate token). That Claude routine needs the Antwork connector andsetup.promptas its prompt.chatgpt_events: Antwork sends
routine.due; subscribe to it in this chat withsetup.prompt.webhook:
routine.dueto the workspace's webhook endpoints (paid plans).
Args: routine_id: For every action but list and create. cadence: {"kind": "weekly", "days": [1..7] (1 = Monday), "time": "09:00", "timezone": "Europe/Madrid"} or {"kind": "every_n_days", "every_days": 2, "time", "timezone"}. mode: "draft" (drafts for the user's approval), "schedule" or "publish". max_posts_per_run: Most posts one run may make (default 3). trigger: {"kind": ..., "fire_url"?, "token"?}. Omit to keep the current one. workspace_id: Workspace ID or name. Optional if user has only one workspace.
Inputs: action (required), mode, name, brief, +9 more. Returns: _mcp_instructions
publish_postADestructiveInspect
Publish one post, several, or every version of one now, and wait for the platforms to answer (about half a minute).
A post whose earlier publish failed is retried (requeued about a minute
out, retried: true). Every post first passes the same checks: character
limit, required media and settings, a connected account. One post answers
with its live url; several come back per post in posts with
publishedCount, and a post that cannot go is reported on its own while
the rest still publish (at most 10 per call). Still processing answers
pending with checkAfterSeconds: one get_post after it, no polling. A TikTok post answers
tiktok_choices_needed until the user has answered each choice; never
answer for them.
Args:
post_ids: The posts to publish.
campaign_id: Every version of one post (its campaignId from create_post) instead.
post_id: One post; the same as post_ids=[post_id].
workspace_id: Workspace ID or name. Optional if user has only one workspace.
tiktok_settings: A TikTok post's settings, as the user answered the
tiktokChoices a first call returned: {privacyLevel, allowComment,
allowDuet, allowStitch, commercialContent: {enabled, yourBrand,
brandedContent}, userConsented: true}, or {useLast: true,
userConsented: true} once the user said yes to the lastUsed
settings offered. Keyed by post id for several posts; a flat
useLast applies to every TikTok post in the call. Only the user's
own answers for this post.
routine_id: The Autopilot routine this run is for: its mode decides whether it may schedule or publish.
Inputs: context, post_id, post_ids, llm_model, +5 more. Returns: _mcp_instructions
reply_to_commentAInspect
Reply, in public and at once, to a comment on a published post, as the account that posted it.
Only after the user approved this exact text. Comment ids come from
get_post(post_id, include_comments=True); without comment_id it is a
comment on the post itself, e.g. a link under the user's own post. On Mastodon start the text with the comment's
mention so its author is notified. Held to the network's character
limit. X, Mastodon, Bluesky and LinkedIn company pages take replies;
other networks answer comments_unsupported with the reason.
Args: post_id: The published post the comment is on. text: The reply, exactly as the user approved it. comment_id: The comment to answer. Omit to reply to the post. workspace_id: Workspace ID or name. Optional if user has only one workspace.
Inputs: text (required), post_id (required), context, llm_model, +3 more. Returns: _mcp_instructions
report_issueAInspect
Report what looks like an Antwork defect to the Antwork team, who read every report.
For a result that contradicts what the call said it did, a user saying
something did not happen, or a failure with no reason given. Not for a
refusal that explains itself (limits, media_required, plan, reconnect).
The calls made before it are attached by Antwork; describe what you saw.
Args: what_happened: What went wrong, in plain words, with any error text seen. expected: What should have happened instead. tool_name: The Antwork tool that misbehaved, if one did. post_id: The post involved, if any. workspace_id: Workspace ID or name, if one was involved.
Inputs: what_happened (required), context, post_id, expected, +4 more. Returns: _mcp_instructions
schedule_postADestructiveInspect
Schedule one post, several, or every version of one to publish automatically at scheduled_for.
Every post first passes the same checks as publish_post. Several posts
come back per post in posts with scheduledCount; one that cannot be
scheduled is reported on its own and the rest still go (at most 10 per
call). schedules gives up to 25 posts each its own time in one call;
next_slot gives each post its account's next free posting slot in turn. A
cadence the user asks for ("3 a day", "an hour apart") is set once with
update_workspace(account_posting=...), and every send then holds it.
Args:
scheduled_for: ISO 8601 datetime (e.g. "2026-04-01T10:00:00Z"), in the future (Free: up to 30 days ahead; paid plans: any time); or "next_slot": the account's next free posting slot (posting.slots, shown by get_post_context), named in the answer's slot (no slots: the soonest allowed time, slotFallback).
post_ids: The posts to schedule.
campaign_id: Every version of one post (its campaignId from create_post) instead.
post_id: One post; the same as post_ids=[post_id].
workspace_id: Workspace ID or name. Optional if user has only one workspace.
tiktok_settings: As publish_post's.
schedules: Instead of the above: [{post_id, scheduled_for, tiktok_settings?}], each scheduled as a one-post call, in order.
routine_id: The Autopilot routine this run is for: its mode decides whether it may schedule or publish.
Inputs: context, post_id, post_ids, llm_model, +7 more. Returns: _mcp_instructions
set_default_workspaceAIdempotentInspect
Set (or clear) the workspace every tool uses when workspace_id is omitted.
The default lives on the user's account, so it holds across conversations
and clients; an explicit workspace_id on a call still overrides it. The
result carries the workspace's connected accounts.
Args: workspace_id: Workspace ID or name. Null or empty clears the default.
Inputs: context, llm_model, workspace_id, conversation_id. Returns: _mcp_instructions
update_postADestructiveInspect
Change a draft or scheduled post; returns it as saved, with its links.
On a published post, text alone changes the live post on LinkedIn,
Facebook, Mastodon, Telegram, Discord, Google Business Profile, Pinterest
and Slack (needs the publish scope). People already see it: show the user
the new text and get their yes first. Other platforms cannot edit a live post.
account_id moves the post to another account (its platform follows).
The same idea on another account with its own copy is a new draft.
post_ids makes the same change on up to 50 posts in one call (e.g.
status: "draft" unschedules them all): only status, hashtags, goal,
campaign_id, pinterest_board_id, slack_channel and platform_options; each post answers
in posts, and one that fails does not stop the rest. updates changes
up to 50 posts each its own way (new text, a new time) in one call; to
schedule drafts each at its own time, schedule_post(schedules=...).
Args:
post_id: The post ID to update.
text: New post text.
account_id: A different social account id to publish to.
hashtags: Appended to the text as #tags, counted in its limit (YouTube: video tags, unless platform_options.tags). A list, or a string split on commas (on spaces if it has none).
goal: Updated goal.
status: "draft" or "scheduled". "draft" on a scheduled post unschedules it. "scheduled" sends it as schedule_post does (approval workspaces: pending_approval), so only once the user approved it; to propose a time, send scheduled_for alone.
scheduled_for: ISO 8601 datetime. On a draft it only proposes the time (it stays a draft); it moves a scheduled post, or schedules with status "scheduled", which needs the publish scope.
campaign_id: Grouping id shared by related drafts.
pinterest_board_id: Pinterest only, an id from boards in get_post_context.
slack_channel: Slack only, a channel id or #name from slackChannels in get_post_context.
platform_options: Settings to change, merged into the post's own (keys as in create_post); null resets one to the platform default. Pinterest also takes newBoardName, which creates that board and sets it. TikTok settings are set by the user at settingsUrl.
workspace_id: Workspace ID or name. Optional if user has only one workspace.
post_ids: Several posts to change the same way, instead of post_id.
repeat: Make a scheduled or published post again on a rhythm: {"every": 2, "unit": "week", "count"?: 5, "until"?: ISO}. "pause", "resume" or "stop" change an existing repeat or evergreen post. Paid plans; not TikTok. Each post made goes through every scheduling check; a refused one is skipped (lastSkip).
evergreen: true puts the post in its account's evergreen queue, re-sent into empty posting slots (posting.slots), least recently sent first; false takes it out.
evergreen_per_week: Evergreen posts per week on that account (default 3).
variants: Alternate texts rotated per repeat, so X and Threads' duplicate rule does not skip them.
updates: One entry per post instead of post_id/post_ids: {post_id, text?, scheduled_for?, account_id?, hashtags?, goal?, status?, campaign_id?, pinterest_board_id?, slack_channel?, platform_options?}, each checked as a one-post call; no repeat or evergreen.
Inputs: goal, text, repeat, status, +17 more. Returns: _mcp_instructions
update_workspaceADestructiveInspect
Update the workspace's identity (name, website, logo), its settings, or its accounts' posting rules.
Only the fields passed change. The result's workspace is the workspace
as saved, settings included; accountPosting the accounts' rules as saved.
Args:
name: The workspace / brand name (60 characters max).
website: Brand website URL.
logo_url: URL to the brand logo image.
timezone: IANA timezone for scheduling, e.g. "Europe/Madrid".
preferred_times: Preferred posting times as HH:MM, e.g. ["09:00", "18:00"].
tag_outbound_links: Append UTM parameters to links on the workspace's own
website when a post publishes, so clicks stop reading as "direct"
traffic. Needs website set; no other site's links are touched.
account_posting: Per account id, the user's own posting rules, only
when the user asks; a limit they state for posting ("at most 4 a
day", "30 minutes apart") lives here, held on every send rather
than counted by hand: {maxPostsPerDay, minGapMinutes, timezone, slots:
[{day: 1-7 (Monday=1), time: "HH:MM"}]}; null removes one. Enforced
like the platform caps (account_limit_reached); slots are what
schedule_post(scheduled_for="next_slot") fills.
workspace_id: Workspace ID or name. Optional if user has only one workspace.
Inputs: name, context, website, logo_url, +7 more. Returns: _mcp_instructions
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
Related MCP Connectors
Draft, schedule and publish social media posts from your AI assistant.
Draft, schedule and publish social media posts to 12 networks from your AI assistant.
Draft, schedule and publish social media posts from AI agents, under workspace approval rules.
Draft, schedule and publish social media posts from any AI agent.
Related MCP Servers
- AlicenseAqualityBmaintenanceOfficial MCP server for PostEverywhere (posteverywhere.ai/social-media-scheduler). Let Claude, ChatGPT, Cursor or any MCP client schedule and publish posts to 13 platforms: Instagram, TikTok, YouTube, LinkedIn, Facebook, X, Threads, Pinterest, Bluesky, Telegram, Discord, WordPress and Google Business Profile. 40 tools: best-time scheduling, threads, cross-posting, campaigns, analytics.33242 npm7MIT
- AlicenseNot gradedqualityCmaintenanceEnables AI assistants to draft, schedule, and publish social media content, generate AI text and image variations, analyze performance, and automate social workflows.MIT

PostMCP MCP Serverofficial
AlicenseAqualityBmaintenanceEnables AI assistants to manage social media publishing across platforms like LinkedIn, Twitter, Facebook, Instagram, Threads, and Bluesky.748 npmMIT- AlicenseNot gradedqualityCmaintenanceSocial media scheduling and publishing for AI agents. 17 validation-first tools to post to X, LinkedIn, Instagram, TikTok, YouTube, Reddit, Discord, Telegram, and more through one connected workspace.187 npm106MIT
Glama MCP Gateway
Add one secure layer between your agents and this server.