Last updated: September 2026

How do I get Claude Code to post my tweet to Bluesky too?

Add the OpenTweet MCP server with one command, connect both accounts once, then have Claude pass platforms: ["x","bluesky"] on the posting tool. That publishes a native post on each network from a single tool call, not a link from one to the other.

Four steps below, plus the one instruction that stops the agent quietly reverting to X-only on the next session.

The four steps

1

Add the server

One claude mcp add command with the hosted URL and your ot_ key as a header. Nothing runs locally.

2

Connect the accounts once

X with one click, Bluesky over atproto OAuth. No developer app on either side, and no App Password.

3

Ask for both networks

Tell Claude to pass platforms: ["x","bluesky"]. Explicit values are honoured exactly and never expanded.

4

Make it stick

Add the rule to your project instructions so the next session does not have to be reminded.

Add the server

The endpoint is hosted, so this installs nothing on your machine. Your ot_ key goes in the header and can be rotated on its own from the dashboard.

terminal
claude mcp add --transport http opentweet \
  https://mcp.opentweet.io/mcp \
  --header "Authorization: Bearer ot_your_key"

For Claude Desktop, Cursor or any other MCP client, the same URL goes into the connectors config instead.

mcp config
{
  "mcpServers": {
    "opentweet": {
      "type": "streamable-http",
      "url": "https://mcp.opentweet.io/mcp",
      "headers": { "Authorization": "Bearer ot_your_key" }
    }
  }
}

Then connect the accounts once in the dashboard. X takes a click. Bluesky uses atproto OAuth, so you type your handle, sign in on the server that holds your account, and no password or App Password is pasted into anything. There is no Bluesky API key to find, because Bluesky does not issue them.

Ask for both networks

In conversation this is just a sentence: post this to X and Bluesky. What the agent does underneath is one tool call with an explicit platforms array.

tool calls
opentweet_create_tweet({
  text: "Shipped cross-posting today.",
  platforms: ["x", "bluesky"],
  publish_now: true
})

// Not sure where an unspecified post would land? Ask first.
opentweet_list_platforms({})

Omitting platforms does not mean X

A post with no platforms value follows the account auto cross-post setting, so it can land on one network or both depending on a setting the agent cannot see from the call site. Explicit values are always honoured exactly and never expanded. This is the single most common reason a cross-post silently becomes an X-only post.

Make it stick past this session

Reminding the agent every time is the part that fails. Put the rule in your project instructions instead, in CLAUDE.md or whatever your client reads at startup, and it applies to every future post without you thinking about it.

CLAUDE.md
## Posting

When posting through the opentweet MCP server, always pass an explicit
platforms array. Omitting it follows the account cross-post setting,
which is not what we want here.

Default: platforms: ["x", "bluesky"]
X-only announcements: platforms: ["x"]

If unsure where a post will land, call opentweet_list_platforms first.

One thing to expect: Bluesky allows 300 characters and X allows 280, or 25,000 on Premium. A long post publishes on a Premium X account and comes back skipped on Bluesky with the reason attached, rather than being truncated or failing the call. Bluesky also takes up to 4 images at 2MB each with alt text and supports threads, but does not take video and returns no analytics.

7-day free trial. Cancel anytime.

Frequently asked questions

How do I get Claude Code to post my tweet to Bluesky too?

Add the OpenTweet MCP server with claude mcp add --transport http opentweet https://mcp.opentweet.io/mcp and an Authorization header carrying your ot_ key, connect both accounts once in the dashboard, then ask Claude to post with platforms set to ["x","bluesky"]. One tool call publishes a native post on each network.

Do I need a Bluesky API key for this?

No. Bluesky issues no API keys and runs no developer program, so there is nothing to apply for. You connect the account over atproto OAuth in the OpenTweet dashboard, which means signing in on the server that holds your account rather than pasting a credential anywhere.

Why did Claude post only to X?

Almost always because it omitted the platforms field. Omitting it does not mean X, it means follow the account auto cross-post setting, and if that setting is off the post lands on X alone. Tell the agent to pass an explicit platforms array, or turn the setting on.

How do I stop the agent forgetting on the next post?

Put the rule in your project instructions, in CLAUDE.md or the equivalent for your client: always pass an explicit platforms array on posting tools, and call opentweet_list_platforms if unsure where a post will land. That converts a per-conversation reminder into a standing rule.

What happens if the post is too long for Bluesky?

It is skipped on Bluesky with the reason recorded, and still publishes on X. Bluesky allows 300 characters against 280 on X, or 25,000 on a Premium X account, so long posts are the case where the two diverge. Nothing is truncated and the tool call does not fail outright.

Does this work in Claude Desktop and other MCP clients?

Yes. The same URL, https://mcp.opentweet.io/mcp, works in any MCP client: Claude Desktop, Cursor, Windsurf, Cline and OpenClaw among them. The server exposes 43 tools, and the posting ones take the same platforms parameter everywhere.

Give Claude Code both networks

One command, 43 tools, no X developer account and no Bluesky key. Flat $11.99 a month.

7-day free trial. Cancel anytime.