Disclosure: I'm Renzo, and I build PostWire, the MCP server used here. It has a free plan. The same steps work with any MCP server that exposes scheduling tools; the tool names will differ.
Claude can't post to LinkedIn or Bluesky on its own. It has no access to your accounts. It can once you connect an MCP server (Anthropic calls these connectors) that holds those connections and exposes tools like "schedule this post". This tutorial sets that up, schedules a post, plans a week of posts, and cancels one. Along the way it shows the actual tool calls Claude makes, so you can do the same from your own agent.
Everything below was run on Oct 1, 2026 against PostWire's hosted server with a test account.
Step 1: Add the server
In Claude (web, desktop, mobile): PostWire is in Claude's connector directory. Search for "PostWire", press Connect, and sign in with your email. You get a 6-digit code; there's no password and no card.
In Claude Code, one command:
claude mcp add --transport http postwire https://postwire.io/api/mcp
Without a key, Claude Code signs you in with OAuth: run /mcp inside Claude Code and pick postwire. To use an API key instead (dashboard → API & MCP → Copy key):
claude mcp add --transport http postwire https://postwire.io/api/mcp \
--header "Authorization: Bearer pw_live_your_key"
Check it:
$ claude mcp list
postwire: https://postwire.io/api/mcp (HTTP) - ✔ Connected
The hosted server has 15 tools. The ones this tutorial uses are create_connect_link, generate_posts, schedule_post, plan_week, list_scheduled_posts and cancel_scheduled_post.
Step 2: Connect the networks you post to
Ask: "Connect my LinkedIn." Claude calls create_connect_link:
{ "name": "create_connect_link", "arguments": { "platform": "linkedin" } }
and gets back a link that's valid for one hour:
{ "url": "https://postwire.io/connect/#…", "expires_in": 3600, "platform": "linkedin" }
You open it and sign in on LinkedIn itself. Claude never sees a password. The networks you can connect are TikTok, Instagram, YouTube, LinkedIn (personal profiles), Facebook Pages, Bluesky, Mastodon, Telegram and Discord. X, Threads, Reddit and Pinterest aren't available.
Step 3: Tell Claude your time zone once
Scheduling needs an exact time with an offset (run_at, ISO 8601, up to 365 days ahead). Say "I'm in New York" once and Claude will turn "Friday at 9" into 2026-10-09T09:00:00-04:00.
Step 4: Schedule one post
"Write a short post announcing our autumn menu for LinkedIn and Bluesky and schedule it for Friday 9:00."
Claude first calls generate_posts, which returns one draft per network and publishes nothing. It shows you the drafts. After you approve, it calls:
{
"name": "schedule_post",
"arguments": {
"run_at": "2026-10-09T09:00:00-04:00",
"platforms": ["linkedin", "bluesky"],
"per_platform": { "linkedin": { "text": "…" }, "bluesky": { "text": "…" } },
"label": "Menu launch"
}
}
The answer (trimmed, from my run against a test channel):
{
"ok": true,
"scheduled": {
"id": "0f8b4368-…",
"run_at": "2026-10-09T13:00:00+00:00",
"status": "queued",
"label": "Menu launch"
},
"message": "Scheduled for 2026-10-09T13:00:00.000Z to …"
}
Two details matter here:
- PostWire's servers publish it, so the chat and your laptop can be closed at 9:00.
-
The checks happen now, not at 9:00. If a network isn't connected, or a network needs a video and the post has none,
schedule_postrefuses immediately with anot_connectedormedia_requiredcode. You find out while you're still in the conversation.
Step 5: Or plan the whole week
"Plan the next 5 days of posts about our autumn menu and the farmers behind it, LinkedIn and Bluesky, 9 am New York time."
Claude calls plan_week:
{
"name": "plan_week",
"arguments": {
"topic": "our new autumn menu and the farmers behind it",
"platforms": ["linkedin", "bluesky"],
"days": 5, "hour": 9, "timezone": "America/New_York"
}
}
It writes one post per day, each from a different angle and each in the format of its network, and queues them starting tomorrow. In my run with "days": 2 (to a test Discord channel) it queued 2026-10-02T13:00:00Z and 2026-10-03T13:00:00Z (9:00 in New York). Day one opened with a lesson ("building our autumn menu taught us something we didn't expect…") and day two with an opinion ("hot take 🍂 most people scroll past a new menu…").
Limits you should know about:
-
plan_weekis for text networks. It refuses TikTok, Instagram and YouTube, because those need a video or photo. Schedule those one post at a time. - Each day uses one AI draft. The free plan allows 15 a day and 30 posts a month, and a post to two networks counts as 2.
- If the week doesn't fit in the month's posts, the extra days are saved as held. They're never published on the current plan, and get scheduled if you upgrade.
Step 6: Check and cancel
"What's scheduled?" → list_scheduled_posts returns each post's id, time, networks and status (queued, done, failed, canceled…).
"Cancel Friday's post." →
{ "name": "cancel_scheduled_post", "arguments": { "id": "0f8b4368-…" } }
→ { "ok": true }
A post can be cancelled until it starts publishing. The same queue shows up in the dashboard, with Reschedule and Cancel buttons.
Videos: the attachment problem
If you attach a video in the chat, it never reaches an MCP server. Claude can't hand it over. Instead it calls create_upload_link:
{ "url": "https://postwire.io/upload/#…", "expires_in": 86400, "max_bytes": 1073741824 }
You open that link on the device that has the file and upload it (up to 1 GB). Claude then calls get_uploaded_file to get its media_url and uses that as video_url.
One caveat I found while writing this: schedule_post has no privacy field today. A TikTok or YouTube video scheduled through it goes out private (with no privacy value, PostWire posts to TikTok as private, and YouTube uploads default to private) unless the connected account's default visibility is set to public. For YouTube you can set that in the dashboard under Accounts. For a public video now, post_to_social accepts "privacy": "public". For a public video later, use the REST call below, which passes privacy through.
Without Claude: the same thing over REST
Any agent framework (or a cron job) can do the same with one HTTP call:
curl -X POST https://postwire.io/api/schedule \
-H "Authorization: Bearer $POSTWIRE_API_KEY" -H "Content-Type: application/json" \
-d '{"run_at":"2026-10-09T09:00:00-05:00","platforms":["linkedin","bluesky"],"text":"Launch day.","label":"Launch"}'
GET /api/schedule lists the queue and DELETE /api/schedule/<id> cancels a post. If a network isn't connected, you get 400 with "code": "not_connected" and the list of missing networks.
When this is the wrong tool
- If you need X, Threads, Pinterest or Reddit, PostWire doesn't publish there.
- LinkedIn is personal profiles only, not Company Pages.
- Claude asks before it publishes, and it should keep doing that. Every
post_to_socialcall is a real post on a real account, so approve the exact text.
Configs for Claude Desktop, Cursor, VS Code and Windsurf, plus runnable curl, Node and Python versions of the REST calls, are in the Perufitlife/postwire-examples repository on GitHub. The step-by-step guide, with the FAQ, is here: How to schedule social media posts with Claude.
Top comments (0)