Social media MCP server
One MCP server for every network your agent posts to.
Hosted, Streamable HTTP, bearer-key auth. The same preflight, idempotency and receipts as the REST API.
- LinkedIn MCP server
Hosted LinkedIn MCP server for personal profiles. What each tool returns for LinkedIn, a worked dry-run session, the 60-day token, escaping, caps and error fixes.
- X (Twitter) MCP server
Hosted X MCP server. What each tool returns for X, the 280 weighted-character and $0.20 link-post rules, OAuth with refresh, and X-specific error fixes.
- Bluesky MCP server
Hosted Bluesky MCP server, live today. What each tool returns for Bluesky, app-password setup, facets, a worked session, caps and Bluesky error fixes.
Why use a hosted server instead of one per network?
Running your own MCP server for a network usually means registering your own developer app with that network, keeping its client secret on your machine, and running a separate server per platform. A hosted server needs one key and one connection, and the account owner approves access on the network's own screen through a connect link.
It also applies the same rules on every network before anything goes out: length counted the way each network counts it, duplicate text on the same account within 24 hours, image limits, and a per-account daily cap. Those checks are ordinary code with no AI calls, and a dry run returns each problem with a fix the agent can act on.
Which networks work today?
Five networks are live: X, Bluesky, LinkedIn (personal profiles), Mastodon (any server) and Telegram (channels and groups, through a bot). Instagram, Threads, Facebook, TikTok, YouTube, Pinterest and Reddit are coming; each needs the network's own review or is still being built. Video isn't supported on any network yet. The list_platforms tool always returns the current status, so an agent never has to guess.
Keeping a human in the loop
Agents can't complete OAuth for someone else, so a person always approves account access. For posting, the safest pattern is to have the agent call create_post with dry_run: true, show you the preview, and publish only after you confirm. Passing an idempotency_key means a retried tool call never posts twice.
An agent with a posting tool can publish something wrong faster than a person can read it. The server gives you four controls; use all of them.
- Dry run first.
dry_run: trueruns every preflight check and returns the exact text each account would get, without publishing or consuming an idempotency key. The checks are plain code with no AI calls and no cost. - Ask for approval. Tell the agent to show you the dry-run preview and wait for a yes. Leave your client's tool approval prompt on for
create_post, so the publish call itself needs a click. - Send an idempotency key. If the agent retries after a timeout with the same key and the same body, it gets the original post back instead of a second one.
- Rely on the caps. Each account has a fair-use cap per rolling 24 hours: 100 on X, 300 on Bluesky and Mastodon, 50 on LinkedIn, 500 on Telegram (
daily_cap_reached). Identical text to the same account within 24 hours is blocked withduplicate_content.
Every tool and its inputs
The server exposes eight tools. None of them is tied to one network: the same create_post call can target accounts on several networks at once, with a different text per network through platform_options. Inputs below are the real schema fields. The LinkedIn, X and Bluesky pages describe what each tool returns for that network.
list_platforms(no input): each platform's id, name, whether it's available on this server, and its limits:maxChars,maxImages,supportsVideo,dailyPostCap.list_accounts(platform?,external_ref?): connected accounts withid,platform,handle,display_name,status(activeorneeds_reauth) andconnected_at. The ids go intocreate_post.create_connect_link(platforms?,external_ref?,redirect_url?,expires_in?): a hosted URL the account owner opens.expires_inis 300 seconds to 30 days and defaults to 7 days.create_post:accounts(1 to 100 account ids),text(up to 10,000 characters before per-platform limits),media(up to 20 items of{url, type?: image|video, alt?}),platform_options(per-platform text, for example{"x": {"text": "..."}}),scheduled_at(ISO-8601 with offset, up to 365 days ahead),dry_run(default false),wait(default true on the MCP server, so the call returns per-account results),idempotency_key(up to 255 characters) andmetadata(any JSON object you want back on the post).get_post(id): the post with one target per account:status,url,external_post_id,attempts,next_attempt_at,published_at,verifiedanderror(code,message,fix,retryable).list_posts(status?,limit1 to 100, default 20,before?cursor): recent posts, newest first, withhas_moreandnext_cursor.cancel_post(id): cancels a scheduled post that hasn't started publishing. A post that is already publishing returnspost_not_cancelable.get_usage(no input): active accounts this month, posts, plan and estimated cost.
Set up in Claude Code, Cursor or Claude Desktop
Claude Code adds remote servers with claude mcp add --transport http and takes request headers with --header, per its MCP docs. Export your key first so it never lands in shell history as plain text, then run the command below.
The default scope is local (this project, only you). Add --scope user to load the server in every project. Avoid --scope project with a raw key: that scope writes .mcp.json in the project root, which is meant to be committed. Run claude mcp list to confirm the server shows as connected, or /mcp inside a session. Tools appear as mcp__socials__create_post and so on. Cursor and Claude Desktop follow in the next two sections; other clients are on the agent guides.
export SOCIALS_API_KEY=sk_...
claude mcp add --transport http socials https://socialsforai.vercel.app/api/mcp \
--header "Authorization: Bearer $SOCIALS_API_KEY"Cursor configuration
Cursor reads .cursor/mcp.json in a project or ~/.cursor/mcp.json for every project, and supports Streamable HTTP servers with url and headers. Cursor resolves ${env:NAME} inside headers, so the key can stay in your environment. Cursor asks for approval before running MCP tools by default; keep that on for create_post. More in the Cursor guide.
{
"mcpServers": {
"socials": {
"url": "https://socialsforai.vercel.app/api/mcp",
"headers": { "Authorization": "Bearer ${env:SOCIALS_API_KEY}" }
}
}
}Claude Desktop configuration
Claude Desktop launches local servers from claude_desktop_config.json (on macOS in ~/Library/Application Support/Claude/, on Windows in %APPDATA%\Claude\). mcp-remote bridges that to our HTTP server and forwards your key with --header. Its README notes that some clients, Claude Desktop on Windows among them, don't escape spaces inside args, so the header is written without a space after the colon and the Bearer sk_... value sits in env. Restart Claude Desktop after saving. More in the Claude Desktop guide.
{
"mcpServers": {
"socials": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://socialsforai.vercel.app/api/mcp",
"--header", "Authorization:${AUTH_HEADER}"],
"env": { "AUTH_HEADER": "Bearer sk_..." }
}
}
}Troubleshooting by error code
Every error carries a stable code, a message and a fix written for the agent to act on. Tool errors come back as an MCP error result whose text is the same JSON body the REST API returns. This is the full list of codes that behave the same on every network; the LinkedIn, X and Bluesky pages add the causes specific to each.
- HTTP 401 when the client connects: the
Authorizationheader is missing or the key is wrong. The server checks the bearer key before any tool runs. On the REST API the same problem returnsmissing_api_keyorinvalid_api_key. Check the header spelling (Authorization: Bearer sk_...) and that the environment variable is set in the process that launches the client. account_not_found(404): an id inaccountsdoesn't belong to this workspace, often because the agent invented one. The fix tells it to calllist_accounts.preflight_failed(422): the post would fail at least one check, and nothing was published. Theissuesarray lists every problem withcode,fieldandfix. Repeat the call withdry_run: trueuntilokis true.text_too_long,too_many_media,video_not_supported,empty_post: per-network content checks insidepreflight_failed. Each issue names the account and, for text, theplatform_optionsfield to set a shorter version in.account_needs_reauth: the account's token expired or was revoked. Callcreate_connect_linkwith that platform and send the URL to the account owner. The account keeps its id when reconnected.duplicate_content: the same text went to the same account in the last 24 hours. Vary the text, or set a per-platform version inplatform_options.daily_cap_reached: the account hit our fair-use cap for the rolling 24 hours. Passscheduled_atto post later.scheduled_in_pastorscheduled_too_far:scheduled_atis more than 5 minutes ago or more than 365 days ahead. Omit it to publish now.idempotency_key_reused(409): the key was already used with a different body. Use a new key for a different post; reuse a key only to retry the identical request.post_not_cancelable(409):cancel_postwas called on a post that already started publishing. Delete published copies on the network itself.platform_unavailable(400) fromcreate_connect_link, orplatform_not_configuredin a dry run: that network isn't live on this server.list_platformsshows which are.connect_link_expired(410): the link is past itsexpires_in. Create a new one.invalid_media_url,media_fetch_failedormedia_too_large: we couldn't download an image from a public http(s) URL, or it's over that network's size limit. Host the file publicly and pass its URL.platform_rate_limitedorplatform_unavailableon a target: the network said no for now. These are retryable; we try again after 30 seconds, 2 minutes, 10 minutes, 30 minutes and 2 hours, six attempts in total, then mark the targetfailed. Poll withget_postinstead of posting again.platform_rejected: the network refused the post after preflight passed. Its message is included; adjust the post and send it with a new idempotency key.plan_limit_active_accountsorplan_limit_posts: the Free plan's 3 active accounts or 100 posts a month is used up. Both are hard limits on Free only.
Questions
What people ask
Is there a free social media MCP server?
Yes. SocialsForAI's Free plan covers 3 active accounts and 100 posts a month, with the MCP server included. Paid plans add accounts and unlimited posts; every plan includes the MCP server, the REST API and webhooks.
Which MCP clients does it work with?
Any client that supports remote MCP servers over Streamable HTTP with a custom Authorization header, such as Claude Code and Cursor. Clients that only run local servers can connect through mcp-remote, which forwards the header. Setup guides are on the agent pages.
Does the agent see my social media passwords?
No. Account owners approve access on the network's own OAuth screen, or with a Bluesky app password, Mastodon access token or Telegram bot token, from a hosted connect link. Credentials are stored encrypted with AES-256-GCM and never returned by the API or the MCP server.
Can an agent spam my accounts with this?
Each account has a fair-use cap per rolling 24 hours (100 on X, 300 on Bluesky and Mastodon, 50 on LinkedIn, 500 on Telegram), identical text on the same account within 24 hours is blocked, and every post can go through a dry run first. You can also revoke the API key at any time.
Get an API key and send your first post in five minutes.