Skip to main content
Glama

Server Details

Draft, schedule, and publish social posts for your workspace straight from your AI.

Ownership verified
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

A4/5.0

Scored across 24 tools

Disambiguation4/5

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.

Naming Consistency5/5

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.

Tool Count4/5

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.

Completeness4/5

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
Vendor relationship
First-party
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 tools
add_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_mediaA
Destructive
Inspect

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_mediaA
Destructive
Inspect

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_postA
Destructive
Inspect

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_postsA
Read-only
Inspect

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_urlsA
Read-only
Inspect

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_toolsA
Read-onlyIdempotent
Inspect

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_performanceA
Read-only
Inspect

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_postA
Read-only
Inspect

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_contextA
Read-only
Inspect

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, postsLeftToday and nextFreeAt (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 its queue (slots, taken, how many more posts fit in the next 7 days, nextFree), for Pinterest its boards, for Slack its slackChannels and defaultSlackChannel, for Instagram recentTags (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 by rankedBy, the metric that matters on that platform: saves on Instagram, link clicks on Pinterest, watch time on YouTube...) and followers (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_mediaA
Read-only
Inspect

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_postsA
Read-only
Inspect

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_accountsA
Read-only
Inspect

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_workspacesB
Read-only
Inspect

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_routineA
Destructive
Inspect

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.prompt in a recurring task on the cadence (ChatGPT Tasks, Grok Automations, Claude Code /schedule…); setup.steps says where.

  • claude_routine: Antwork starts the user's Claude routine. Needs its fire_url and token, which only the user can create (claude.ai/code/routines → Add trigger → API → Generate token). That Claude routine needs the Antwork connector and setup.prompt as its prompt.

  • chatgpt_events: Antwork sends routine.due; subscribe to it in this chat with setup.prompt.

  • webhook: routine.due to 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_postA
Destructive
Inspect

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_postA
Destructive
Inspect

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_workspaceA
Idempotent
Inspect

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_postA
Destructive
Inspect

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_workspaceA
Destructive
Inspect

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

    Related MCP Servers

    • A
      license
      A
      quality
      B
      maintenance
      Official 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.
      33
      242 npm
      7
      MIT
    • A
      license
      A
      quality
      B
      maintenance
      Enables AI assistants to manage social media publishing across platforms like LinkedIn, Twitter, Facebook, Instagram, Threads, and Bluesky.
      7
      48 npm
      MIT
    • A
      license
      Not graded
      quality
      C
      maintenance
      Social 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 npm
      106
      MIT
    Try in Browser

    Glama MCP Gateway

    Add one secure layer between your agents and this server.