post2all
Programa una publicación y publícala a la vez en 13 redes sociales: X, LinkedIn, Instagram, TikTok, YouTube y más. Incluye un calendario de contenido, textos para cada cuenta, analíticas y un servidor MCP para agentes de IA.
Documentación
Get Started
Connect post2all to AI agents via the Model Context Protocol (MCP). This page covers connecting from coding tools like Cursor, Claude Code, and Codex.
Prerequisites
- Sign in to your post2all workspace in the browser.
- Make sure you have an active workspace selected before authorizing MCP access.
- Use the MCP server URL:
https://mcp.post2all.com/mcp
The MCP endpoint uses OAuth 2.1. Add the server URL in your client, then complete the browser-based sign-in and consent flow when the client prompts you. Long-lived sessions depend on the client requesting refresh-token-capable OAuth scopes such as offline_access.
Cursor
Create or update .cursor/mcp.json in your project, or ~/.cursor/mcp.json for a global setup:
{
"mcpServers": {
"post2all": {
"url": "https://mcp.post2all.com/mcp"
}
}
}
After adding the server, restart Cursor if needed and follow the OAuth prompt to sign in to post2all.
Claude Code
Add post2all as a remote HTTP MCP server:
claude mcp add --transport http post2all https://mcp.post2all.com/mcp
You can verify it from Claude Code with:
claude mcp list
Alternatively, add the JSON config to .mcp.json for a project-level setup:
{
"mcpServers": {
"post2all": {
"type": "http",
"url": "https://mcp.post2all.com/mcp"
}
}
}
When Claude Code first connects, complete the OAuth sign-in flow in the browser window it opens.
Codex CLI
Add the server to ~/.codex/config.toml:
[mcp_servers.post2all]
url = "https://mcp.post2all.com/mcp"
When Codex connects to the server, approve the OAuth flow and sign in to post2all in the browser.
OpenCode
Add the server to your opencode.json or opencode.jsonc config:
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"post2all": {
"type": "remote",
"url": "https://mcp.post2all.com/mcp",
"enabled": true
}
}
}
When OpenCode prompts for authorization, continue in the browser and grant MCP access to your active workspace.
Testing the connection
Restart your coding tool after changing MCP config, then ask the agent something like:
What post2all tools are available?
or:
List my connected post2all social accounts.
If the server fails to connect, check that the URL is exactly https://mcp.post2all.com/mcp, that your browser completed the sign-in flow, and that you had an active workspace selected when granting access.
Media uploads
Pick the media tool by where the file lives:
- Existing post2all media ID: pass it in
mediadirectly. - Public HTTPS URL or a file attachment your client passes natively:
upload_media. You can also reference a public URL inmediaas caller-managed media; it must stay reachable until publishing completes. - Local file, and the agent can run
curlor another HTTP client (Claude Code, Codex, Cursor, n8n):media_upload_create, then an HTTP PUT, thenmedia_upload_confirm. - MCP Apps host with local images and no native file object:
upload_media_widget.
The direct-upload flow has three steps:
- Call
media_upload_createwith the file's exact MIME type and size in bytes:
It returns a{ "filename": "./launch.mp4", "contentType": "video/mp4", "fileSize": 18874368 }mediaId, a presigneduploadUrlthat expires after 10 minutes, the requiredheaders, and a ready-to-runcurlExample. Accepted types are JPEG, PNG, GIF, WebP, MP4, QuickTime, and WebM. - Upload the bytes with exactly the returned
Content-TypeandContent-Length:curl -X PUT -H 'Content-Type: video/mp4' -H 'Content-Length: 18874368' \ --data-binary @'./launch.mp4' '<uploadUrl>' - Call
media_upload_confirmwith{ "mediaId": "<mediaId>" }. post2all checks that the stored file matches the declared type and size, then returns themediaIdandpublicUrl. Calling it again for a confirmed upload returns the same result.
Use the confirmed mediaId in post_validate and post_create. An unconfirmed media ID is rejected until you confirm it. If confirmation reports a mismatch, or the upload URL expired, start again with media_upload_create. Uploads that are never confirmed are deleted after 24 hours.
The CLI also uploads local files in one command:
npx @post2all/cli media upload ./photo.jpg --json
Analytics tools
The MCP server exposes three read-only analytics tools in addition to the publishing workflow:
analytics_account— account-level normalized metrics, time series, metric definitions, and previous-period comparisons. Defaults to the latest 30 inclusive UTC days; maximum 90 days.analytics_account_posts— provider-wide post performance with pagination and metric sorting. Supported platforms can return posts published outside post2all; useoriginto distinguish matched post2all posts from external provider posts.analytics_post— per-target analytics for one post2all post. One failed or unavailable provider does not hide successful analytics from other targets.
Use refresh: true only when the user explicitly wants the freshest provider data. Otherwise allow post2all's analytics cache to protect provider rate limits and improve response time.
Never infer a zero from an empty metric list. Check the returned status or analyticsStatus first, especially for no_data, reconnect_required, coming_soon, unavailable, and provider_error.
Dynamic options and lookups
publishing_schema returns discoveries (Pinterest boards, Discord and Slack destinations, TikTok creator restrictions) and, when present, lookups for each account. Call publishing_options once, only for accounts that return either. Instagram accounts connected through Facebook Login list "lookups": ["reelAudio"], and their reelAudioId field carries "lookup": "reelAudio"; pass reelAudioSearch to search Instagram's audio catalog:
{
"accountIds": ["acc_instagram_123"],
"reelAudioSearch": { "query": "lofi", "audioType": "music" }
}
Omit query for trending audio and use audioType: "original_sound" for creators' sounds. Each returned reelAudio track has id, title, artist, imageUrl, durationMs, and a temporary previewUrl. Put the chosen id in settings.reelAudioId on a target with exactly one video, optionally with reelAudioVolume and reelVideoVolume (1–100, default 100). Accounts without the lookup omit reelAudio, and post_validate rejects reelAudioId for them with a reconnect message. Instagram collaborators (up to 3 usernames without @) and Facebook video title are fixed fields in the schema and need no lookup. See Instagram collaborators and Reel audio.
Stories
Instagram and Facebook accounts return capability.story from publishing_schema. Set settings.placement to "story" to publish one image or video as a 24-hour Story: validate the media against capability.story.media instead of capability.media, omit every setting in capability.story.unsupportedFields (including caption, firstComment, and the Instagram Reel options), and tell the user that a Story never shows the post text. Run post_validate before post_create as usual.
First comments
X, Instagram, Facebook Pages, Threads, Bluesky, and Wircle targets accept an optional firstComment that the same account posts after that target publishes, plus firstCommentDelaySeconds (integer, 0–86400, counted from the moment that target is published). A non-zero delay without a comment is rejected. Comment limits are X 280, Instagram 2,200, Facebook 2,000, Threads 500, Bluesky 300, and Wircle 2,000 characters; the schema's capability.fields.firstComment.maxLength is authoritative. Instagram Story accounts and YouTube do not support first comments.
Agents follow the usual publishing workflow and check eligibility before adding the fields:
accounts_listto find the selected account IDs.publishing_schemaonce with every selected account ID. Each account returnsfirstComment: { available, reason }. Whenavailableisfalse(for example"Reconnect with comment permissions"on accounts connected before first comments launched), tell the user the reason and leave both fields out for that account.post_validatewith the constructed targets.- After the user confirms,
post_create.
publishing_schema arguments:
{ "accountIds": ["acc_x_123", "acc_threads_123"] }
post_validate arguments, then the same arguments for post_create:
{
"content": "post2all v3 is live.",
"targets": [
{
"platform": "twitter",
"accountId": "acc_x_123",
"settings": {
"firstComment": "Release notes: https://example.com/release-notes",
"firstCommentDelaySeconds": 60
}
},
{
"platform": "threads",
"accountId": "acc_threads_123",
"settings": { "firstComment": "What should we build next?" }
}
],
"delivery": { "mode": "now" }
}
post_get returns each target's firstComment delivery (status, dueAt, sentAt, platformCommentId, error), separate from the target's publish status. The MCP server does not expose first-comment retry or cancel tools: use the dashboard, the REST endpoints, the SDK, or the CLI. On X, each first comment is one additional X API create billed like a post, including the URL rate when the comment contains a link; mention this when you preview an X post with a first comment.
Comment automations
The comment_automation tool manages Instagram comment to DM automations on posts that are already live, including posts not published through post2all. One tool covers every action; pass action and that action's fields:
action | Fields | Result |
|---|---|---|
list | accountId?, enabled?, status?, profileId?, cursor?, limit? | Automations with pagination.nextCursor |
get | id | One automation with 7-day stats and its 10 latest deliveries |
create | accountId, platformPostId, settings | The automation, warnings, and created |
update | id, settings?, enabled? | The updated automation and warnings |
pause | id | The paused automation |
resume | id | The automation, on again; also clears a pause post2all applied |
delete | id | success: true |
Agents add an automation to an existing post in this order:
accounts_listto pick the connected Instagram account.- Find the post's
platformPostId. For a post2all post,posts_list, thenpost_get, and read the published Instagram target'splatformPostId. For any post on the account,analytics_account_postswithstartDateandendDateup to 90 days apart, paging withcursorand stepping back to earlier 90-day windows if the post is older. Each row hasplatformPostIdandplatformPostUrl. publishing_schemafor the account.capability.commentAutomation.availablemust betrue, andcapability.fieldshas theinstagramCommentHook*limits and enum values.- Confirm the rule with the user, then
comment_automationwithaction: "create". comment_automationwithaction: "get"to confirmstatusison.
create arguments:
{
"action": "create",
"accountId": "acc_ig_1",
"platformPostId": "17912345678901234",
"settings": {
"instagramCommentHookMatchMode": "keywords",
"instagramCommentHookKeywords": ["guide"],
"instagramCommentHookMatchType": "full_word",
"instagramCommentHookDmEnabled": true,
"instagramCommentHookReplyMessage": "Here you go: https://example.com/guide"
}
}
The automation answers comments made after it is created. Instagram allows one private reply per comment, sent within 7 days of the comment, so older comments are never DM'd, and post2all sends one DM per person per post. Creating on a post that already has an automation updates it (created: false). Treat every action except list and get as state-changing and confirm it with the user first. To add an automation while scheduling a new post, set the instagramCommentHook* fields on the Instagram target in post_validate and post_create instead.