The full upstream README, mirrored here for reference. Install config, tool schemas, adoption signals, and an original overview live on the Postproxy listing page.
MCP (Model Context Protocol) server for integrating Postproxy API with Claude Code. This server provides tools for publishing posts, checking statuses, and managing social media profiles through Claude Code.
Claude Code stores MCP server configuration under ~/.claude/plugins/.
After installing postproxy-mcp, Claude will automatically detect the server on restart.
After installing postproxy-mcp, register it with Claude Code using the claude mcp add command:
Replace your-api-key with your actual Postproxy API key.
The configuration will be automatically saved to ~/.claude/plugins/. After running this command:
For non-technical users, you can use the interactive setup command:
or
This will guide you through the setup process step by step and register the server using claude mcp add automatically.
auth_statusCheck authentication status, API configuration, and workspace information.
Parameters: None
Returns:
summary_getAnswer "what's the status?" in one call — an activity snapshot for a time window instead of separate history_list / comments_list / dm_chats_list round trips.
Parameters:
window (string, optional): 24h (default), 7d, or 30dfrom (string, optional): ISO 8601 timestamp or bare date starting an explicit range. Overrides window, and the *_previous counts come back nullto (string, optional): End of the explicit range. Defaults to now when only from is givenprofile_group_id (string, optional): Report on a single group. Omit to cover every group the key can reachReturns:
Notes:
by_platform counts per-network deliveries, so a 3-item X thread is 3 under twitter.engagement is lifetime-to-date for posts published in the window, not engagement earned during it — it sums each post's newest stats snapshot. A post published minutes ago may have no snapshot yet and won't be in posts_with_insights. Keys are the normalized metrics listed in Stats Fields by Platform.awaiting_reply counts describe current state, not the window — they don't change when you change window. They look back 30 days, returned as window.backlog_from. A comment counts as replied only when the reply came from you (via Postproxy or the profile itself); chats_awaiting_reply is derived from message timestamps, since Postproxy has no read/unread state.reply_window_closing counts chats with under 6 hours of their 24h messaging window left. Networks without a window (Telegram, Bluesky) are excluded.engagement is null when insights are off for the account; dms is null when DMs are off.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 profiles. Use a group's id to filter profiles_list by profile_group_id.
Parameters: None
Returns:
profiles_listList all available social media profiles for posting.
Parameters:
profile_group_id (string, optional): If provided, only profiles in this group are returned (use profile_groups_list to find group IDs)Returns:
profiles_placementsList available placements for a profile. For Facebook profiles, placements are business pages. For LinkedIn profiles, placements include the personal profile and organizations. For Pinterest profiles, placements are boards. For Telegram profiles, placements are channels the bot can post to. For Google Business profiles, placements are locations, returned as full resource paths (accounts/X/locations/Y) to pass as location_id. Available for facebook, linkedin, pinterest, telegram, and google_business profiles.
Parameters:
profile_id (string, required): Profile hashidReturns (LinkedIn example):
Notes:
chat_id is required on every postlocation_id is required on every post and on every google_business_* toolprofiles_statsGet the follower/engagement timeseries for a profile. Snapshots are captured roughly every 23 hours, so you can plot follower growth and other trends over time. The stats fields are platform-native (not normalized) — see Stats Fields by Platform in the post_stats section for shape and add-on profile-level keys (followers_count, followersCount, etc.) per network.
Parameters:
profile_id (string, required): Profile hashidplacement_id (string, conditional): Required for facebook, linkedin, telegram, and google_business profiles. Get it from profiles_placements. Omit for instagram, threads, youtube, twitter, tiktok, pinterest, and bluesky.from (string, optional): ISO 8601 timestamp — only include snapshots recorded at or after this timeto (string, optional): ISO 8601 timestamp — only include snapshots recorded at or before this timeReturns (LinkedIn example):
For non-placement networks (e.g. Bluesky), omit placement_id:
post_publishPublish a post to specified social media profiles.
Parameters:
content (string, required): Post content text
profiles (string[], required): Array of profile IDs (hashids) or platform names (e.g., "linkedin", "instagram", "twitter"). When using platform names, posts to the first connected profile for that platform.
schedule (string, optional): ISO 8601 scheduled time
media (string[], optional): Array of media URLs or local file paths
idempotency_key (string, optional): Idempotency key for deduplication
require_confirmation (boolean, optional): If true, return summary without publishing
draft (boolean, optional): If true, creates a draft post that won't publish automatically
queue_id (string, optional): Queue ID to add the post to. The queue will automatically assign a timeslot. Do not use together with schedule.
queue_priority (string, optional): Priority when adding to a queue: high, medium (default), or low
platforms (object, optional): Platform-specific parameters. Key is platform name (e.g., "instagram", "youtube", "tiktok"), value is object with platform-specific options. See Platform Parameters Reference for full documentation.
Example:
Returns:
Note on draft posts: If you request a draft post (draft: true) but the API returns draft: false, a warning field will be included in the response indicating that the API may have ignored the draft parameter. This can happen if the API does not support drafts with certain parameters (e.g., media attachments) or under specific conditions. Check the warning field in the response for details.
post_statusGet status of a published post by job ID.
Parameters:
post_id (string, required): Post ID from post.publish responseReturns:
scheduled_at is null for posts published immediately. Platform url is the published permalink (null until published).
Status values:
overall_status: "draft", "pending", "processing", "complete", "failed"status: "pending", "processing", "published", "failed", "deleted"error: Error message if publishing failed (null if successful)post_publish_draftPublish a draft post. Only posts with draft: true status can be published using this endpoint.
Parameters:
post_id (string, required): Post ID of the draft post to publishReturns:
post_deleteDelete a post by job ID.
Parameters:
post_id (string, required): Post ID to deleteReturns:
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.
Parameters:
post_ids (string[], required): Array of post hashids (max 50)profiles (string, optional): Comma-separated list of profile hashids or network names (e.g. instagram,twitter or abc123,def456 or mixed)from (string, optional): ISO 8601 timestamp — only include snapshots recorded at or after this timeto (string, optional): ISO 8601 timestamp — only include snapshots recorded at or before this timeReturns:
Stats fields by platform:
| Platform | Fields |
|---|---|
impressions, likes, comments, saved, profile_visits, follows | |
impressions, clicks, likes | |
| Threads | impressions, likes, replies, reposts, quotes, shares |
impressions, likes, retweets, comments, quotes, saved | |
| YouTube | impressions, likes, comments, saved |
impressions | |
| TikTok | impressions, likes, comments, shares |
impressions, likes, comments, saved, outbound_clicks |
Notes: Instagram stories do not return stats. TikTok stats require the post to have a public ID.
queues_listList all posting queues. Queues automatically schedule posts into recurring weekly timeslots with priority-based ordering.
Parameters:
profile_group_id (string, optional): Filter queues by profile groupReturns:
queues_getGet details of a single posting queue including its timeslots and post count.
Parameters:
queue_id (string, required): Queue IDqueues_createCreate a new posting queue with weekly timeslots.
Parameters:
profile_group_id (string, required): Profile group ID to connect the queue to (use profiles_list to find this)name (string, required): Queue namedescription (string, optional): Optional descriptiontimezone (string, optional): IANA timezone name (e.g. America/New_York). Default: UTCjitter (number, optional): Random offset in minutes (0–60) applied to scheduled times for natural posting patterns. Default: 0timeslots (array, optional): Initial weekly timeslots. Each object has day (0=Sunday through 6=Saturday) and time (24-hour HH:MM format)Example:
queues_updateUpdate a queue's settings, timeslots, or pause/unpause it. Changes to timezone or timeslots trigger rearrangement of all queued posts.
Parameters:
queue_id (string, required): Queue ID to updatename (string, optional): New queue namedescription (string, optional): New descriptiontimezone (string, optional): IANA timezone nameenabled (boolean, optional): Set to false to pause the queue, true to unpausejitter (number, optional): Random offset in minutes (0–60)timeslots (array, optional): Timeslots to add or remove. To add: { "day": 1, "time": "09:00" }. To remove: { "id": 42, "_destroy": true }.queues_deleteDelete a posting queue. Posts in the queue will have their queue reference removed but will not be deleted.
Parameters:
queue_id (string, required): Queue ID to deletequeues_next_slotGet the next available timeslot for a queue.
Parameters:
queue_id (string, required): Queue IDReturns:
When publishing a post with post_publish, you can add it to a queue instead of scheduling it manually:
queue_id (string, optional): Queue ID to add the post to. The queue will automatically assign a timeslot. Do not use together with schedule.queue_priority (string, optional): Priority level: high, medium (default), or low. Higher priority posts get earlier timeslots.Example:
comments_listList comments on a published post. Returns paginated top-level comments with nested replies.
Parameters:
post_id (string, required): Post IDprofile_id (string, required): Profile ID to identify which platform's comments to retrievepage (number, optional): Page number, zero-indexed (default: 0)per_page (number, optional): Number of top-level comments per page (default: 20)from (string, optional): ISO 8601 date/time — only comments received at or after this pointto (string, optional): ISO 8601 date/time — only comments received at or before this pointfrom/to filter on when Postproxy received the comment, not the platform's posted_at (which isn't always populated). A bare date such as 2026-03-25 means that date's start of day. The filter applies to top-level comments only — a comment in range still returns its full replies array.
Returns:
Comment objects may also include an attachments array (media on the comment — image, video, audio, gif, external, file), each with id, type, url, status, and external_id. Populated for Facebook, Threads, and Bluesky; Instagram, YouTube, and LinkedIn comments are text-only. The array is empty when there is no media.
comments_getGet a single comment with its replies.
Parameters:
post_id (string, required): Post IDcomment_id (string, required): Comment ID (Postproxy ID or platform external ID)profile_id (string, required): Profile IDcomments_createCreate a comment or reply on a published post. The comment is published to the platform asynchronously.
Parameters:
post_id (string, required): Post IDprofile_id (string, required): Profile IDtext (string, required): Comment text contentparent_id (string, optional): ID of comment to reply to (Postproxy ID or external ID). Omit to comment on the post itself.Returns:
The comment is created with status: "pending". Once published to the platform, it becomes "published". If publishing fails, it becomes "failed".
comments_deleteDelete a comment from the platform asynchronously. Supported on Instagram, Facebook, YouTube, and LinkedIn. Not supported on Threads.
Parameters:
post_id (string, required): Post IDcomment_id (string, required): Comment ID (Postproxy ID or external ID)profile_id (string, required): Profile IDcomments_hideHide a comment on the platform asynchronously. Supported on Instagram, Facebook, and Threads.
Parameters:
post_id (string, required): Post IDcomment_id (string, required): Comment IDprofile_id (string, required): Profile IDcomments_unhideUnhide a previously hidden comment. Supported on Instagram, Facebook, and Threads.
Parameters:
post_id (string, required): Post IDcomment_id (string, required): Comment IDprofile_id (string, required): Profile IDcomments_likeLike a comment on the platform asynchronously. Currently only supported on Facebook.
Parameters:
post_id (string, required): Post IDcomment_id (string, required): Comment IDprofile_id (string, required): Profile IDcomments_unlikeRemove a like from a comment. Currently only supported on Facebook.
Parameters:
post_id (string, required): Post IDcomment_id (string, required): Comment IDprofile_id (string, required): Profile ID| Action | Threads | YouTube | |||
|---|---|---|---|---|---|
| List | Yes | Yes | Yes | Yes | Yes |
| Reply | Yes | Yes | Yes | Yes | Yes |
| Delete | Yes | Yes | No | Yes | Yes |
| Hide/Unhide | Yes | Yes | Yes | No | No |
| Like/Unlike | No | Yes | No | No | No |
1:1 messaging (chats and messages) on DM-capable profiles. Supported on Facebook (Messenger), Instagram (DMs), Telegram (Bot DMs), and Bluesky. Outbound sends are processed asynchronously (returned with status: "pending"). Meta's 24h messaging window applies to Facebook/Instagram — a human replying to the participant's own inquiry can pass tag: "HUMAN_AGENT" to send outside it (up to 7 days, never for promotional or automated content); Telegram and Bluesky have no window.
dm_chats_listList chats for a profile, ordered by most recent activity.
Parameters:
profile_id (string, required): Profile ID (Facebook, Instagram, Telegram, or Bluesky)page (number, optional): Page number, zero-indexed (default: 0)per_page (number, optional): Items per page (default: 20)before / after (string, optional): ISO 8601 timestamp filters on last_message_atdm_chat_createFind or create a chat for a participant (idempotent — returns the existing chat if one exists). Use before messaging a participant the profile hasn't messaged yet.
Parameters:
profile_id (string, required): Profile IDparticipant_external_id (string, required): Platform participant ID (IG-scoped user ID, Facebook PSID, Telegram user id, or Bluesky DID)participant_username (string, optional)participant_name (string, optional)dm_chat_getGet a single chat by Postproxy ID or platform external_conversation_id.
Parameters:
chat_id (string, required): Chat ID or external conversation IDdm_messages_listList messages in a chat, most recent first.
Parameters:
chat_id (string, required): Chat ID or external conversation IDpage (number, optional): Page number, zero-indexed (default: 0)per_page (number, optional): Items per page (default: 20)direction (string, optional): inbound or outboundstatus (string, optional): Filter by message statusdm_message_sendSend an outbound message. Provide either body (text) or media (a single attachment), not both.
Parameters:
chat_id (string, required): Chat ID or external conversation IDbody (string, optional): Message text (required when media is empty)media (string[], optional): Up to one attachment as a URL or local file path. Not supported on Bluesky. (The remote/Worker MCP accepts URLs only.)tag (string, optional): HUMAN_AGENT to send outside the 24h window — extends it to 7 days from the participant's last inbound message (Facebook/Instagram only). Meta restricts it to a human replying to the participant's own inquiry; using it for marketing, offers, or automated re-engagement can get that Page / Instagram account's messaging capability suspended. Past 7 days Meta rejects the send and the message lands in status: failed with the platform error in error_details.reply_to_external_id (string, optional): Telegram only — message_id to thread underreply_markup (object, optional): Telegram only — inline/reply keyboard payloadquick_replies (object[], optional): Facebook & Instagram only — up to 13 tappable chips above the participant's composer. Each { title, payload }.buttons (object[], optional): Facebook & Instagram only — up to 3 buttons attached to the message. Each { type: "web_url", title, url } or { type: "postback", title, payload }.card (object, optional): Facebook & Instagram only — extra fields for the card carrying buttons (subtitle, image_url, default_action). Requires buttons.Facebook Messenger and Instagram Direct only — on Telegram use reply_markup instead (passing these returns a 422). Quick replies are ephemeral chips that vanish once one is tapped; buttons stay attached to the message in the thread.
quick_replies | buttons | |
|---|---|---|
| Max per send | 13 | 3 |
title | required, ≤20 chars | required, ≤20 chars |
payload | required, ≤1000 chars | required for postback, ≤1000 chars |
url | — | required for web_url, must be https:// |
Needs body | no | yes, and body is capped at 80 chars |
With media | Facebook only | not allowed |
Buttons are delivered as a Meta generic template whose element title is your body — that's where the 80-character cap comes from. Instagram is stricter than Messenger: it delivers quick replies only on a plain-text message, so quick_replies with media or with buttons returns 422 there.
Receiving taps: a tapped chip or button postback arrives as an inbound message carrying tapped_action: { "kind": "quick_reply" | "postback" | "callback_query", "payload": "...", "title": "..." }. Read it from dm_messages_list / dm_message_get instead of digging through platform_data. Instagram ice-breaker taps and Telegram callback queries normalize to the same field.
dm_message_getGet a single message by Postproxy ID or platform external_id.
Parameters:
message_id (string, required): Message ID or external IDdm_message_editEdit a previously-sent outbound message. Telegram only. Provide body and/or reply_markup (pass {} to clear the keyboard); at least one is required.
Parameters:
message_id (string, required): Message ID or external IDbody (string, optional): New text/captionreply_markup (object, optional): New keyboard (or {} to remove)dm_message_react / dm_message_unreactAdd or remove your business account's reaction on a message. Facebook Messenger and Instagram Direct only.
Parameters (dm_message_react):
message_id (string, required): Message ID or external IDreaction (string, optional): Named reaction (default love)emoji (string, optional): Unicode emojiParameters (dm_message_unreact):
message_id (string, required)dm_chat_archive / dm_chat_unarchiveArchive (mute) or unarchive (unmute) a chat. Bluesky only. Returns the chat with archived set.
Parameters:
chat_id (string, required): Chat ID or external conversation IDdm_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 only.
Parameters:
post_id (string, required): Post IDcomment_id (string, required): Comment ID or external IDprofile_id (string, required): Profile ID (Instagram or Facebook)text (string, required): DM textquick_replies (array, optional): Up to 13 chips — same shape as dm_message_sendbuttons (array, optional): Up to 3 buttons — same shape as dm_message_send; caps text at 80 characterscard (object, optional): Card styling for buttons (subtitle, image_url, default_action)Interactive elements follow the same rules as dm_message_send — on Instagram, quick_replies and buttons are mutually exclusive. Media attachments are not available on private replies.
| Action | Telegram | Bluesky | ||
|---|---|---|---|---|
| List/Send/Get | Yes | Yes | Yes | Yes |
| Media attachment | Yes | Yes | Yes | No |
| Edit message | No | No | Yes | No |
| React/Unreact | Yes | Yes | No | No |
| Archive/Unarchive | No | No | No | Yes |
| Private reply to comment | Yes | Yes | No | No |
tag (24h window) | Yes | Yes | n/a | n/a |
reply_to_external_id / reply_markup | No | No | Yes | No |
quick_replies / buttons / card | Yes | Yes (text-only) | No | No |
tapped_action on inbound taps | Yes | Yes | Yes | No |
history_listList recent post jobs.
Parameters:
limit (number, optional): Maximum number of jobs to return (default: 10)Returns:
scheduled_at is null for posts that were published immediately. status is the raw API status (draft, scheduled, processing, processed, …), while overall_status folds platform outcomes into a single verdict.
Note: Postproxy's
/postsAPI does not return profile identity (profile ID or name) per platform — only the network. Useprofiles_listto map networks to connected profiles.
These edit the Google business listing itself — hours, attributes, services, food menus, action links and profile photos — as opposed to publishing local posts to it (that's post_publish with platform google_business).
Three rules apply to every tool in this group:
location_id is always required. It's the full Google resource path accounts/X/locations/Y, returned by profiles_placements.fields array naming exactly what's being replaced. Anything named in fields but absent from the payload is cleared, and nested objects are replaced wholesale rather than merged. Always read before you patch.422.Payloads use Google's own shapes and camelCased keys in both directions, so a response can be sent straight back as a request body.
| Tool | Purpose |
|---|---|
google_business_location_get | Read the listing — name, description, website, phones, categories, address, hours, service area, metadata |
google_business_location_update | Update listing fields (title, websiteUri, phoneNumbers, categories, storefrontAddress, serviceArea, labels, latlng, openInfo, profile, storeCode) |
google_business_categories_list | Resolve category resource names (categories/gcid:*) for a region — needed for any categories patch |
google_business_hours_update | Set regularHours, specialHours and moreHours |
google_business_attributes_get | Read attributes currently set |
google_business_attributes_available | List which attributes this listing can set, with value types |
google_business_attributes_update | Set attributes |
google_business_service_list_get | Read the service list |
google_business_service_list_update | Replace the service list (needs metadata.canModifyServiceList) |
google_business_food_menus_get | Read food menus (restaurant-like categories only) |
google_business_food_menus_update | Replace food menus (needs metadata.canHaveFoodMenus) |
google_business_place_action_links_list | List action buttons ("Book online", "Order online") |
google_business_place_action_link_create | Add an action button |
google_business_place_action_link_update | Update an action button |
google_business_place_action_link_delete | Remove an action button |
google_business_media_list | List profile photos and videos |
google_business_media_create | Add a photo or video |
google_business_media_delete | Remove a photo or video |
google_business_attributes_available returns a valueType per attribute, which decides the shape to send back:
| valueType | Shape |
|---|---|
BOOL | { "name": "attributes/offers_online_appointments", "values": [true] } |
URL | { "name": "attributes/url_linkedin", "uriValues": [{ "uri": "https://..." }] } |
ENUM | { "name": "attributes/preferred_messaging_service", "repeatedEnumValue": { "setValues": ["TOKEN"] } } |
attribute_mask defaults to exactly the names you send, so a partial update never clears attributes you left out.
Times accept either "09:00" / "09:00:00" strings or Google's { "hours": 9, "minutes": 0 } objects — both are normalized before the call. Read current hours from google_business_location_get; each block named in fields is replaced entirely.
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 250×250 and at most 5MB. category defaults to ADDITIONAL; use COVER or LOGO only when you intend to change the profile header or logo.
Google omits keys rather than returning empty values: a listing with no attributes returns { "name": "..." } with no attributes key at all, and the same applies to serviceItems, placeActionLinks and boolean flags like isPreferred. Treat absent as empty.
Google Business location analytics come through the standard profiles_stats tool — pass the location_id as placement_id. Metrics are Search and Maps impressions (desktop and mobile), website clicks, call clicks, direction requests, conversations, bookings, food orders and food-menu clicks. Google Business has no follower count, and Google exposes no per-post analytics for local posts.
Here are some example prompts you can use with Claude Code:
Using profile IDs:
Using platform names:
You can use platform-specific parameters to customize posts for each platform. The platforms parameter accepts an object where keys are platform names and values contain platform-specific options.
Regular Post with Collaborators:
Or with explicit parameters:
Instagram Reel:
Instagram Story:
YouTube Video with Title and Privacy:
Or with explicit parameters:
Unlisted YouTube Video:
Public TikTok with Auto Music:
TikTok for Followers Only with AI Label:
Facebook Post with First Comment:
Facebook Story:
Facebook Page Post:
Personal LinkedIn Post:
Company LinkedIn Post:
Plain Bluesky post (auto-faceted mentions/tags/links):
You don't need any markup — Postproxy auto-converts @handles, #tags, and URLs into AT Protocol facets, and generates a link card preview from the URL's Open Graph meta (when no media is attached). 300-grapheme limit.
Telegram channel post (HTML formatting):
Use profiles_placements against your Telegram profile to list channel chat_ids the bot can post to. The bot must be added to the channel as administrator with permission to post.
Same Content, Different Platforms:
Video Across Platforms with Specific Parameters:
Instagram:
format: "post" | "reel" | "story"collaborators: Array of usernames (max 10 for posts, 3 for reels)first_comment: String - comment to add after postingcover_url: String - thumbnail URL for reelsaudio_name: String - audio track name for reelstrial_strategy: "MANUAL" | "SS_PERFORMANCE" - trial strategy for reelsthumb_offset: String - thumbnail offset in milliseconds for reelsuser_tags: Array of { username, x, y, media_index } - tag public Instagram accounts on any format (post, reel, story). Images require x and y (floats 0.0–1.0 from the top-left corner); reels and video slides are tagged by username only (coordinates are dropped); stories accept coordinates but don't need them. media_index picks the carousel slide (0-based, default 0). A leading @ is stripped. Out-of-range coordinates, a media_index past the last media item, or an image tag missing x/y are rejected with a 422 naming the entry. Private accounts and accounts with tagging off are silently skipped by Instagram.YouTube:
title: String - video titleprivacy_status: "public" | "unlisted" | "private"cover_url: String - custom thumbnail URLTikTok:
privacy_status: "PUBLIC_TO_EVERYONE" | "MUTUAL_FOLLOW_FRIENDS" | "FOLLOWER_OF_CREATOR" | "SELF_ONLY"photo_cover_index: Integer - index of photo to use as cover (0-based)auto_add_music: Boolean - enable automatic musicmade_with_ai: Boolean - mark content as AI-generateddisable_comment: Boolean - disable commentsdisable_duet: Boolean - disable duetsdisable_stitch: Boolean - disable stitchesbrand_content_toggle: Boolean - mark as paid partnership (third-party)brand_organic_toggle: Boolean - mark as paid partnership (own brand)Facebook:
format: "post" | "story"first_comment: String - comment to add after postingpage_id: String - page ID for posting to company pagesLinkedIn:
organization_id: String - organization ID for company page postsTelegram:
chat_id: String, required — destination channel/chat ID (use profiles_placements to list)parse_mode: "HTML" | "MarkdownV2" — omit for plain textdisable_link_preview: Boolean — suppress URL preview carddisable_notification: Boolean — send silently (no notification sound)Bluesky:
@handle.bsky.social mentions, #hashtags, and URLs and converts them to clickable facetsthread arrayTwitter/X & Threads:
For complete documentation, see the Platform Parameters Reference.
This will show detailed status including draft status, platform-specific errors, and publishing results.
POSTPROXY_API_KEY is set when registering with claude mcp addpostproxy-mcp is installed and in PATHclaude mcp add and configuration is saved in ~/.claude/plugins/--env POSTPROXY_API_KEY=... when running claude mcp addprofiles_list to see available profiles.{"status":400,"error":"Bad Request","message":"..."}{"errors": ["Error 1", "Error 2"]} - Array of validation error messagesWhen checking post status with post_status, platform-specific errors are now available in the error field of each platform object:
error: null - Post published successfullyerror: "Error message" - Detailed error message from the platform APIIf you create a draft post (draft: true) but receive draft: false in the response:
warning field explaining that the API may have ignored the draft parameterwarning field in the response for detailsPOSTPROXY_MCP_DEBUG=1) to see detailed logging about draft parameter handlingEnable debug logging by setting POSTPROXY_MCP_DEBUG=1 when registering the server:
MIT