MCP Server

Schedule posts from Claude, ChatGPT, Cursor, or any MCP-compatible client, over stdio (npm) or HTTP.

Last updated Sep 9, 2026Updated this week

posterly speaks the Model Context Protocol so any MCP-compatible AI client can list connected accounts, schedule posts, and pull analytics on the user's behalf. Two connection options are available, pick the one that fits your client.

New accounts that start from /mcp pay for a plan plus API & MCP in one Stripe subscription, charged immediately (Starter + API is $10/month). That path has no free trial. After checkout, create a key at Dashboard → API & MCP.

Two connection options

1. Stdio (npm package), desktop AI clients

For Claude Desktop, ChatGPT Desktop, Cursor, Windsurf, Cline, and other clients that run an MCP server as a local subprocess.

You do not need to install anything globally. Add this to your client's MCP config and let npx run the current server:

{
  "mcpServers": {
    "posterly": {
      "command": "npx",
      "args": ["-y", "posterly-mcp-server@latest"],
      "env": {
        "POSTERLY_API_KEY": "pst_live_your_key_here"
      }
    }
  }
}

Quick setup, copy for your AI: Paste this into Claude, ChatGPT, or Cursor and it will configure everything for you:

"I want to connect posterly via MCP. Add this to my MCP config: { "mcpServers": { "posterly": { "command": "npx", "args": ["-y", "posterly-mcp-server@latest"], "env": { "POSTERLY_API_KEY": "YOUR_KEY" } } } }, merge it with my existing config, then remind me to restart."

Replace YOUR_KEY with your API key from Dashboard → API & MCP.

If the user has not signed up yet, install the same server without POSTERLY_API_KEY. The public tools get_agent_signup_info, start_signup, and get_signup_session work before a key exists, so the AI can start paid signup, send the posterly checkout handoff URL, and poll progress while the user pays and sets a password in the browser.

2. HTTP, browser-based AI clients

For Claude in Chrome, ChatGPT (developer mode apps), Cursor in browser, Grok Bot, or any web-based or cloud agent that can't spawn a local process. Dedicated connect pages: Claude, ChatGPT, Cursor, Grok Bot, Poke, Hermes, and OpenClaw. First-schedule walkthroughs: ChatGPT, Claude, Cursor, Poke, Hermes, OpenClaw, Grok Bot Marketplace. Media bodies: Solving the 4MB MCP limit.

  • Endpoint: POST https://www.poster.ly/api/mcp
  • Wire format: JSON-RPC 2.0 (single request, no SSE in v1)
  • Auth header: Authorization: Bearer pst_live_your_key_here
  • Capability hint: GET /api/mcp returns server info without auth.

Quick smoke test from any terminal:

curl -s https://www.poster.ly/api/mcp \
  -H "Authorization: Bearer pst_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

Both connection options use the same API key, the same paywall, and the same route-aware API limits. They expose the same authenticated toolset, but media upload ergonomics differ by transport because hosted HTTP MCP tool calls are JSON only.

Create-post calls are limited to 100 requests per hour per key. This does not mean you can only schedule 100 posts per hour: use create_posts_batch to create up to 25 posts in one confirmed request. Media writes and read-only calls have separate higher limits.

User-created API keys are tier-based: Starter 1, Pro 2, Power 3, Agency 4. Keys can also be scoped to one workspace; connection handoff and webhook tools use the scoped workspace automatically and reject a different workspace_id.

Managed connection through Smithery

Smithery provides a managed connection to the same hosted HTTP MCP endpoint. It uses posterly OAuth, so users authorize their own account without pasting a posterly API key into Smithery.

  1. Open the posterly server on Smithery.
  2. Add or connect it to your Smithery toolbox.
  3. Sign in to posterly, or create an account if needed.
  4. Review the requested account, post, media, and analytics scopes.
  5. Select Allow, then return to Smithery and test with whoami or list_accounts.

Each OAuth connection belongs to the posterly user who approved it. Other Smithery users cannot access that user's accounts, posts, media, or analytics. An active posterly plan plus the API/MCP add-on is still required; Smithery does not provide free posterly API access.

For permission explanations, example prompts, and troubleshooting, read the Smithery social media MCP setup guide.

Media upload: where the 4MB limit exists, and how to get past it

Vercel caps request bodies to posterly API routes at about 4MB. Hosted MCP (POST /api/mcp) is JSON on that same path, so a base64 file inside upload_media counts against it. Base64 also inflates the file, so hosted upload_media is only for small images. Our relay cap is 5MB decoded; treat anything larger as signed upload.

This is not an MCP-protocol file limit, and it is not posterly's plan storage cap. It is the function body on Vercel.

PathHits the ~4MB Vercel body?What to use it for
Hosted MCP upload_media (base64 JSON to /api/mcp)YesSmall images only
REST POST /api/v1/media/upload (base64)YesSmall images only
Legacy PUT /api/v1/media/signed-upload/uploadYesDo not use. Returns FUNCTION_PAYLOAD_TOO_LARGE on large videos
upload_media_from_url / create_post with a third-party media_urlThe JSON call is small. posterly then fetches the URL on the serverSmall public files. About 5MB on the relay path, 60MB remote-fetch hard cap. Large R2/S3 URLs fail with remote_media_too_large
MCP create_signed_upload, then PUT bytes to upload_urlNo. The PUT goes to object storage (R2/Supabase), not VercelVideos and large images. Plan caps: Starter 500MB, Pro 750MB, Power 1GB, Agency 4GB
MCP create_media_drop, human opens /drop/<token>No. The browser PUTs to object storageChatGPT web and Claude.ai laptop files. Agent then calls list_media
Stdio upload_media with file_pathNo. The npm server reads the disk and uses signed upload for large filesCursor, Claude Code, Claude Desktop, Codex, Hermes: give a real local path
CLI media:signed-upload then PUTNoScripts and coding agents that can HTTP PUT
Dashboard composer and Media LibraryNo. They already use signed / direct storageHumans in the app

create_signed_upload is the bypass when the agent can PUT the file itself (know filename, content_type, and exact size, then PUT raw bytes to upload_url with the returned headers, then pass public_url to create_post). Cursor, Claude Code, and Codex can do that.

ChatGPT web and Claude.ai cannot PUT a laptop file, and chat paperclips never reach MCP. For those clients call create_media_drop, send the user drop_url (https://www.poster.ly/drop/<token>), wait, then call list_media. HEIC and PDF are rejected. Plan video caps still apply: Starter 500MB, Pro 750MB, Power 1GB, Agency 4GB.

Why the 4MB number exists, and which tool to call on each runtime: Solving the 4MB MCP limit.

Local stdio MCP can read a local file path and automatically use signed upload for larger media. Use this when the agent is on the same machine as the file.

Hosted HTTP MCP has no binary channel. For larger media on a client that can PUT:

  • Call create_signed_upload with filename, content_type, and size.
  • PUT the raw file bytes to the returned upload_url (object storage). Do not PUT to a poster.ly API route.
  • Pass public_url into validate_post / create_post.

Do not pass a 500MB to 2GB Cloudflare R2, S3, or other remote URL straight to create_post. That fetch fails with remote_media_too_large. Download it (or PUT it) via signed upload instead.

Uploaded media is analyzed automatically in the background. If a video can never reach a selected platform (for example, it is longer than the platform allows, or too large for the platform's file size limit), create_post rejects that combination with an actionable message such as "This video is too large for Telegram (20 MB limit). Export it under 20 MB to include Telegram." Relay the message to the user.

If a destination would need a pixel-changing conversion and the video is HDR, full-range, not Rec.709, or missing complete colour tags, posterly publishes the original file rather than converting it or failing. Compatible originals, remuxes, and video-copy repairs still pass. See Video colour compatibility.

create_post also rejects, at creation time, media combinations that no platform call could satisfy: a PDF sent anywhere other than LinkedIn, an .avi or .mkv video sent to Instagram, and an Instagram account that is missing its business account id (which needs reconnecting in posterly). These used to be accepted and then fail at publish. Relay the message rather than retrying.

The .mov, .webm and .m4v containers remain accepted at creation. Whether a repair is needed depends on the inspected input and destination; compatible originals can pass through unchanged. If colour conversion is unsafe, posterly publishes the original rather than asking for a Rec.709 re-export.

Agent response style

MCP signup and connect tools return user-facing guidance by default. Agents should narrate progress in plain language, send the secure browser links, and avoid showing raw curl commands, HTTP payloads, or JSON unless the user asks for debugging.

Use debug: true only when you deliberately need the raw signup or connect response for troubleshooting. The tools that support this are start_signup, get_signup_session, get_connect_link, create_connect_session, and get_connect_session.

Post tools also return posterly dashboard links. After creating, listing, reading, or deleting posts, share the returned View in posterly link so the user lands in the right dashboard view. Current-month scheduled posts open in Calendar with the post selected; general/future post lists fall back to Table.

Auto-discovery for agents

posterly publishes the standard .well-known discovery endpoints so agents can find everything programmatically:

URLPurpose
/.well-known/mcp/server-card.jsonMCP server card, describes both connection options + tools
/.well-known/api-catalogRFC 9727 linkset describing the REST API surface
/.well-known/oauth-authorization-serverRFC 8414, authorize/token/register endpoints, refresh-token grant
/.well-known/oauth-protected-resourceRFC 9728, bearer methods, scopes, where to mint tokens
/.well-known/agent-skills/index.jsonCloudflare Agent Skills index, links to SKILL.md files
/api/openapiFull OpenAPI 3.1 spec for the REST API

Public marketing pages also emit RFC 8288 Link headers pointing at all of the above, so agents that crawl https://www.poster.ly discover the API surface without any prior configuration.

Auth & billing handoff (RFC 6750)

When an agent calls a tool with a missing/invalid token or no API add-on, posterly returns a WWW-Authenticate header that tells the agent exactly what to do, surface this to the user and they can subscribe inside the agent conversation.

  • 401 invalid_token, WWW-Authenticate: Bearer ... token_uri="https://www.poster.ly/dashboard/api"
  • 403 insufficient_subscription, WWW-Authenticate: Bearer ... error_uri="https://www.poster.ly/dashboard/api?upgrade=api_addon"
  • 403 insufficient_scope, WWW-Authenticate: Bearer ... scope="posts:write"
  • 403 origin_not_allowed, browser caller from an Origin not on the trusted MCP host list (Claude, ChatGPT, posterly, localhost, plus MCP_TRUSTED_ORIGINS).
  • 429, body includes retry_after, limit, remaining, and reset, plus a Retry-After header.

Hosted MCP clients (Claude.ai, ChatGPT, and similar)

Browser-hosted MCP clients can complete a full OAuth connect flow without manual allowlisting via RFC 7591 Dynamic Client Registration:

  • POST /api/oauth/register, send a JSON metadata document (client_name, redirect_uris, scope), receive a client_id immediately.
  • The new client starts the standard authorization-code + PKCE flow at https://www.poster.ly/oauth/authorize.
  • If you are new and still need a plan, posterly sends you to choose a plan and then returns you to the consent screen. The API add-on is still required before the access token activates.
  • The consent screen flags self-registered clients so the user can decide whether to trust the source.
  • Access tokens issued via OAuth live 1 hour. Refresh tokens live 30 days and rotate on every use; reuse revokes the chain.
  • grant_type=refresh_token at /api/oauth/token to renew.

The discovery document at /.well-known/oauth-authorization-server advertises registration_endpoint, token_endpoint, and the supported grants so MCP hosts can wire this up automatically. API keys still work for stdio MCP and scripts.

Available tools

The local stdio server exposes 89 tools. The public setup tools work without POSTERLY_API_KEY; authenticated tools require a posterly API key. The HTTP MCP connection is authenticated and exposes 86 tools.

  • get_mcp_status, show the installed server version, latest npm version, MCP endpoint health, API auth health, and update guidance.

  • get_agent_signup_info, explain the safe agent-led signup flow before an API key exists.

  • start_signup, start paid signup and return a posterly checkout handoff URL plus signup poll URL.

  • get_signup_session, poll checkout, payment, password, and agent-access status.

  • whoami, show the user, workspaces, and scopes your key can access.

  • create_api_key, create a new scoped API key after explicit confirmation. The calling key must be a dashboard-created key, and new scopes cannot exceed the calling key.

  • delete_api_key, revoke a user-created API key after explicit confirmation. The endpoint refuses to revoke the key currently authenticating the request.

  • list_accounts, show all connected social accounts.

  • disconnect_account, disconnect a connected social account after explicit confirmation. It preserves reconnect metadata, archives Instagram analytics, and emits account.disconnected webhooks.

  • get_connect_link, inspect dashboard connection links, provider readiness, required scopes, and connected account counts.

  • connect_account, connect a credential-based account (telegram, bluesky, discord, wordpress, devto, hashnode, lemmy) directly, no browser session needed.

  • create_connect_session, create a guided browser handoff for connecting a social account.

  • get_connect_session, poll connection progress while the user logs in, approves OAuth, or enters credentials.

  • list_oauth_clients / create_oauth_client / update_oauth_client / delete_oauth_client, manage self-serve public OAuth 2.1 + PKCE developer clients after confirmation.

  • list_platforms / get_platform_schema, inspect supported integrations, post types, settings fields, media limits, analytics support, and planned provider possibilities.

  • trigger_platform_helper, run helper discovery such as pinterest.boards, youtube.playlists, tiktok.creator_info, linkedin.recent_mentions, or x.quota.

  • list_brands, show brands/clients available in the current workspace context.

  • get_brand, inspect one brand/client in detail.

  • list_brand_accounts, show the social accounts assigned to a brand/client.

  • get_brand_profile, read the saved brand voice/profile for a brand/client. Also returns learned_voice: the voice posterly has learned from each connected account's real published captions.

  • get_learned_voice, read the voice learned from one account's real published captions (the "learned captions" shown on the dashboard), keyed by social account ID. Returns a narrative summary, voice traits, style guidelines, and observed posting habits. Read-only; never overwrites the saved brand profile.

  • list_posts / get_post / get_post_missing, browse scheduled content and inspect missing content/settings before publish.

  • ask_support, ask authenticated docs-backed support questions with read-only account/post diagnostics. If the user asks for a human, agent, real person, or an escalation, Support AI files a ticket. Agent-initiated handoff still uses request_human plus confirm_escalation.

  • create_post, schedule or immediately publish one post. Pass thread_posts: string[] (2+ entries) for X or Threads chains, and platform_settings for platform-specific composer controls. For media, pass URLs returned by the media upload tools.

  • validate_post, validate the complete payload without creating a post, copying remote media, consuming post-item/storage quota, reserving X quota, emitting webhooks, or enqueueing publication. Resolve warnings, show the final preview, and ask for explicit confirmation before calling create_post.

  • submit_agent_feedback, submit bounded private operational telemetry after a concrete workflow outcome. Never include secrets, prompts, captions, media URLs, personal data, or fabricated outcomes.

  • submit_product_feedback, file a product bug, idea, or feedback on the public posterly feedback board after the user explicitly approves the title and category (confirm=true). Do not use this for tool failures; use submit_agent_feedback for private operational telemetry.

  • create_posts_batch, create up to 25 confirmed posts in one API request. Each item accepts the same fields as create_post, and partial failures return the item index. Third-party media URLs are copied into posterly storage before each post is saved.

  • update_post / update_post_status / update_post_release_id / delete_post / delete_post_group, manage scheduled content, repair release/group metadata, and clean up grouped drafts/scheduled posts after confirmation.

  • upload_media, small base64 files on hosted HTTP (Vercel ~4MB body). Stdio file_path uses signed upload for large files.

  • upload_media_from_url, fetch a public image/video URL into posterly storage with SSRF protections (small files; large R2/S3 URLs fail).

  • create_signed_upload, mint an object-storage PUT URL so large files never enter the Vercel body. The client must PUT the bytes.

  • create_media_drop, mint a no-login https://www.poster.ly/drop/<token> page so a human can upload a laptop file. Chat paperclips still never reach MCP.

  • list_media, list newest media assets, or files from one drop session, then pass public_url to validate_post / create_post.

  • find_available_slot, find the next open posting slot honoring the 1h gap.

  • generate_captions, generate or adapt brand-aware caption suggestions without creating a post. Captions are checked against the brief and the workspace's business facts; unverifiable prices, dates, times, links, phone numbers and handles are removed, as is any never-say phrase set on a fact, so fewer variants than requested may come back.

  • generate_image, create AI images with Nano Banana.

  • get_video_options, inspect read-only Veo video models, durations, input modes, and credit-cost estimates.

  • run_video_function, run read-only Veo helpers for cost estimation and request validation.

  • generate_video, queue a cost-guarded Veo video job after user confirmation.

  • get_credits, read the AI credit balance for the caller's workspace wallet. Read-only, spends nothing.

  • get_video_job, poll one Veo job or list recent video jobs until video_url is ready.

  • get_account_analytics, follower growth, reach, views, engagement rate for social platforms, and API-provided native display_metrics such as Google Business Profile's Profile Views, Search Views, Maps Views, Customer Actions, and Posts (Instagram, Facebook Pages, LinkedIn, Google Business Profile, Pinterest, YouTube, and Threads). Accepts presentation: "compact" | "table" | "json" so Telegram can stay bullet-based while Markdown clients or custom renderers can choose tables/structured data.

  • get_post_analytics, per-post likes, comments, reach, impressions, saves, shares, plays. Also accepts presentation: "compact" | "table" | "json".

  • get_performance_profile, read the read-only performance profile posterly derives for one account from the last 90 days of per-post analytics (top formats, timing, caption-length patterns, an engagement-rate trend, and a narrative summary), keyed by social account ID. Requires a Pro plan or higher.

  • get_post_insights, list per-post feedback-loop insights for recently published posts: the performance tier (great/good/mixed/poor), a diagnosis, a suggested next action, metrics, and the baseline each was compared against. Filter by account_id, post_id, and checkpoint (1h, 6h, 24h, 72h, 7d). Requires a Pro plan or higher.

  • list_post_suggestions, list evidence-based weekly post drafts written in each account's learned voice, each with a rationale tying it back to what has performed well. Filter by account_id and status (pending, scheduled, dismissed). Requires a Pro plan or higher.

  • dismiss_suggestion, dismiss a post suggestion after user confirmation. Never dismisses a suggestion that was already turned into a scheduled post.

  • list_conversations, list Instagram and Facebook Page inbox DMs. Threads has no DMs. Requires a Pro plan or higher.

  • get_conversation, get one inbox conversation and its messages.

  • send_message, send a DM reply after explicit confirmation. Honors Meta 24-hour messaging windows.

  • list_comments, list Instagram, Facebook Page, and Threads inbox comments.

  • get_comment, get one inbox comment and its replies.

  • reply_to_comment, reply to a comment after explicit confirmation. Facebook has no private comment replies; Threads is public-only.

  • update_comment, hide/unhide a comment or mark it read. Hide is reversible and does not delete.

  • delete_comment, delete an Instagram or Facebook Page inbox comment after confirmation. Irreversible. Admin only. Threads replies cannot be deleted; hide them with update_comment.

  • sync_inbox, pull the latest inbox data for one Instagram, Facebook, or Threads account, with a 30-second cooldown.

  • list_google_business_reviews, list GBP reviews for one location or every accessible location. Returns every review Google holds (it pages past Google's own 50-per-page cap), with the full untruncated review text and its date. Filter by rating and unanswered, and page with limit (default 200, max 1000) and offset; has_more tells you when more remain. Each location also reports its total_review_count and average_rating from Google, plus an error field, so a location with no reviews is distinguishable from one that failed to sync.

  • get_google_business_review_link / audit_google_business_profile, generate review request links and run local-profile audits.

  • suggest_google_business_review_reply, generate brand-aware reply options without posting.

  • reply_google_business_review / delete_google_business_review_reply, manage public GBP review replies after explicit confirmation.

  • list_google_business_media, list the photos and videos on a GBP profile gallery (the media shown on Maps and Search).

  • add_google_business_media / delete_google_business_media, add a photo/video to the profile gallery from a public URL, or remove one, after explicit confirmation.

Google Business tip: pass account_id (the integer id from list_accounts) to every GBP tool. If you use location_id instead, it is the numeric location_id from list_accounts (the GBP location id), not the ChIJ... Place ID that get_google_business_review_link returns. Passing the Place ID resolves to no account and returns "Google Business Profile account not found".

  • list_activity, read the agent notifications feed of post activity, publish attempts, failures, and retries.
  • get_updates, get the latest posterly product updates and news from the updates feed. Requires an active posterly subscription.
  • list_webhooks, inspect webhook subscriptions and delivery status.
  • create_webhook / update_webhook / delete_webhook / test_webhook, manage signed webhook subscriptions after explicit confirmation.
  • get_x_posting_quota, inspect workspace X posting allowance and URL-block status.
  • get_subscription, read the user's posterly subscription status, tier, cancel/pause state, and period end. Requires the billing:read scope.
  • cancel_subscription, cancel the subscription after explicit confirmation. The agent must ask the user for a cancellation reason first (a fixed catalog value) and pass confirm: true; immediate defaults to cancel-at-period-end. Requires the billing:write scope.
  • pause_subscription, pause the subscription for 30 days (one pause per 90-day cooldown) after confirm: true. Requires the billing:write scope.
  • resume_subscription, resume a paused subscription. Requires the billing:write scope.
  • downgrade_subscription, downgrade one tier (or to an explicit lower tier) at the next renewal after confirm: true. Requires the billing:write scope.

Subscription management runs on the same API key but does not require the paid API add-on, so a paused or cancel-pending user can still resume or manage their plan. The destructive actions (cancel_subscription, pause_subscription, downgrade_subscription) require confirm: true after explicit user confirmation, and cancel_subscription also requires a reason. Reactivating a pending cancellation, restarting a lapsed plan, and retention offers stay in the dashboard.

Usage examples

In Claude, ChatGPT, or any MCP client:

  • "Schedule a LinkedIn post about our Q1 results for tomorrow at 10am"
  • "What accounts do I have connected to posterly?"
  • "Disconnect the old Instagram account after I confirm the exact account ID"
  • "Pause post 971 after I confirm it is the right scheduled post"
  • "Upload this image and create an Instagram post with it"
  • "Schedule this as an Instagram Reel, add @partner as a collaborator, and use this image as the Reel cover"
  • "Schedule this YouTube video as unlisted, add these tags, and put it in our launch playlist"
  • "Post this TikTok with comments on, duet off, stitch off, and public privacy"
  • "Turn this Google Business update into an event post with a Learn more CTA"
  • "How did my Instagram perform over the last 14 days?"
  • "Which of my recent LinkedIn posts got the most engagement?"
  • "Post this 5-tweet thread on my X account at 3pm tomorrow" (uses thread_posts for X / Threads chains)

platform_settings covers the same scheduling controls exposed by the composer: Instagram feed/story/reel/carousel options plus parent-container is_ai_generated and licensed Reel audio_id (Facebook Login / Meta-linked only), Facebook stories/reels/backgrounds, YouTube thumbnails/privacy plus notify_subscribers, add_shorts_hashtag, and optional brand_partner, LinkedIn document, mention, poll, and content_call_to_action_label settings (including BUY_NOW and SHOP_NOW), TikTok video and photo slideshow controls (including video_cover_timestamp_ms to pick the cover frame on direct-post videos), Pinterest board/link/title/product_tags, Google Business event/offer/CTA/recurrence fields, X polls, reply settings (incl. subscribers/verified), and paid_partnership, Threads reply controls, polls, topic tags, text attachments, ghost posts, spoilers, reply approvals, GIPHY, and share_to_instagram, Telegram polls, inline CTA buttons, video cover, and live photo, Slack markdown/blocks, Mastodon visibility/quote/poll (media plus poll allowed), and Bluesky language, alt-text, content warnings, hidden tags, quote posts, and disable-quotes settings. Pass ai_generated: true to label a post as AI-generated on TikTok, X, YouTube, Pinterest, and Instagram.

For TikTok you do not need to set a post type for images. posterly auto-detects image media and schedules it as a photo slideshow of 1 to 35 images (sending every image), so "Schedule these 5 photos as a TikTok" just works. A single video schedules as a standard TikTok video.

See the MCP marketing page for client-specific setup screenshots.

Claude Code plugin alternative

If you use Claude Code, you can install the official posterly plugin instead of editing MCP config by hand. The plugin bundles this MCP server plus the agent skill and a guided /posterly:setup flow.

/plugin marketplace add awpthorp/posterly-agent
/plugin install posterly@posterly-agent

Full steps: Claude Code plugin.