Social Publishing via BulkPublish
Cross-platform scheduling and publishing through one API. Unlike per-platform skills, this
targets many networks in a single call, with each platform's rules enforced up front.
Setup
MCP (recommended) — hosted server, no install:
claude mcp add --transport http bulkpublish https://mcp.bulkpublish.com/mcp
Add it as a custom connector and OAuth 2.1 walks you through consent — no key in the URL.
Or the npm server (stdio):
claude mcp add bulkpublish --env BULKPUBLISH_API_KEY=bp_your_key -- npx -y @bulkpublish/mcp-server
Or plain REST: https://app.bulkpublish.com/api, spec at
https://app.bulkpublish.com/openapi.json, docs at https://app.bulkpublish.com/docs.
Get an API key at app.bulkpublish.com/developer and
send it as Authorization: Bearer <key>. API and MCP access are on every plan, free included.
Workflow
list_channels — get connected accounts with their channelId and platform. Do this
first; never guess a channel id.
- Check the platform rules below (or
get_channel_options) before composing.
- Upload media if needed —
upload_media takes a public url or a local filePath, and
returns the id you pass in mediaFileIds.
create_post with content, channels, and status: "scheduled" plus scheduledAt
(or leave it a draft, then publish_post when the user confirms).
- Confirm the exact text, target accounts, and time with the user before publishing.
create_post essentials
content (string, required) — post text
channels (array, required) — [{ channelId: number, platform: string }]
status ("draft" | "scheduled") — default "draft"
scheduledAt (ISO 8601 string) — required when status is "scheduled"
timezone (string) — e.g. "America/New_York"
mediaFileIds (number[]) — ids from upload_media
platformContent (object) — per-platform text override
postTypeOverrides (object) — per-platform post type, e.g. {"instagram":"reel"}
platformSpecific (object) — per-platform extras (titles, link previews)
requestApproval (boolean, false) — hold the post for human review
create_post schedules or drafts. To send something out immediately, create it and then call
publish_post; retry_post re-runs a failed one.
Platform rules that actually break posts
- YouTube and TikTok require video. Never include them on an image-only or text-only post.
- YouTube and Pinterest require a title — set
platformSpecific.youtube.title /
platformSpecific.pinterest.title.
- Instagram defaults to
feed_photo. With a video you must set
postTypeOverrides.instagram to reel or feed_video, or the post fails.
- Instagram needs a Business or Creator account — personal accounts are rejected.
- Character limits differ sharply: X 280, Bluesky 300, Threads / Mastodon / Google Business
500, Pinterest 1,500, Discord 2,000, Instagram / TikTok 2,200, LinkedIn 3,000, Telegram 4,096,
YouTube 5,000, Facebook 63,206. Use
platformContent to give the short networks their own
trimmed text rather than truncating everything down to the smallest limit.
- Facebook cannot mix images and video in one post.
Approvals
Posts carry an approvalStatus (none | pending | approved | rejected) separate from
status. The scheduler never publishes a pending or rejected post. Pass
requestApproval: true to hold a post for a human; approve_post / reject_post release it.
API keys whose role lacks post:publish always have it forced on and get 403 APPROVAL_REQUIRED from publish and retry — that is expected, not a bug.
Analytics
get_analytics takes startDate / endDate (ISO dates) and returns a summary with a
per-platform breakdown; get_post_metrics covers a single post. Outbound linkClicks are
measured by BulkPublish's own short links and are reported separately from clicks — one
visit can appear in both, so never add them together.
Other tools
get_channel_health (re-auth needed?), get_queue_slot (next optimal time for a timezone),
create_schedule (recurring posts), list_labels, get_quota_usage (plan limits and usage).
Rules
- Read the docs or the OpenAPI spec rather than inventing endpoints or parameters.
- Confirm channel ids from
list_channels before every publish.
- Show the user the exact text, accounts and time before anything goes out.
- If a platform cannot do what was asked, say so instead of silently dropping it.
1---2name: bulkpublish-social-scheduling3description: Schedule, publish and analyze social posts across 15 networks via BulkPublish (MCP or REST) — Facebook, Instagram, X, TikTok, YouTube, Threads, Bluesky, Pinterest, Google Business, LinkedIn, Mastodon, Discord, Telegram, Tumblr, Snapchat. Use when the user wants to post, schedule, or bulk-publish to social media, check connected channels, or read post analytics. Always check platform rules before composing.4license: MIT5---6
7# Social Publishing via BulkPublish
8
9Cross-platform scheduling and publishing through one API. Unlike per-platform skills, this
10targets many networks in a single call, with each platform's rules enforced up front.
11
12## Setup
13
14**MCP (recommended)** — hosted server, no install:
15
16```bash
17claude mcp add --transport http bulkpublish https://mcp.bulkpublish.com/mcp
18```
19
20Add it as a custom connector and OAuth 2.1 walks you through consent — no key in the URL.
21
22**Or the npm server (stdio):**
23
24```bash
25claude mcp add bulkpublish --env BULKPUBLISH_API_KEY=bp_your_key -- npx -y @bulkpublish/mcp-server
26```
27
28**Or plain REST:** `https://app.bulkpublish.com/api`, spec at
29`https://app.bulkpublish.com/openapi.json`, docs at `https://app.bulkpublish.com/docs`.
30
31Get an API key at [app.bulkpublish.com/developer](https://app.bulkpublish.com/developer) and
32send it as `Authorization: Bearer <key>`. API and MCP access are on every plan, free included.
33
34## Workflow
35
361. `list_channels` — get connected accounts with their `channelId` and `platform`. Do this
37 first; never guess a channel id.
382. Check the platform rules below (or `get_channel_options`) before composing.
393. Upload media if needed — `upload_media` takes a public `url` or a local `filePath`, and
40 returns the id you pass in `mediaFileIds`.
414. `create_post` with `content`, `channels`, and `status: "scheduled"` plus `scheduledAt`
42 (or leave it a draft, then `publish_post` when the user confirms).
435. Confirm the exact text, target accounts, and time with the user **before** publishing.
44
45## create_post essentials
46
47```
48content (string, required) — post text
49channels (array, required) — [{ channelId: number, platform: string }]
50status ("draft" | "scheduled") — default "draft"
51scheduledAt (ISO 8601 string) — required when status is "scheduled"
52timezone (string) — e.g. "America/New_York"
53mediaFileIds (number[]) — ids from upload_media
54platformContent (object) — per-platform text override
55postTypeOverrides (object) — per-platform post type, e.g. {"instagram":"reel"}
56platformSpecific (object) — per-platform extras (titles, link previews)
57requestApproval (boolean, false) — hold the post for human review
58```
59
60`create_post` schedules or drafts. To send something out immediately, create it and then call
61`publish_post`; `retry_post` re-runs a failed one.
62
63## Platform rules that actually break posts
64
65- **YouTube and TikTok require video.** Never include them on an image-only or text-only post.
66- **YouTube and Pinterest require a title** — set `platformSpecific.youtube.title` /
67 `platformSpecific.pinterest.title`.
68- **Instagram defaults to `feed_photo`.** With a video you must set
69 `postTypeOverrides.instagram` to `reel` or `feed_video`, or the post fails.
70- **Instagram needs a Business or Creator account** — personal accounts are rejected.
71- **Character limits differ sharply**: X 280, Bluesky 300, Threads / Mastodon / Google Business
72 500, Pinterest 1,500, Discord 2,000, Instagram / TikTok 2,200, LinkedIn 3,000, Telegram 4,096,
73 YouTube 5,000, Facebook 63,206. Use `platformContent` to give the short networks their own
74 trimmed text rather than truncating everything down to the smallest limit.
75- **Facebook cannot mix images and video** in one post.
76
77## Approvals
78
79Posts carry an `approvalStatus` (`none` | `pending` | `approved` | `rejected`) separate from
80`status`. The scheduler never publishes a `pending` or `rejected` post. Pass
81`requestApproval: true` to hold a post for a human; `approve_post` / `reject_post` release it.
82API keys whose role lacks `post:publish` always have it forced on and get `403
83APPROVAL_REQUIRED` from publish and retry — that is expected, not a bug.
84
85## Analytics
86
87`get_analytics` takes `startDate` / `endDate` (ISO dates) and returns a summary with a
88per-platform breakdown; `get_post_metrics` covers a single post. Outbound `linkClicks` are
89measured by BulkPublish's own short links and are reported separately from `clicks` — one
90visit can appear in both, so never add them together.
91
92## Other tools
93
94`get_channel_health` (re-auth needed?), `get_queue_slot` (next optimal time for a timezone),
95`create_schedule` (recurring posts), `list_labels`, `get_quota_usage` (plan limits and usage).
96
97## Rules
98
99- Read the docs or the OpenAPI spec rather than inventing endpoints or parameters.
100- Confirm channel ids from `list_channels` before every publish.
101- Show the user the exact text, accounts and time before anything goes out.
102- If a platform cannot do what was asked, say so instead of silently dropping it.