← Social media scheduling for AI agents

Schedule social media posts with MCP

CrossPostingPal exposes a Model Context Protocol (MCP) server so MCP-compatible agents can discover your connected social accounts, create drafts and schedule posts — through the same publishing engine as the dashboard. Nothing is published outside your normal queue.

In short: how to schedule posts with MCP

  1. Connect your social accounts in CrossPostingPal.
  2. Add the endpoint below to your AI client — sign in with OAuth, or paste a personal access token.
  3. Ask your agent to list your accounts, create drafts and schedule the ones you approve.

New to MCP? Read the step-by-step guide to scheduling social media posts with MCP.

Endpoint

POST https://api.crosspostingpal.com/api/mcp

Authorization: Bearer cpp_pat_…

Auth: personal access token, or OAuth 2.1 (PKCE) for Hermes / ChatGPT / Claude

Transport: Streamable HTTP (JSON-RPC 2.0)

The server implements initialize, tools/list and tools/call, including batch requests and notifications. All tools are request/response — there is no SSE channel.

1. Create an API token

  1. Log in to CrossPostingPal and go to Settings → Developer / AI Agents.
  2. Click Create token, give it a name (e.g. “Cursor on my laptop”).
  3. Optionally restrict scopes or set an expiry.
  4. Copy the token immediately — it is shown only once and only a hash is stored. Tokens look like cpp_pat_…
Treat a token like a password: never commit it to source control, never paste it into a chat, and revoke it if it may have leaked. You can create separate tokens per client.

2. Configure your MCP client

Cursor

Add to ~/.cursor/mcp.json (global) or .cursor/mcp.json (project). Cursor auto-detects Streamable HTTP from the url field.

{
  "mcpServers": {
    "crosspostingpal": {
      "url": "https://api.crosspostingpal.com/api/mcp",
      "headers": {
        "Authorization": "Bearer cpp_pat_YOUR_TOKEN"
      }
    }
  }
}

Claude Code

claude mcp add --transport http crosspostingpal https://api.crosspostingpal.com/api/mcp \
  --header "Authorization: Bearer cpp_pat_YOUR_TOKEN"

Claude (claude.ai / Desktop)

Settings → Connectors → Add custom connector → enter the endpoint URL above → under Request headers add Authorization: Bearer cpp_pat_…. If request headers are unavailable on your plan, Claude Desktop can bridge through mcp-remote in claude_desktop_config.json:

{
  "mcpServers": {
    "crosspostingpal": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote",
        "https://api.crosspostingpal.com/api/mcp",
        "--header",
        "Authorization:${AUTH_HEADER}"
      ],
      "env": {
        "AUTH_HEADER": "Bearer cpp_pat_YOUR_TOKEN"
      }
    }
  }
}

Codex

Codex stores the environment-variable name, not the token — export CPP_MCP_TOKEN in the environment where you run Codex.

# ~/.codex/config.toml
[mcp_servers.crosspostingpal]
url = "https://api.crosspostingpal.com/api/mcp"
bearer_token_env_var = "CPP_MCP_TOKEN"

Or via the CLI:

codex mcp add crosspostingpal --url https://api.crosspostingpal.com/api/mcp \
  --bearer-token-env-var CPP_MCP_TOKEN

Hermes Agent

Add CPP to the configuration of the Hermes profile running your assistant:

# ~/.hermes/config.yaml (merge with your existing entries)
mcp_servers:
  crosspostingpal:
    url: "https://api.crosspostingpal.com/api/mcp"
    auth: oauth

Run this in a fresh terminal on the Hermes host and complete the CPP OAuth sign-in:

hermes mcp login crosspostingpal

Start a new session or restart your messaging gateway, then ask Hermes to list your CPP accounts and create a draft. Follow the Hermes workflow and remote-host setup links.

ChatGPT (developer mode)

ChatGPT connects with OAuth — no token to copy. Verified end-to-end: any ChatGPT user on a paid plan can connect in under a minute:

  1. In ChatGPT, go to Settings → Apps → Advanced settings and enable Developer mode (on Business/Enterprise workspaces an admin enables it first).
  2. Back in Apps, click Create → Create MCP app.
  3. Name it (e.g. CrossPostingPal), set the URL to https://api.crosspostingpal.com/api/mcp and choose OAuth as authentication.
  4. ChatGPT registers itself automatically (no client ID to copy) and opens a CrossPostingPal sign-in page — approve the permissions and you're connected.

The same OAuth flow works for Claude custom connectors. Disconnect anytime under Settings → Developer / AI Agents → Connected apps. Publishing immediately (posts:publish) and writing comment automations (automations:write) are off by default on the consent screen.

Publishing skills, plugins and more MCP clients

OpenClaw

Install the CPP publishing skill. Download and extract the skill below. Install the directory containing SKILL.md with the command shown below, then start a new OpenClaw session.

openclaw skills install /absolute/path/to/crosspostingpal --as crosspostingpal

# In an interactive terminal on the agent host:
python3 /absolute/path/to/crosspostingpal/scripts/cpp_mcp.py configure
python3 /absolute/path/to/crosspostingpal/scripts/cpp_mcp.py accounts

Claude Cowork

Install the CPP plugin and connect with OAuth. Download the plugin below. In Claude Desktop, open Cowork → Customize → Plugins and upload the custom plugin file. Workspace settings may control plugin installation.

/crosspostingpal:campaign
/crosspostingpal:release
/crosspostingpal:queue

Claude Code mods

Install the CPP release plugin with a Code mod. Download and extract the release mod package. Start a trusted Claude Code session with the --plugin-dir command below. Workspace policies may control whether mods can load.

claude --plugin-dir /absolute/path/to/extracted/crosspostingpal-release

# Inside Claude Code:
/mcp
/crosspostingpal-release:release
/cpp-activity
/crosspostingpal-release:queue

OpenCode

Connect through remote MCP with OAuth. Merge the configuration below into your OpenCode opencode.json. Use the global config location for access across projects; preserve existing entries.

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "crosspostingpal": {
      "type": "remote",
      "url": "https://api.crosspostingpal.com/api/mcp",
      "enabled": true
    }
  }
}

Cursor

Connect through remote MCP with OAuth. Merge the configuration below into ~/.cursor/mcp.json for global access or .cursor/mcp.json for this project.

{
  "mcpServers": {
    "crosspostingpal": {
      "url": "https://api.crosspostingpal.com/api/mcp"
    }
  }
}

Gemini CLI

Connect through HTTP MCP with OAuth. Merge the configuration below into ~/.gemini/settings.json or your project’s .gemini/settings.json. Use httpUrl for CPP and preserve existing entries.

{
  "mcpServers": {
    "crosspostingpal": {
      "httpUrl": "https://api.crosspostingpal.com/api/mcp"
    }
  }
}

OpenAI dots and Cue

OpenAI dots

Connect the CPP MCP app in ChatGPT with OAuth as described above and make it available through your app permissions. Your dot uses the connected app to discover accounts, create drafts and schedule approved posts. Follow the dots workflow.

Cue agent skill

Import the CPP skill into Cue and assign it to your publishing agent. The bundled Python client calls this MCP endpoint directly. Configure a separate personal access token as CPP_MCP_TOKEN in the agent environment or in a private ~/.config/crosspostingpal/token file. Keep the token out of chat. Python 3.9 or later is required; no additional packages are needed.

Download the CPP agent skill
python3 scripts/cpp_mcp.py accounts
python3 scripts/cpp_mcp.py tools
python3 scripts/cpp_mcp.py call create_post_draft --args-file draft.json
Follow the full Cue setup guide.

3. Verify the connection

A raw list_social_accounts call looks like this:

POST https://api.crosspostingpal.com/api/mcp
Authorization: Bearer cpp_pat_YOUR_TOKEN
Content-Type: application/json

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "list_social_accounts",
    "arguments": {}
  }
}

Then ask your agent: “Schedule ‘We just launched X’ tomorrow at 10:00 on LinkedIn and Instagram.” The agent resolves your account IDs and calls create_and_schedule_post:

{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "create_and_schedule_post",
    "arguments": {
      "text": "We just launched X",
      "socialAccountIds": [123, 124],
      "scheduledAt": "2026-09-22T10:00:00+02:00"
    }
  }
}

Tools

ToolScopeWhat it doesParameters
list_social_accountsaccounts:readLists your connected social accounts: id, platform, username, authorization status and capabilities (canPublish, supportsScheduling, requiresMedia). Call this first to discover socialAccountIds.—
create_post_draftposts:writeCreates a draft visible in the normal CrossPostingPal UI. Nothing is published until scheduled.text, socialAccountIds[], mediaUrls[]?, postType?, platformParameters?
create_and_schedule_postposts:writeCreates and schedules a post in one call. The post appears in your scheduled queue and is published by the normal scheduler.text, socialAccountIds[], scheduledAt, timezone?, mediaUrls[]?, postType?, platformParameters?
schedule_postposts:writeSchedules an existing draft post.postId, scheduledAt, timezone?
publish_nowposts:publishPublishes immediately — same as "Post now" in the UI. Use only when the user explicitly asks; otherwise prefer draft/scheduled so the post stays reviewable.text, socialAccountIds[], mediaUrls[]?, postType?, platformParameters?
upload_mediaposts:writeUploads one base64 media file to CrossPostingPal storage and returns a public mediaUrl for mediaUrls. For large files, host externally and pass the URL instead.contentType, dataBase64
list_scheduled_postsposts:readLists upcoming scheduled posts (default window: now to +90 days, max 100).fromUtc?, toUtc?
get_postposts:readReturns status, schedule time, content and per-channel results of one of your posts.postId
list_automation_capabilitiesautomations:readShows which of your connected accounts support comment automations (Instagram business/creator only) and whether your plan includes the feature.—
list_comment_automationsautomations:readLists your Instagram comment-to-DM automations. Pass postId to filter to one post (includes stats).postId?
get_comment_automationautomations:readReturns one automation with live stats: comments seen, matches, DMs and public replies sent, failures.automationId
create_comment_automationautomations:writeCreates an Instagram comment-to-DM automation on one post (postId or externalPostUrl). When a comment matches the keyword, a private DM reply is sent; optional public reply.socialAccountId, keyword, postId?, externalPostUrl?, matchMode?, publicReplyEnabled?, publicReplyText?, privateReplyEnabled?, privateReplyText?, isActive?
update_comment_automationautomations:writeUpdates keyword, match mode, reply texts or active state of an existing automation (isActive=false pauses it).automationId, keyword?, matchMode?, publicReplyEnabled?, publicReplyText?, privateReplyEnabled?, privateReplyText?, isActive?
delete_comment_automationautomations:writePermanently deletes a comment automation.automationId

Notes & limits

  • Time zones: prefer an explicit ISO 8601 offset in scheduledAt (e.g. +02:00 or Z). Without an offset, the timezone parameter (IANA name) is applied; otherwise UTC.
  • Media: Instagram, TikTok and Dribbble require public mediaUrls that stay reachable until publish time (max 10). Either pass external URLs or upload first with upload_media — it returns a hosted mediaUrl.
  • Rate limits: the endpoint is rate-limited per user and per token, with an extra cap on schedule operations. Exceeding them returns HTTP 429.
  • Scope errors: calling a tool without the required scope returns a JSON-RPC error (-32001) naming the missing scope.
  • Revocation: revoking a token in Settings takes effect immediately; the client will receive HTTP 401 on the next request.
  • Comment automations: the *_comment_automation tools manage Instagram comment-to-DM automations — keyword triggers that send a private DM (and optionally a public reply) when someone comments on a post. Instagram accounts only; automations:write is opt-in on the OAuth consent screen.
  • What agents can’t do (yet): edit or delete posts, manage account connections or read analytics.

Frequently asked questions

How do I schedule social media posts with MCP?

Connect your social accounts in CrossPostingPal, add the MCP endpoint to your AI client (OAuth for ChatGPT and Claude connectors, a personal access token for Cursor, Claude Code and Codex), then ask the agent to list your accounts, create drafts and schedule the ones you approve.

Which AI clients can schedule posts through CrossPostingPal MCP?

Any client that supports remote MCP. Setup is documented for Claude, ChatGPT in developer mode, Cursor, Claude Code, Codex and Hermes Agent, with additional guides for OpenClaw, OpenCode, Gemini CLI and Cue.

Can an AI agent publish without my approval?

Agents create drafts and scheduled posts by default, and a scheduled post publishes at its chosen time. Publishing immediately requires the separate posts:publish permission, which is off by default on the OAuth consent screen. Revoking a token takes effect immediately.

Do I need to write code to connect an agent?

No. ChatGPT and Claude connectors need only the endpoint URL and an OAuth sign-in. Cursor, Claude Code and Codex need a short configuration snippet and a personal access token.

What can an agent not do yet?

Agents cannot edit or delete posts, manage account connections or read analytics. Instagram, TikTok and Dribbble posts need public media URLs.

Ready to connect?

Generate a token and point your agent at CrossPostingPal.