MCP server for the PostFast API — schedule and manage social media posts via AI tools
PostFast MCP demonstrates solid definition quality with consistent naming conventions, comprehensive descriptions, and well-structured schemas. All 17 tools follow verb-noun naming patterns (list_*, get_*, create_*, search_*, set_*, reply_*, send_*, mark_*, assign_*). Descriptions are detailed and actionable, averaging 180-250 characters, within the 10-1024 character baseline and well above the 194-char production average. All parameters have type definitions and descriptions. However, output schemas are not explicitly documented in the tool definitions (only documented in prose descriptions), and error handling lacks structured recovery guidance. The server properly uses tool annotations (readOnlyHint, destructiveHint) and declares data contracts in descriptions. Most parameters are well-constrained with enums (platforms, statuses, actions) and UUID formats. A few tools accept free-form text (reply text, search query) with only length constraints documented in descriptions rather than enforced via JSON Schema minLength/maxLength. Overall, this is a well-engineered tool catalog that would serve agents reliably, though output schemas and formal error codes would elevate it further.
Assign a conversation to a workspace member (via their userId) — they will see it in their inbox. Pass null assigneeUserId to unassign (returns to the shared inbox). An assigned conversation is visible only to its assignee and workspace admins.
Generate a shareable link for external clients to connect their social accounts to the workspace. Can be scoped to specific platforms and return the user to your own app when done.
Daily follower-count snapshots for one connected account (pass its socialMediaId from list_accounts). Returns currentFollowerCount, delta (current − first snapshot in range), trackingStartedAt (when PostFast began recording this account), and a series of { capturedAt, followerCount } points. All counts are strings (bigint); currentFollowerCount, delta, and trackingStartedAt may be absent until the account has its first snapshot. Optional from/to bound the range (ISO 8601; default last 90 days, capped at 365). Snapshots are forward-only — no data before trackingStartedAt. Coverage: Facebook Pages, Instagram, YouTube, Pinterest, Threads, Bluesky, Telegram, LinkedIn company pages, and TikTok. Not available: X, personal Facebook.
Fetch one inbox conversation by id, including its server-computed reply capability (canReply, maxReplyLength, windowState, disabledReason) — derive reply ability from these fields, never from hardcoded platform rules. postPreview carries the post's caption and, when available, its public permalink — use the permalink to link the user to the post on the platform (null on Instagram for now). Returns null when the conversation does not exist in the workspace.
Output schemas not explicitly declared in tool definitions. Tool descriptions document response fields in prose (e.g. 'Returns currentFollowerCount, delta...'), but no formal outputSchema is present. LLMs cannot parse prose field documentation as reliably as structured JSON Schema. This forces LLMs to infer output structure from descriptions rather than having a machine-readable contract.
Free-form text parameters lack JSON Schema length constraints. reply_to_inbox_item.text and send_inbox_private_reply.text document maxReplyLength and 1,000 bytes in prose descriptions, but JSON Schema constraints (minLength/maxLength) are not visible. Constraints should be enforced at the schema level, not just documented.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | C | 69 | 2025-06-18+ | v2 |
| 2026-03-09 | C | 60 | - | v1 |
Total unread comment count across all inbox conversations in the workspace (the sum of per-conversation unreadCount). Use mark_inbox_conversation_read after presenting a conversation to the user.
List all social media accounts connected to the workspace. Each account includes connectionStatus (CONNECTED or DISABLED) and disabledReason (null unless DISABLED), plus followerCount (latest stored snapshot, a string; absent for platforms without follower data), followerCountUpdatedAt, and inboxCapable (whether the account can appear in the social inbox, i.e. comment ingestion is supported). A DISABLED account will not publish until the user reconnects it — pre-check before scheduling. For a follower trend over time, use get_follower_history.
List Google Business Profile locations for a connected GBP account (pass its socialMediaId). Use a returned location's locationId field as controls.gbpLocationId in create_posts.
List comment conversations from the social inbox — comments on your connected accounts' posts, grouped per post, newest activity first. Covers TikTok, Instagram, Facebook Pages, and Threads; an account's inboxCapable flag (from list_accounts) tells you whether comments can flow for it today. Comments arrive within seconds of being posted and only from connect/launch onward (no history backfill). Each conversation carries a server-computed reply capability — canReply, maxReplyLength, windowState, disabledReason — plus unreadCount, status (OPEN | SNOOZED | CLOSED), and assignedToUserId. ALWAYS derive whether and how long you can reply from those fields; never assume platform rules. postPreview carries the post's caption and, when available, its public permalink — use the permalink to link the user to the post on the platform (null on Instagram for now).
List the items of one inbox conversation — the comments and the replies sent to them — oldest first by default (order=DESC for newest first). Items carry direction (INBOUND | OUTBOUND), state (VISIBLE | HIDDEN | DELETED), author info, and on Instagram comments canPrivateReply (eligibility for send_inbox_private_reply). Replies sent from PostFast appear exactly once — no duplicates when the platform reports them back.
List Pinterest boards for a connected Pinterest account (pass its socialMediaId). Use a returned board's boardId field as controls.pinterestBoardId in create_posts.
List YouTube playlists for a connected YouTube account (pass its socialMediaId). Use a returned playlist's playlistId field as controls.youtubePlaylistId in create_posts.
Mark one conversation read (zeroes its unreadCount). Do this after presenting a conversation's comments to the user. Internal to PostFast — nothing changes on the platform.
Reply publicly UNDER a specific comment — pass the comment item's id (from list_inbox_items), not the conversation id. BEFORE replying, check the conversation's canReply and maxReplyLength and stay within them; the caps are per platform (TikTok 1,200, Instagram 2,200, Facebook 8,000, Threads 500 characters) but the server-computed fields are authoritative — never assume. Failures return inbox.* codes (e.g. replyTooLong, replyNotSupported, rateLimited).
Search for a place to geotag a post. Pass free text (min 2 chars, e.g. a venue name or address); returns matching places, each with an id that works as BOTH controls.facebookPlaceId (Facebook feed posts) and controls.instagramLocationId (Instagram single-media posts). Only Facebook Pages that carry location data are returned.
Instagram only: send ONE private reply to a comment — it arrives as a direct message to the commenter and may land in their Message Requests folder. Allowed once per comment, within 7 days of the comment, up to 1,000 bytes (emoji and non-Latin text count multi-byte — roughly 1,000 characters, less with emoji). Check the item's canPrivateReply first (from list_inbox_items). A second attempt on the same comment fails with inbox.privateReplyAlreadySent; other failures include privateReplyWindowExpired and privateReplyNotSupported.
Triage a conversation: set its status to OPEN (returned to active), SNOOZED (out of sight, e.g., you are awaiting a response), or CLOSED (archived but still queryable). Internal to PostFast — nothing changes on the platform.
Moderate a comment on the platform: HIDE hides it from the public, UNHIDE restores it, DELETE removes the comment on the platform — cannot be undone. HIDE/UNHIDE work on TikTok, Instagram, Facebook, and Threads; DELETE is not supported on Threads (inbox.deleteNotSupported). State changes made on the platform itself sync back to the inbox automatically.
Error handling lacks structured error codes and recovery guidance. Tool descriptions mention failure modes (e.g. 'inbox.replyTooLong', 'inbox.privateReplyAlreadySent'), but there is no documented error classification (retryable vs user-fixable vs fatal) or standardized error response format that agents can parse programmatically.
Irreversible operations (set_inbox_item_state DELETE, reply_to_inbox_item public posts) lack confirmation or dry-run support. These tools can permanently delete comments or post public replies that cannot be undone. Agents should be required to confirm before executing.
generate_connect_link accepts email as a parameter when sendEmail=true, but no validation or permission check is visible. Sending links to arbitrary email addresses could enable unauthorized account connections. Server-side validation is critical.