# How to let Claude schedule your social media posts (MCP, step by step)

> Source: <https://dev.to/perufitlife/how-to-let-claude-schedule-your-social-media-posts-mcp-step-by-step-3d41>
> Published: 2026-10-01 10:01:02+00:00

*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.

**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:

``` bash
$ 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`.

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.**

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`.

*"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:

`schedule_post` refuses immediately with a `not_connected` or `media_required` code. You find out while you're still in the conversation.
*"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_week` is for *"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.

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.

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.

`post_to_social` call 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](https://postwire.io/claude/schedule-social-media-posts/).
