Updated October 2026
Give a Claude Agent SDK agent an X, LinkedIn and Bluesky tool
Pass OpenTweet's hosted MCP server to the Agent SDK's mcpServers option with your ot_ key in the Authorization header, and the agent gets 43 tools for posting, threads and scheduling. No X developer account is needed, and plans start at $11.99 a month.
The same entry works in TypeScript (@anthropic-ai/claude-agent-sdk) and Python (claude-agent-sdk). Both are below, along with the permission rule that trips most people up.
7-day free trial. Cancel anytime.
What your agent can do
All 43 tools arrive with one server entry. You do not write a tool wrapper for any of them.
Post now
opentweet_create_tweet with publish_now publishes the moment the agent calls it.
Schedule
Pass scheduled_date on a new post, or schedule existing drafts with opentweet_schedule_tweet and opentweet_batch_schedule.
Threads
opentweet_create_thread ships a connected thread in one call.
43 tools
Posts, threads, articles, evergreen, media and analytics, with no tool code to write.
Three networks
Pass platforms ["x","linkedin","bluesky"] and one call posts to all three.
No X API
No developer account, no OAuth to build, no per-post billing.
Install and set two keys
The Agent SDK needs Node.js 18+ or Python 3.10+ and an Anthropic API key. OpenTweet needs its own ot_ key, which you copy from the dashboard after connecting your accounts. The SDK does not load .env files for you, so export both in the shell that runs the agent or load them yourself.
# TypeScript
npm install @anthropic-ai/claude-agent-sdk
# Python
pip install claude-agent-sdk
# Both SDKs read these from the environment
export ANTHROPIC_API_KEY=your-anthropic-key
export OPENTWEET_API_KEY=ot_your_keyTypeScript
A remote server takes type: "http", a url and a headers object. The server name you pick, here opentweet, becomes the middle part of every tool name.
import { query } from "@anthropic-ai/claude-agent-sdk";
for await (const message of query({
prompt: 'Post "Shipped v2.3: exports are 40% faster." to X and Bluesky now.',
options: {
mcpServers: {
opentweet: {
type: "http",
url: "https://mcp.opentweet.io/mcp",
headers: {
Authorization: `Bearer ${process.env.OPENTWEET_API_KEY}`,
},
},
},
allowedTools: ["mcp__opentweet__*"],
},
})) {
if (message.type === "system" && message.subtype === "init") {
console.log("MCP servers:", message.mcp_servers);
}
if (message.type === "result" && message.subtype === "success") {
console.log(message.result);
}
}Python
Same fields, snake_case options: mcp_servers and allowed_tools on ClaudeAgentOptions.
import asyncio
import os
from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage, SystemMessage
async def main():
options = ClaudeAgentOptions(
mcp_servers={
"opentweet": {
"type": "http",
"url": "https://mcp.opentweet.io/mcp",
"headers": {"Authorization": f"Bearer {os.environ['OPENTWEET_API_KEY']}"},
}
},
allowed_tools=["mcp__opentweet__*"],
)
async for message in query(
prompt='Post "Shipped v2.3: exports are 40% faster." to X and Bluesky now.',
options=options,
):
if isinstance(message, SystemMessage) and message.subtype == "init":
print("MCP servers:", message.data.get("mcp_servers"))
if isinstance(message, ResultMessage) and message.subtype == "success":
print(message.result)
asyncio.run(main())The init message lists each server with a status. connected means the key worked. failed or needs-auth means the agent is running without the OpenTweet tools, usually because the key is missing or wrong. pending on its own is not a failure: the server may still be connecting.
Allowing the tools
MCP tools follow the pattern mcp__<server-name>__<tool-name>. OpenTweet's tools already start with opentweet_, so the full name repeats it: mcp__opentweet__opentweet_create_tweet. Without an allowedTools entry, Claude sees the tools but cannot call them.
mcp__opentweet__* allows all of them, including delete and DM campaign tools. For an agent that only posts, list the ones it needs:
allowedTools: [
"mcp__opentweet__opentweet_list_platforms",
"mcp__opentweet__opentweet_create_tweet",
"mcp__opentweet__opentweet_create_thread",
"mcp__opentweet__opentweet_schedule_tweet",
"mcp__opentweet__opentweet_list_tweets",
]Prefer allowedTools to a permission mode here. Anthropic notes that acceptEdits does not approve MCP tools, and bypassPermissions approves them but also switches off most other safety prompts.
Develop against drafts or a test account
An allowed tool runs with no human in the loop. While you build, tell the agent not to publish: a post with neitherpublish_now nor scheduled_date is saved as a draft you can review in OpenTweet. Or connect a throwaway X test account and have the agent target it by passing the ID from opentweet_list_accounts as x_account_id. Switch to your real profiles only once the prompts behave.Key or OAuth? Use the key
OpenTweet's hosted server also supports OAuth sign-in, which is how chat apps such as Claude connect with no key. That flow needs a person to click Allow. The Agent SDK does not open a browser or run an interactive OAuth flow: a server that asks for authorization reports needs-auth and the agent carries on without its tools. A headless agent should send the ot_ key.
| Route | Fits | Setup | For an Agent SDK agent |
|---|---|---|---|
| Hosted MCP + ot_ Bearer key | Agent SDK agents, cron jobs, servers, CI | headers: { Authorization: "Bearer ot_..." } | Use this |
| Hosted MCP + OAuth sign-in | Chat apps where a person clicks Allow, such as Claude | Add the URL, sign in to OpenTweet | Not for headless agents |
| npm package over stdio | Running the server as a local process | command: "npx", args: ["-y", "@opentweet/mcp-server"] | Works, more to maintain |
| REST, POST /api/v1/posts | Scripts with no model in the loop | One HTTP call with the same key | Use when no agent decides |
Or keep it in .mcp.json
With default query() options the SDK also loads servers from a .mcp.json at the project root (if you set settingSources yourself, include "project"), with ${OPENTWEET_API_KEY} expanded from the environment at runtime. That keeps the key out of the file, which matters because the file usually sits in the repository. You still need the allowedTools entry.
{
"mcpServers": {
"opentweet": {
"type": "http",
"url": "https://mcp.opentweet.io/mcp",
"headers": {
"Authorization": "Bearer ${OPENTWEET_API_KEY}"
}
}
}
}Prompts that work
Name the networks every time. A post that leaves platforms out follows your account's auto cross-post setting, which may not be what you meant.
Draft a post about today's release for X and LinkedIn. Do not publish it.
Write a 4 part thread from CHANGELOG.md and post it to X and Bluesky now.
Post the release note to all three networks: platforms ["x","linkedin","bluesky"].
Write five drafts with platforms ["x"], then schedule them for 9am UTC
on weekdays next week with opentweet_batch_schedule.Scheduling
opentweet_schedule_tweet takes an ISO 8601 time such as 2026-10-20T09:00:00Z. Once scheduled, OpenTweet sends the post at its time, whether or not your agent process is still running.
Per-network limits
If X is a target and the text is over its limit, the call fails. LinkedIn allows 3,000 characters and gets a thread as one post. A post too long for Bluesky or LinkedIn is skipped there with a reason and still goes to the others.
Plans and limits
Every plan includes the API and the MCP server. Account limits apply per network. LinkedIn means personal profiles only.
| Plan | Price | X accounts | LinkedIn profiles | Bluesky accounts | Posts with links per day |
|---|---|---|---|---|---|
| Pro | $11.99/month | 1 | 1 | 1 | 0 |
| Advanced | $29/month | 3 | 3 | 3 | 10 |
| Agency | $49/month | 10 | 10 | 10 | 20 |
Over the link allowance, OpenTweet removes the URL and posts the text. URL credits cover overflow on any plan.
The REST fallback
If no model needs to decide anything, for example a nightly job that posts a fixed message, skip the agent. Same key, one endpoint.
curl -X POST https://opentweet.io/api/v1/posts \
-H "Authorization: Bearer ot_your_key" \
-H "Content-Type: application/json" \
-d '{"text":"Shipped v2.3.","platforms":["x","linkedin","bluesky"],"scheduled_date":"2026-10-20T09:00:00Z"}'Full field reference in the API docs. Tool details are in the MCP docs.
Frequently asked questions
How does a Claude Agent SDK agent post to X?
Add OpenTweet's hosted MCP server to the mcpServers option (mcp_servers in Python) with type "http", the URL https://mcp.opentweet.io/mcp and an Authorization: Bearer ot_ header. Allow the tools with allowedTools set to mcp__opentweet__*. The agent then has 43 tools, including opentweet_create_tweet, and posts to X through OpenTweet.
Can the same agent post to LinkedIn and Bluesky?
Yes. Connect LinkedIn and Bluesky in OpenTweet settings, then have the agent pass platforms ["x","linkedin","bluesky"] on a post. One tool call goes to all three. LinkedIn means your personal profile. Company pages are not supported.
Why use an ot_ key and not OAuth?
The Agent SDK does not open a browser or run an interactive OAuth flow. Anthropic documents that a server which answers with an authorization challenge reports the status needs-auth and the run continues without its tools. A headless agent should send the ot_ key in the headers. OAuth sign-in is for chat apps such as Claude, where a person clicks Allow.
Why does my agent see the tools but never call them?
MCP tools need explicit permission in the Agent SDK. Without an allowedTools entry, Claude sees the tools but cannot use them. Add mcp__opentweet__* to allow every OpenTweet tool, or list single tools such as mcp__opentweet__opentweet_create_tweet.
Do I need an X developer account?
No. OpenTweet holds the X connection, the OAuth flow and token refresh. Your agent authenticates to OpenTweet with one ot_ key, and the same key covers LinkedIn and Bluesky once they are connected.
Can the agent post links?
Only within your plan allowance. Pro includes 0 posts with links per day, Advanced 10 and Agency 20. Over the allowance OpenTweet removes the URL and still posts the text. URL credits cover overflow on any plan.
Keep exploring
The Agent SDK is one client of many. The same hosted MCP server works everywhere.
Claude Code
The same hosted server from one claude mcp add command.
Can Claude post to social media?
Every Claude surface, and which ones can post.
OpenAI Agents SDK
The same tools for an OpenAI agent, with function tool or MCP.
The OpenTweet MCP server
Every tool, the hosted endpoint, and the npm package.
Is an MCP server safe on my X account?
What a write tool inside an agent can and cannot do.
REST API docs
POST /api/v1/posts, for scripts and CI rather than agent turns.
Give your agent accounts it can post to
Connect X, LinkedIn or Bluesky, copy your key, add one mcpServers entry.
7-day free trial. Cancel anytime.