Post from Claude Code in 90 seconds
August 30, 2026
You have just shipped something and you want it on LinkedIn and X. You are in Claude Code. The gap between those two facts is normally a browser tab, two logins and ten minutes of losing your train of thought.
This is that gap closed. Install a plugin, export a key, and ask Claude to post. Everything below is real: the commands run, the JSON is the shape the API actually returns, and the tool names are the five that exist.
#Step 1: install the plugin
Two lines inside Claude Code.
/plugin marketplace add yeetpost/yeetpost
/plugin install yeetpost@yeetpostIf the install summary ends with Run /reload-plugins to activate., run that.
#Step 2: give it a key
The MCP server reads your key at startup, so export it and restart Claude Code.
export YEETPOST_API_KEY=yp_secret_...Keys live in settings. Two kinds exist. A live key starting yp_secret_ reaches your real accounts. A test key starting yp_test_ reaches sandbox connections and nothing else, which is the one to start with if you would rather not discover the tool surface in public. More on that below.
Do not want the plugin? The same server added by hand does the same job.
claude mcp add --transport http \
--header "Authorization: Bearer $YEETPOST_API_KEY" \
--scope user yeetpost https://api.yeetpost.com/api/v2/mcpIt is a hosted Streamable HTTP server at https://api.yeetpost.com/api/v2/mcp. Any MCP client that speaks Streamable HTTP and can set a header works: point it there with Authorization: Bearer <key> or x-api-key: <key>.
#Step 3: connect an account
Posting needs somewhere to post. That part is a browser, once. Sign in at app.yeetpost.com, hit "New connection", and pick a platform. Six are live: LinkedIn (personal profiles and company pages), X, Bluesky, Discord channels, Telegram channels and Mastodon.
Every connection gets a short slug. The first LinkedIn account is linkedin, the second is linkedin_2, and so on. Slugs are what the agent names when it posts, which is why they are short and stable rather than UUIDs.
#The five tools
That is the whole setup. What Claude now holds is five tools:
| Tool | What it does |
|---|---|
list_connections | Your accounts and channels, with their slugs |
create_post | Posts text to one or more connections, now, scheduled, queued or as a draft |
list_posts | Recent posts, newest first, filterable by status and tag |
get_post | One post by id, with its status and permalink |
cancel_scheduled_post | Cancels a scheduled post that has not gone out |
Five. Not five hundred behind a search endpoint. An agent can hold all of them in context and still have room to think about your post.
#The session
Here is what it looks like from the inside. You type:
> post "shipped per-connection results today, one account failing no
longer fails the request" to linkedin and xClaude does not know your slugs yet, so it calls list_connections first. That tool takes an optional profileId and nothing else, and returns a plain array:
[
{ "slug": "linkedin", "description": "Alex Doe (LinkedIn)", "profileId": null },
{ "slug": "x", "description": "@alexdoe (X)", "profileId": null },
{ "slug": "bluesky", "description": "@alexdoe.bsky.social (Bluesky)", "profileId": null }
]Now it has the slugs, so it calls create_post with connectionSlugs: ["linkedin", "x"] and the text. And here is the part worth understanding, because it is the part that surprises people:
{
"results": [
{
"connectionSlug": "linkedin",
"status": "sent",
"postId": "6f1b0c8a-1f3d-4d3e-9a2b-2f5a1c9e7d10",
"url": "https://www.linkedin.com/feed/update/urn:li:share:1234567890",
"scheduledFor": null,
"threadCount": 0,
"hasFirstComment": false,
"error": null
},
{
"connectionSlug": "x",
"status": "failed",
"postId": "0b7e4a52-9f0c-4a1c-8b3a-6d2f5b1c0e44",
"url": null,
"scheduledFor": null,
"threadCount": 0,
"hasFirstComment": false,
"error": {
"code": "platform_rejected",
"message": "X: duplicate post was detected"
}
}
]
}One entry per connection, in the order the slugs were given. LinkedIn went out. X refused it as a duplicate. That is not a tool error, and Claude does not roll anything back: it reports both, in plain language, and asks whether you want to reword the X one. A tool error is reserved for problems with the whole call, like empty text, a scheduledFor in the past, or none of the slugs matching a connection of yours.
This shape exists because the alternative is worse. A single success flag over a fan-out either lies when one platform is down, or throws away three good posts because the fourth failed.
#Scheduling, and taking it back
create_post also takes scheduledFor, an ISO 8601 timestamp that has to be in the future and inside 30 days:
> schedule that for tomorrow 9am on blueskyThe result comes back scheduled with the time it holds, and a postId. Change your mind and the fifth tool earns its place:
{ "id": "b41d2e77-6a90-4c31-9d55-3e0a1f8c2b64", "status": "cancelled" }cancel_scheduled_post only works while the post is still pending. If the worker has already picked it up, you get post_not_cancellable and an honest explanation rather than a silent no-op.
#Try it without posting anything
Nobody wants their first agent-driven post to be a live one. So add a sandbox connection in the dashboard. It gets the slug sandbox, it is free (sandbox connections never count toward your plan and never change your bill), and it validates posts, stores them, returns the same shapes a real platform returns and fires the same webhooks. It publishes nothing.
Then create a test key. Point Claude at that key instead, and list_connections shows only your sandbox connections, create_post refuses every other slug with invalid_connection, and list_posts sees sandbox posts only. The whole tool surface behaves exactly as it will in production, on a connection that cannot embarrass you.
One extra trick: start the text with [fail] and the sandbox answers 422 platform_rejected with "sandbox failure requested". That is how you see what Claude does with a failure without waiting for a real one.
#What does not work yet
Plenty. There is no upload tool: create_post takes mediaIds, but the images themselves go up over HTTP with POST /api/v2/media first, so an agent working purely through MCP cannot attach a picture it just made. There is no publish tool either, so isDraft: true stores a draft that you then publish over REST. Threads work on X, Bluesky, Telegram and Mastodon and are refused elsewhere with shape_unsupported; first comments are LinkedIn only. Facebook, Threads, Slack, SMS and email are not connections you can make today, whatever the older posts on this blog say. And the v2 CLI mentioned in our SDK docs is not on npm yet: the yeetpost package published there is an older, much smaller one, so build the CLI from the repo or stay on the API for now.
#Where to go next
The MCP docs have the full tool reference, and the API docs cover everything the tools sit on top of. If you want the shortest possible version of this post: install, export, ask.