auth_status
Check authentication status, API configuration, and workspace information
Publish to every connected social profile in one call, schedule a brand's posts on weekly timeslots, answer comments, reviews and DMs, and manage a WhatsApp Business account and a Google Business listing.
LABSCO SUMMARY
Removing a post from the platforms names the networks it covers and states which ones it cannot reach; comments can be hidden on some networks and liked on only one; message editing is Telegram-only, reactions are Meta-only, chat archiving is Bluesky-only. Two timing rules are worth planning around rather than discovering: a scheduled post can only be updated while it is still comfortably ahead of its publish time, and a Meta private reply is one per comment, ever. The stats are equally plain about their resolution — profile snapshots are roughly daily, and the fields inside them are platform-native rather than normalised.
A multi-network social publishing and inbox client: profiles and profile groups, posts with scheduling and queues, comment moderation, Google Business reviews, direct messages, and per-post and per-profile stats. It also manages a WhatsApp Business account and edits a business's Google listing: hours, menus, photos. An interactive setup command registers it for you if you would rather not edit config by hand.
A Postproxy account and its API key in POSTPROXY_API_KEY, with POSTPROXY_BASE_URL pointing at the API. A social profile connected into a profile group before anything can be posted — the connect tool returns the URL the user opens to finish it, with Bluesky taking an identifier and an app password and Telegram taking a bot token. A placement id where the network has one: profile stats require it for Facebook, LinkedIn and Telegram, and Telegram and Pinterest posts fail without one.
One command plus a key — npm install -g postproxy-mcp, then supply credentials
USE CASES
Publish to the whole profile list in a single call, with per-network overrides where the copy or the media has to differ.
List recent post jobs with their status, then the comments and the DM chats, to see what published, what failed and what is waiting on a reply.
Define the recurring timeslots once, then queue posts into them — and ask for the next opening rather than picking a time.
Generate the connect URL for the user to complete, then check which placements that profile can actually post to.
Read the thread, reply where it helps, hide what does not, and take a conversation private when it should not be public.
List the reviews on the location and post replies — the review itself is never yours to delete, only your reply.
List the chats by recent activity, read a conversation, and send the reply as text or a single attachment.
Pull every stats snapshot across the period rather than a single number, and put follower growth beside it.
Listed in project code.
auth_statusCheck authentication status, API configuration, and workspace information
summary_getAnswer "what's the status?" in one call. Returns an activity snapshot for a time window: posts published and failed (plus what's scheduled next), engagement totals summed from each post's latest stats snapshot, comments and reviews received, and DM volume — each broken down per network. Also returns what's still waiting on you: comments and reviews with no reply from you, and DM chats whose newest message is inbound (with how many are about to run out of their 24h messaging window). Prefer this over calling history_list / comments_list / dm_chats_list separately. Two quirks worth knowing: engagement is lifetime-to-date for posts published in the window rather than engagement earned during it, and the awaiting_reply counts describe current state so they don't change with the window (they look back 30 days, returned as window.backlog_from). Post counts are posts — a post sent to three networks counts once — while by_platform counts per-network deliveries. engagement is null when insights are off for the account, dms when DMs are.
profile_groups_listList all profile groups accessible with your API key. Profile groups are organizational containers (e.g. per brand or client) that hold related social media profiles. Use the returned group id to filter profiles_list by profile_group_id.
profile_groups_initialize_connectionGenerate a URL to connect a new social media profile to a profile group (initiates the OAuth/connect flow). For bluesky, pass identifier + app_password. For telegram, pass bot_token. For whatsapp, optionally pass onboarding ('api' or 'business_app'); when omitted the connect page asks the user where their number lives. The returned URL should be opened by the user to complete the connection.
profiles_listList all available social media profiles for posting. Optionally filter by profile_group_id.
upload_createCreate a temporary file upload URL for sandboxed environments. Returns a key, an upload_url, and expires_in (seconds). Flow: (1) call this tool, (2) POST the raw file bytes to the returned upload_url (valid for expires_in seconds), which responds with {"url": "https://..."}, (3) pass that returned url in the media array of post_publish (or post_update). The upload host is tmpfiles.postproxy.dev — that domain must be whitelisted/allowlisted in the sandbox's network egress rules for the upload to succeed. Only use this when running against the remote (hosted) MCP server: if you are running the local (stdio) MCP server, do NOT use this — instead pass local file paths directly in the media array, which uploads them via multipart.
post_publishPublish a post to specified social media profiles. Supports text content, media attachments, scheduling, drafts, threads (X and Threads only), and platform-specific customization via the 'platforms' parameter.
post_statusGet status of a post by post ID. Returns the full content, scheduled_at (null if not scheduled), created_at, draft flag, internal status, per-platform status with published URLs, and media details
post_publish_draftPublish a draft post. Only posts with draft status can be published using this endpoint
post_updateUpdate an existing post. Only drafts or scheduled posts (more than 5 min before publish) can be updated. Only send fields you want to change — omitted fields are left unchanged.
post_deleteDelete a post from the database. By default does NOT remove from social media platforms. Pass delete_on_platform=true to also remove from all published platforms before DB deletion.
post_delete_on_platformDelete a published post from social media platforms WITHOUT removing it from the database. Async via background job. Optionally narrow scope by post_profile_id (covers entire thread for that profile), profile_id, or network. With no scope, deletes from all published platforms. Supported: Facebook, Threads, X (Twitter), LinkedIn, Pinterest, YouTube. NOT supported: Instagram, TikTok.
history_listList recent post jobs. Each entry includes the full content, created_at, scheduled_at (null if not scheduled), draft flag, internal status, and the platforms the post targets with their status and published URLs
post_statsGet stats snapshots for one or more posts. Returns all matching snapshots so you can see trends over time. Supports filtering by profiles/networks and timespan.
profiles_placementsList available placements for a profile. For Facebook: business pages. For LinkedIn: personal profile and organizations. For Pinterest: boards. For Telegram: channels the bot can post to. For Google Business: locations (returned as full resource paths 'accounts/X/locations/Y' to pass as location_id). For WhatsApp: the phone numbers on the Business Account — the placement id is the phone_number_id every whatsapp_* tool and dm_chat_create take, and metadata carries display_phone_number, quality_rating, messaging_limit_tier, name_status, platform_type. Available for facebook, linkedin, pinterest, telegram, google_business and whatsapp profiles.
profiles_statsGet the follower/engagement timeseries for a profile. Returns daily snapshots (captured every ~23h). placement_id is required for facebook, linkedin, telegram, and google_business profiles (get it from profiles_placements); omit for other networks. Fields in records[].stats are platform-native and not normalized. For google_business the series is per location: impressions, website clicks, call clicks, direction requests and conversations — there is no follower count.
queues_listList all posting queues. Queues automatically schedule posts into recurring weekly timeslots with priority-based ordering.
queues_getGet details of a single posting queue including its timeslots and post count
queues_createCreate a new posting queue with weekly timeslots. Use profiles.list to find the profile_group_id.
queues_updateUpdate a queue's settings, timeslots, or pause/unpause it. Changes to timezone or timeslots trigger rearrangement of all queued posts.
queues_deleteDelete a posting queue. Posts in the queue will have their queue reference removed but will not be deleted.
queues_next_slotGet the next available timeslot for a queue
comments_listList comments on a published post. Returns paginated top-level comments with nested replies. Optionally filter by when PostProxy received the comment with from/to. Not all platforms support comments.
comments_getGet a single comment with its replies
comments_createCreate a comment or reply on a published post. The comment is published to the platform asynchronously. Supported on Instagram, Facebook, Threads, YouTube, and LinkedIn.
comments_deleteDelete a comment from the platform asynchronously. Supported on Instagram, Facebook, YouTube, and LinkedIn. Not supported on Threads.
comments_editEdit the text of a comment you published, asynchronously. Supported on Facebook and YouTube only. Returns { accepted: true }; the result arrives via comment.edited / comment.edit_failed webhooks.
comments_hideHide a comment on the platform asynchronously. Supported on Instagram, Facebook, and Threads.
comments_unhideUnhide a previously hidden comment on the platform asynchronously. Supported on Instagram, Facebook, and Threads.
comments_likeLike a comment on the platform asynchronously. Currently only supported on Facebook.
comments_unlikeRemove a like from a comment on the platform asynchronously. Currently only supported on Facebook.
profile_comments_listList profile-scoped comments. Currently surfaces Google Business reviews (reviews live on a location, not a post, so they cannot be reached via comments_list). Each item may include nested replies. Reviews sync from Google twice daily (06:00 and 18:00 UTC).
profile_comments_getGet a single profile comment (review or your reply) by Postproxy hashid or the platform's external_id (e.g. 'accounts/.../locations/.../reviews/...').
profile_comments_createReply to an existing profile comment (Google Business review). Top-level comments are NOT allowed — you can only reply to a review that already exists. parent_id is required. Response is returned immediately with status 'pending'; a background job then publishes to Google and updates status to 'published' or 'failed'.
profile_comments_deleteDelete your reply to a profile comment. Only your own reply is removed — the underlying review is NOT deleted (Google does not allow businesses to delete reviews). Returns {accepted: true} while the delete is dispatched asynchronously.
dm_chats_listList direct-message chats (conversations) for a DM-capable profile, ordered by most recent activity. Supported on Facebook (Messenger), Instagram, Telegram, Bluesky, and WhatsApp. WhatsApp chats carry external_placement_id (the phone number), group (true for group chats) and within_messaging_window.
dm_chat_createFind or create a chat for a participant on a DM-capable profile (idempotent — returns the existing chat if one already exists). Use before sending a message to a participant the profile has not yet messaged. On WhatsApp, placement_id (the phone number id from profiles_placements) is required and participant_external_id is the recipient's phone number in international format (digits only, no +); a new WhatsApp conversation must open with an approved template via dm_message_send.
dm_chat_getGet a single chat by Postproxy hashid or by the platform's external_conversation_id.
dm_messages_listList messages in a chat, most recent first. Optionally filter by direction or status. Inbound messages created by a tap on an interactive element you sent (quick reply, button postback, Instagram ice breaker, Telegram callback query) carry tapped_action: {kind, payload, title} — read the payload from there instead of digging through platform_data.
dm_message_sendSend an outbound direct message. Provide EXACTLY ONE of body (text), media (a single attachment), or — on WhatsApp — template, interactive, location or contacts. The message is queued and delivered asynchronously (returns status: pending). Outside Meta's 24h messaging window, a human agent replying to the participant's own inquiry can pass tag: HUMAN_AGENT (Facebook/Instagram only) — never for promotional or automated content. On WhatsApp the window is re-opened only by sending an approved template (or a text with category: utility); free-form sends outside it return 422. reply_markup is Telegram-only; reply_to_external_id works on Telegram and WhatsApp; quick_replies, buttons and card are the Facebook/Instagram interactive primitives and are rejected elsewhere — WhatsApp uses interactive (Meta-shaped) instead.
dm_message_getGet a single message by Postproxy hashid or by the platform's external_id. Outbound messages echo the quick_replies / buttons / card they were sent with; an inbound message created by a tap carries tapped_action: {kind, payload, title}.
dm_message_editEdit a previously-sent outbound message on the platform. Telegram only — Facebook and Instagram do not expose outbound edits, so Meta quick_replies and buttons cannot be changed after sending. Provide body (new text/caption) and/or reply_markup (pass {} to clear the keyboard); at least one is required.
dm_message_reactAdd a reaction from your business account to a message. Facebook Messenger, Instagram Direct and WhatsApp (not Telegram or Bluesky). On WhatsApp pass emoji — any unicode emoji — and reaction names are ignored. A second react replaces the previous one.
dm_message_unreactRemove your business account's reaction from a message. Facebook Messenger, Instagram Direct and WhatsApp only.
dm_chat_archiveArchive (mute) a chat. Bluesky only — calls Bluesky's muteConvo. Returns the chat with archived: true.
dm_chat_unarchiveUnarchive (unmute) a chat. Bluesky only — calls Bluesky's unmuteConvo. Returns the chat with archived: false.
dm_chat_mark_readMark a chat as read. On WhatsApp this sends the read receipt (blue ticks) for the newest inbound message to the participant; on other networks it only stamps metadata.read_at locally. Returns the chat.
dm_comment_private_replySend a DM to the author of a comment, in reply to that comment (Meta 'Private Replies'). Bypasses the 24h window (comments up to 7 days old) and creates/reuses a chat automatically. One private reply per comment, ever. Instagram and Facebook (Page comments) only. Supports the same quick_replies / buttons / card interactive elements as dm_message_send; media attachments are not available on private replies.
google_business_location_getRead a Google Business Profile location — name, description, website, phones, categories, address, hours, service area, service items, and metadata. This is the business listing itself, not posts published to it. Read this before any google_business_*_update: Google's updates are field-masked, so you patch back objects you fetched here.
google_business_location_updateUpdate fields on a Google Business Profile location. fields names exactly what you're replacing — anything named there but missing from the payload is CLEARED, and nested objects are replaced wholesale, not merged. Read with google_business_location_get first. Hours and the service list have their own tools.
google_business_categories_listResolve Google business category resource names (e.g. 'categories/gcid:software_company') for a region. Category patches need these resource names, not display names, and the available set differs per country. Use filter to search by display name rather than paging thousands of results.
google_business_hours_updateSet opening hours on a Google Business Profile location. Times accept either "09:00"/"09:00:00" strings or Google's { hours, minutes } objects. Read current hours from google_business_location_get — each block you name in fields is replaced entirely.
google_business_attributes_getRead the attributes currently set on a Google Business Profile location (payments, accessibility, service options, social links). Note Google omits the attributes key entirely when none are set rather than returning an empty array.
google_business_attributes_availableList which attributes a location can actually set, with their value types. Valid attributes depend on the primary category and region, so ALWAYS call this before google_business_attributes_update. Two modes: by location (the default — omit region_code and language_code, Google takes them from the listing) or by category_name (then region_code is required).
google_business_attributes_updateSet attributes on a Google Business Profile location. Value shape depends on the attribute's valueType from google_business_attributes_available: BOOL uses "values": [true], URL uses "uriValues": [{ "uri": "..." }], ENUM uses "repeatedEnumValue": { "setValues": ["TOKEN"] }. attribute_mask defaults to exactly the names you send, so untouched attributes are preserved.
google_business_service_list_getRead the services offered by a Google Business Profile location. Editable only when the location's metadata.canModifyServiceList is true.
google_business_service_list_updateReplace the service list on a Google Business Profile location. This is a full replacement, not a merge — send the complete list. Items are either { structuredServiceItem: { serviceTypeId } } using a serviceTypeId from the location's category, or { freeFormServiceItem: { category, label: { displayName, languageCode } } }. Fails with 422 when metadata.canModifyServiceList is false.
google_business_food_menus_getRead food menus for a Google Business Profile location. Restaurant-like categories only — other locations return 422 with FAILED_PRECONDITION, which is expected rather than an error to retry.
google_business_food_menus_updateReplace the food menus on a Google Business Profile location. Full replacement, not a merge. Structure is menu -> sections -> items; every label carries a languageCode and prices need currencyCode and units. Requires metadata.canHaveFoodMenus on the location, otherwise 422.
google_business_place_action_links_listList the action links on a Google Business Profile location — the 'Book online', 'Order online' and similar buttons. Google omits the placeActionLinks key entirely when there are none.
google_business_place_action_link_createAdd an action button to a Google Business Profile location. Which place_action_type values a location accepts varies by category. Google keys the link off (location, uri, placeActionType), so creating the same combination twice returns the existing link rather than a duplicate.
google_business_place_action_link_updateUpdate an existing action link on a Google Business Profile location. name is the full resource path from google_business_place_action_links_list and must belong to this location.
google_business_place_action_link_deleteRemove an action link from a Google Business Profile location. The button stops showing on Search and Maps.
google_business_media_listList the photos and videos on a Google Business Profile location. These are profile photos, distinct from media attached to a local post.
google_business_media_createAdd a photo or video to a Google Business Profile location. Google downloads the file from media_url itself — there is no upload step, so the URL must be publicly reachable https (not a short-lived signed URL, not localhost). Images need at least 250x250 and at most 5MB. Use category COVER or LOGO only when you intend to change the profile header or logo.
google_business_media_deletePermanently remove a photo or video from a Google Business Profile location. media_name is the full resource name from google_business_media_list and must belong to this location.
whatsapp_templates_listList the message templates on a WhatsApp Business Account (the profile) as Postproxy has them synced from Meta. Filter by name, language or status (APPROVED, PENDING, REJECTED, PAUSED, DISABLED). Pass refresh: true to pull Meta's current list first. Only APPROVED templates can be sent; each entry's variable_count is how many values dm_message_send's template.variables must carry.
whatsapp_template_getGet one WhatsApp message template with its components (header, body, footer, buttons), status, category, parameter_format and variable_count.
whatsapp_template_createSubmit a new WhatsApp message template to Meta for review. Either pass components (custom template: HEADER / BODY / FOOTER / BUTTONS in Meta's shape, with example values for any {{n}} placeholders) or library_template_name to instantiate one of Meta's pre-approved library templates (approved instantly). name must be lowercase letters, digits and underscores; category is UTILITY, MARKETING or AUTHENTICATION. Custom templates come back PENDING — watch the message_template.status_updated webhook or re-list with refresh.
whatsapp_template_updateUpdate a WhatsApp template's components and/or message_send_ttl_seconds. Editing components sends the template back through Meta review (status returns to PENDING). At least one of components / message_send_ttl_seconds is required.
whatsapp_template_deleteDelete a WhatsApp template on Meta and in Postproxy. With language, only that language variant is deleted; addressing by name without language deletes every language of that name. Deleted template names can't be reused for 30 days on Meta.
whatsapp_template_library_getLook up a pre-approved template in Meta's template library by name (e.g. order_confirmation, delivery_update) to see the inputs it needs before creating it with whatsapp_template_create + library_template_name.
whatsapp_number_infoRead the live state of a WhatsApp phone number from Meta: display_phone_number, verified_name, name_status, quality_rating, messaging_limit_tier, throughput, status, platform_type (CLOUD_API vs a coexistence number still in the WhatsApp Business app), plus the Business Account's review and verification status. Also refreshes the placement's stored metadata.
whatsapp_number_registerRegister a phone number with the Cloud API using its 6-digit two-step verification PIN. Postproxy does this automatically on connect with a default PIN; call it when number_info reports a registration_warning or after the PIN changed on the number. Already-registered numbers return already_registered: true.
whatsapp_number_request_verification_codeAsk Meta to send a one-time verification code to a not-yet-verified phone number by SMS or voice call. Follow with whatsapp_number_verify.
whatsapp_number_verifySubmit the one-time code received after whatsapp_number_request_verification_code to verify ownership of the phone number.
whatsapp_business_profile_getRead the public business profile shown in WhatsApp for a phone number: about, address, description, email, websites, vertical and profile_picture_url.
whatsapp_business_profile_updateUpdate the public business profile of a phone number. Send only the fields to change; at least one is required. about max 139 chars, description max 512, websites at most 2 entries. The profile photo has its own tool.
whatsapp_business_profile_photo_updateReplace the profile photo of a phone number. Pass either url (a public https image) or data (base64, with content_type). JPEG or PNG, at most 5MB.
whatsapp_display_name_getRead the verified display name of a phone number and its review status (name_status), plus any pending new_name_status.
whatsapp_display_name_request_changeSubmit a new display name for Meta review. The current name stays until Meta approves; the outcome arrives on the placement.name_status_updated webhook.
whatsapp_username_getRead the WhatsApp username (wa.me/username handle) set on a phone number, if any, and its status.
whatsapp_username_setClaim or change the WhatsApp username of a phone number. Letters, digits, periods and underscores, must contain a letter, no leading / trailing / consecutive periods. Pass transfer_action: force_transfer to move a username already held by another number in the same business.
whatsapp_username_deleteRelease the WhatsApp username set on a phone number.
whatsapp_username_suggestionsGet Meta's available username suggestions for a phone number.
whatsapp_blocked_users_listList the phone numbers (wa_id) blocked on a WhatsApp phone number, paginated with limit / after (next_cursor in the response).
whatsapp_blocked_user_statusCheck whether one phone number is currently blocked on a WhatsApp phone number.
whatsapp_users_blockBlock up to 1000 phone numbers on a WhatsApp phone number so they can no longer message it. Returns succeeded and failed lists.
whatsapp_users_unblockUnblock up to 1000 previously blocked phone numbers on a WhatsApp phone number. Returns succeeded and failed lists.
whatsapp_groups_listList the WhatsApp groups a phone number administers (Groups API — Cloud API numbers only; coexistence numbers can't use it). Paginated with limit / after.
whatsapp_group_createCreate a WhatsApp group administered by the phone number. Returns the group id and invite_link. Add members with whatsapp_group_participants_add or share the invite link.
whatsapp_group_getRead a WhatsApp group: subject, description, join_approval_mode, invite_link, participants, participant_count, created_at, is_suspended.
whatsapp_group_updateChange a WhatsApp group's subject, description and/or join_approval_mode. At least one is required.
whatsapp_group_deleteDelete a WhatsApp group the phone number administers.
whatsapp_group_participants_addAdd up to 8 phone numbers to a WhatsApp group (a group holds 8 participants).
whatsapp_group_participants_removeRemove phone numbers from a WhatsApp group.
whatsapp_group_invite_link_createGenerate a fresh invite link for a WhatsApp group (revokes the previous one).
whatsapp_group_join_requests_listList pending join requests on a WhatsApp group with join_approval_mode approval_required.
whatsapp_group_join_requests_approveApprove pending join requests for the given phone numbers.
whatsapp_group_join_requests_rejectReject pending join requests for the given phone numbers.
whatsapp_dataset_getRead the Conversions API dataset id attached to the WhatsApp Business Account (null when none). Needed for whatsapp_conversion_event_send.
whatsapp_dataset_createCreate a Conversions API dataset on the WhatsApp Business Account so Click-to-WhatsApp ad conversions can be reported. Idempotent: returns the existing dataset with created: false.
whatsapp_conversion_event_sendReport a conversion (LeadSubmitted, Purchase, AddToCart, InitiateCheckout, ViewContent) for a conversation that started from a Click-to-WhatsApp ad, so Meta can attribute it. Identify the conversation by chat_id or phone; it must carry a captured ctwa_clid (422 otherwise). event_id must be unique per event. email and external_id are SHA-256 hashed before sending. Pass test_code to route the event to Meta's test-events view.
BEFORE YOU INSTALL
103 tools registered in the project's code. Version 1.18.1 covers posts, queues, comments, DMs and Google Business review replies. 18 more edit a Google Business listing: hours, menus, photos, attributes, action links. 37 run a WhatsApp Business account: message templates, phone numbers, business profile, username, blocked users, groups.
POSTPROXY_API_KEY in your environment
INSTALLATION
npm install -g postproxy-mcpclaude mcp add --transport stdio postproxy-mcp --env POSTPROXY_API_KEY=<YOUR_POSTPROXY_API_KEY> --env POSTPROXY_BASE_URL=https://api.postproxy.dev/api -- postproxy-mcppostproxy-mcp setup