How to Connect OpenClaw AI Agent to LinkedIn, Instagram, X, TikTok & 6 More Platforms Using Publora

Jane Ivanova

CEO, Publora

· Updated

How to Connect OpenClaw AI Agent to LinkedIn, Instagram, X, TikTok & 6 More Platforms Using Publora

TL;DR

A comprehensive guide with code samples showing how to connect OpenClaw AI agent to 10 social media platforms via Publora MCP server and REST API. Includes examples for LinkedIn, X, Instagram, Threads, TikTok, YouTube, Facebook, Bluesky, Mastodon, and Telegram.

What Is OpenClaw and Why It Matters for Social Media

OpenClaw is the open-source autonomous AI agent that has taken the developer world by storm — with over 190,000 GitHub stars and a thriving ecosystem. Built by Peter Steinberger (formerly known as Clawdbot, then Moltbot), OpenClaw is an agentic AI that can reason, plan multi-step workflows, call external tools, and execute complex tasks autonomously.

What makes OpenClaw uniquely powerful for social media management is its mcporter skill — a built-in MCP (Model Context Protocol) server manager that lets OpenClaw connect to external services like Publora. Once connected, you can manage your entire social media presence through natural conversation.

AI agent conversational interface for social media management

Imagine telling your AI agent: "Schedule a product launch announcement to LinkedIn, X, and Instagram for tomorrow at 9am" — and having it actually do it. That's what this guide will teach you to build.

Prerequisites

Before we begin, you'll need:

  • OpenClaw installed and running (see docs.openclaw.ai)
  • A Publora account — sign up free (free Starter plan; Pro from $3.99/account/month billed yearly)
  • Your Publora API key — found under API in the Publora dashboard sidebar (starts with sk_)
  • At least one connected social media account in Publora

Step 1: Connect OpenClaw to Publora via mcporter

OpenClaw uses mcporter — its built-in MCP server manager — to connect to external services. The connection takes about 60 seconds.

Option A: Add via mcporter CLI (Recommended)

From within OpenClaw, use the mcporter skill to add Publora as a remote MCP server:

# List available tools from Publora's MCP server
mcporter list --http-url https://mcp.publora.com --name publora --header "Authorization=Bearer sk_YOUR_API_KEY"

# Persist the configuration (including the header) so it's available across sessions
mcporter list --http-url https://mcp.publora.com --name publora --header "Authorization=Bearer sk_YOUR_API_KEY" --persist config/mcporter.json

Or call a Publora tool directly via URL (pass the key with --header):

# Call Publora tools directly via HTTP URL
mcporter call 'https://mcp.publora.com/mcp.list_connections' --header "Authorization=Bearer sk_YOUR_API_KEY"

Option B: Add to mcporter.json Config

You can also add Publora to your mcporter configuration file directly. mcporter reads config from ~/.mcporter/mcporter.json (global) or config/mcporter.json (project-level):

{
  "mcpServers": {
    "publora": {
      "url": "https://mcp.publora.com",
      "headers": {
        "Authorization": "Bearer sk_YOUR_API_KEY"
      }
    }
  }
}

Option C: Use Any MCP-Compatible Client

Since OpenClaw can use multiple CLI backends (including Claude Code), you can also configure Publora in your Claude Code MCP config (.mcp.json), Cursor (.cursor/mcp.json), or any MCP client:

{
  "mcpServers": {
    "publora": {
      "type": "http",
      "url": "https://mcp.publora.com",
      "headers": {
        "Authorization": "Bearer sk_YOUR_API_KEY"
      }
    }
  }
}

Once configured, OpenClaw gains access to 20 tools on every plan (32 with an Agency account): posts, media uploads, platform connections, Mastodon and Bluesky stats, and LinkedIn engagement (comments, reactions, reshares, mentions).

MCP configuration in terminal

Verify the connection by asking OpenClaw:

You: "List my connected social media accounts"

OpenClaw: I'll check your Publora connections...

Connected accounts:
• LinkedIn — John Doe (company page)
• X (Twitter) — @johndoe
• Instagram — @johndoe.official
• Threads — @johndoe.official
• TikTok — @johndoe
• YouTube — @johndoe
• Facebook — Acme Corp page
• Bluesky — @johndoe.bsky.social
• Mastodon — @johndoe@mastodon.social
• Telegram — @johndoe_updates

Step 2: Post to LinkedIn

LinkedIn is the most popular platform for professional content. Here's how to post using both MCP (conversational) and REST API (programmatic) approaches.

Via MCP (Conversational)

You: "Post to my LinkedIn: Excited to share our latest product update!
We've added AI-powered scheduling that saves teams 10+ hours per week.
Check it out → publora.com #ProductUpdate #AI"

OpenClaw: I'll publish that to your LinkedIn now...

✓ Posted to LinkedIn (John Doe - company page)
  Post ID: pg_abc123
  Status: published
  URL: https://linkedin.com/feed/update/urn:li:share:7123456789

Via REST API (Programmatic)

// Node.js / TypeScript
// Omitting scheduledTime creates a draft; the current time publishes right away.
const response = await fetch('https://api.publora.com/api/v1/create-post', {
  method: 'POST',
  headers: {
    'x-publora-key': 'sk_YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    content: `Excited to share our latest product update!
We've added AI-powered scheduling that saves teams 10+ hours per week.
Check it out → publora.com #ProductUpdate #AI`,
    platforms: ['linkedin-ABC123'], // platformId from GET /platform-connections
    scheduledTime: new Date().toISOString(),
  }),
});

const post = await response.json();
console.log('Queued:', post.postGroupId);
# Python
import requests
from datetime import datetime, timezone

response = requests.post(
    'https://api.publora.com/api/v1/create-post',
    headers={'x-publora-key': 'sk_YOUR_API_KEY'},
    json={
        'content': 'Excited to share our latest product update!',
        'platforms': ['linkedin-ABC123'],  # platformId from GET /platform-connections
        'scheduledTime': datetime.now(timezone.utc).strftime('%Y-%m-%dT%H:%M:%SZ'),
    }
)

print('Queued:', response.json()['postGroupId'])

LinkedIn limits: 3,000 characters per post, up to 10 images, videos up to 30 minutes / 500 MB, documents (PDF up to 100 MB), and multi-image posts (shown as a grid; swipeable organic carousels aren't available through the API).

Step 3: Post to X (Twitter)

X requires concise content. Publora automatically handles the 280-character limit and can create threads for longer content.

Via MCP

You: "Tweet this: Just shipped a major update to our scheduling engine.
AI agents can now post to 10 platforms with a single command.
The future of social media is autonomous. 🤖 publora.com"

OpenClaw: Publishing to X...

✓ Posted to X (@johndoe)
  Status: published

Via REST API

await fetch('https://api.publora.com/api/v1/create-post', {
  method: 'POST',
  headers: {
    'x-publora-key': 'sk_YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    content: 'Just shipped a major update to our scheduling engine. AI agents can now post to 10 platforms with a single command. 🤖',
    platforms: ['twitter-123456789'],
    scheduledTime: new Date().toISOString(),
  }),
});

X limits: 280 characters (or 25,000 for Premium users), up to 4 images (5 MB each, GIF allowed) or 1 video (up to 140 seconds / 512 MB) per post. Publora auto-threads longer content.

Step 4: Post to Instagram & Threads

Instagram and Threads are both Meta platforms but have different content requirements.

Social media scheduling across platforms

Instagram via MCP

You: "Post to Instagram with this image [upload photo].
Caption: Behind the scenes of building an AI-powered social media tool.
Our team shipped 47 features this month. #startup #buildinpublic #AI"

OpenClaw: I'll upload the image and post to Instagram...

✓ Posted to Instagram (@johndoe.official)
  Type: image post
  Status: published

Threads via MCP

You: "Post to Threads: Hot take — AI agents will manage 80% of social media
within 2 years. Here's why: they never sleep, they optimize posting times
automatically, and they can manage 100 accounts simultaneously."

OpenClaw: Publishing to Threads...

✓ Posted to Threads (@johndoe.official)
  Status: published

REST API for Both

# Post to both Instagram and Threads simultaneously
import requests
from datetime import datetime, timezone

BASE = 'https://api.publora.com/api/v1'
headers = {'x-publora-key': 'sk_YOUR_API_KEY'}

# 1. Create a draft (no scheduledTime) — Instagram needs media before scheduling
draft = requests.post(f'{BASE}/create-post', headers=headers, json={
    'content': 'Behind the scenes of building an AI-powered social media tool. 🚀',
    'platforms': ['instagram-17841412345678', 'threads-123456789'],
}).json()
post_group_id = draft['postGroupId']

# 2. Get a presigned upload URL attached to the draft
upload = requests.post(f'{BASE}/get-upload-url', headers=headers, json={
    'fileName': 'product-photo.jpg',
    'contentType': 'image/jpeg',
    'postGroupId': post_group_id,
}).json()

# 3. Upload the file (JPEG for Instagram)
with open('product-photo.jpg', 'rb') as f:
    requests.put(upload['uploadUrl'], data=f, headers={'Content-Type': 'image/jpeg'})

# 4. Schedule it (now = publish right away)
requests.put(f'{BASE}/update-post/{post_group_id}', headers=headers, json={
    'status': 'scheduled',
    'scheduledTime': datetime.now(timezone.utc).strftime('%Y-%m-%dT%H:%M:%SZ'),
})

print('Posted to Instagram + Threads:', post_group_id)

Instagram limits: 2,200 characters, requires at least one image or video, up to 10 carousel items, images up to 8 MB (JPEG, PNG or WebP), Reels up to 15 minutes / 300 MB, feed videos up to 60 minutes, carousel videos up to 60 seconds.

Threads limits: 500 characters, up to 20 images (8 MB each), videos up to 5 minutes / 1 GB.

Step 5: Post to TikTok

TikTok focuses on video content but also supports photo posts and carousels.

Via MCP

You: "Upload this video to TikTok with the caption:
How I automated my entire social media with AI 🤖
#AI #automation #socialmedia #techtok"

OpenClaw: Uploading video and posting to TikTok...

✓ Posted to TikTok (@johndoe)
  Type: video
  Status: published

Via REST API

const BASE = 'https://api.publora.com/api/v1';
const headers = { 'x-publora-key': 'sk_YOUR_API_KEY', 'Content-Type': 'application/json' };

// 1. Create a draft — TikTok needs a video before it can be scheduled
const { postGroupId } = await fetch(`${BASE}/create-post`, {
  method: 'POST',
  headers,
  body: JSON.stringify({
    content: 'How I automated my entire social media with AI 🤖 #AI #automation',
    platforms: ['tiktok-123456789'],
  }),
}).then(r => r.json());

// 2. Get a presigned upload URL for the video
const { uploadUrl } = await fetch(`${BASE}/get-upload-url`, {
  method: 'POST',
  headers,
  body: JSON.stringify({ fileName: 'demo-video.mp4', contentType: 'video/mp4', postGroupId }),
}).then(r => r.json());

// 3. Upload the video file
await fetch(uploadUrl, {
  method: 'PUT',
  body: videoBuffer,
  headers: { 'Content-Type': 'video/mp4' },
});

// 4. Schedule the post (now = publish right away)
await fetch(`${BASE}/update-post/${postGroupId}`, {
  method: 'PUT',
  headers,
  body: JSON.stringify({ status: 'scheduled', scheduledTime: new Date().toISOString() }),
});

TikTok limits: 2,200 characters, video up to 10 minutes / 4 GB, photo carousels up to 35 images.

Step 6: Post to YouTube

Publora uploads videos to YouTube, including Shorts.

You: "Upload this short video to YouTube with title 'AI Social Media Automation in 60 Seconds'
and description: Watch how OpenClaw + Publora automates posting to 10 platforms."

OpenClaw: Uploading to YouTube...

✓ Posted to YouTube (@johndoe)
  Type: Short
  Status: processing (YouTube processes videos asynchronously)

YouTube limits: Title up to 100 characters, description up to 5,000 characters, Shorts up to 3 minutes (YouTube's own limit), videos up to 12 hours / 256 GB.

Step 7: Post to Facebook

You: "Post to my Facebook page: We're thrilled to announce our new AI integration!
Manage all your social accounts from a single conversation with your AI assistant.
Try it free → publora.com"

OpenClaw: Publishing to Facebook...

✓ Posted to Facebook (Acme Corp page)
  Status: published
# Python REST API
import requests
from datetime import datetime, timezone

requests.post(
    'https://api.publora.com/api/v1/create-post',
    headers={'x-publora-key': 'sk_YOUR_API_KEY'},
    json={
        'content': 'We are thrilled to announce our new AI integration!',
        'platforms': ['facebook-123456789'],
        'scheduledTime': datetime.now(timezone.utc).strftime('%Y-%m-%dT%H:%M:%SZ'),
    }
)

Facebook limits: 63,206 characters, up to 10 images, video up to 45 minutes / 2 GB through the API (Reels up to 90 seconds / 1 GB).

Step 8: Post to Bluesky, Mastodon & Telegram

Publora also supports decentralized and messaging platforms.

Bluesky

You: "Post to Bluesky: The open web deserves open tools.
That's why we built MCP integration — any AI agent can now manage
your social media through an open protocol. publora.com"

OpenClaw: ✓ Posted to Bluesky (@johndoe.bsky.social)

Bluesky limits: 300 characters (with automatic facet detection for links and mentions), up to 4 images (2,000,000 bytes each) or one video (up to 3 minutes / 100 MB).

Mastodon

You: "Toot to my Mastodon: Open-source AI meets open-source social.
@openclaw + @publora = autonomous social media management.
No walled gardens. #fediverse #opensource #AI"

OpenClaw: ✓ Posted to Mastodon (@johndoe@mastodon.social)

Mastodon limits: 500 characters (varies by instance), up to 4 images, video up to about 99 MB by default (instance-configurable).

Telegram

You: "Send to my Telegram channel: 📢 New feature alert!
AI agents can now post to your Telegram channels automatically.
Connect your channel in Publora and start automating."

OpenClaw: ✓ Sent to Telegram channel (@johndoe_updates)

Telegram limits: 4,096 characters (1,024 for media captions), up to 10 images per post, images up to 10 MB and videos up to 50 MB through the Bot API, and Markdown formatting.

Cross-Platform Posting: All Platforms at Once

The real power comes from posting to multiple platforms simultaneously. OpenClaw handles this elegantly:

Cross-platform social media management dashboard

You: "Post this to ALL my connected accounts:
Big news — we just crossed 10,000 users! 🎉
Thank you to everyone who believed in us from day one.
Here's to the next 10,000. publora.com"

OpenClaw: I'll post to every connected account that accepts text-only posts...

✓ LinkedIn — published
✓ X (Twitter) — published
✓ Threads — published
✓ Bluesky — published
✓ Telegram — published
✓ Facebook — published
✓ Mastodon — published
– Instagram — skipped (it needs an image or video)
– TikTok — skipped (it needs an image or video)
– YouTube — skipped (it needs a video)

Posted to 7 platforms successfully.

REST API for Cross-Platform

const BASE = 'https://api.publora.com/api/v1';
const headers = { 'x-publora-key': 'sk_YOUR_API_KEY', 'Content-Type': 'application/json' };

// Get all connections first
const { connections } = await fetch(`${BASE}/platform-connections`, { headers }).then(r => r.json());

// Text-only post: skip platforms that require media (Instagram, TikTok, YouTube)
// and Pinterest, which is connect-only
const platformIds = connections
  .map(c => c.platformId)
  .filter(id => !/^(instagram|tiktok|youtube|pinterest)-/.test(id));

const post = await fetch(`${BASE}/create-post`, {
  method: 'POST',
  headers,
  body: JSON.stringify({
    content: 'Big news — we just crossed 10,000 users! 🎉',
    platforms: platformIds,
    scheduledTime: new Date().toISOString(),
  }),
}).then(r => r.json());

console.log(`Queued for ${platformIds.length} accounts:`, post.postGroupId);

Scheduling Posts for Later

Schedule posts in advance — perfect for content calendars:

You: "Schedule a LinkedIn post for next Monday at 9am EST:
Monday motivation — The best time to start automating your social media was yesterday.
The second best time is now. publora.com/start"

OpenClaw: Scheduled for Monday, Dec 7 at 9:00 AM EST.

Post details:
  Platform: LinkedIn
  Status: scheduled
  Scheduled: 2026-12-07T14:00:00Z
# Python — Schedule a post for a specific time
import requests
from datetime import datetime, timedelta, timezone

now = datetime.now(timezone.utc)
next_monday = now + timedelta(days=(7 - now.weekday()) % 7 or 7)
scheduled_time = next_monday.replace(hour=14, minute=0, second=0, microsecond=0).strftime('%Y-%m-%dT%H:%M:%SZ')

requests.post(
    'https://api.publora.com/api/v1/create-post',
    headers={'x-publora-key': 'sk_YOUR_API_KEY'},
    json={
        'content': 'Monday motivation — start automating today.',
        'platforms': ['linkedin-ABC123'],
        'scheduledTime': scheduled_time,
    }
)

Bulk Scheduling: A Week of Content in 60 Seconds

You: "Schedule these posts for the week:
- Monday 9am LinkedIn: 'Weekly industry roundup — top 5 AI developments'
- Tuesday 2pm X + LinkedIn: 'New blog post: How we reduced churn by 40%'
- Wednesday 10am Instagram: 'Team photo from our offsite' [attach image]
- Thursday 3pm X: 'Quick tip: Use AI agents to 10x your posting frequency'
- Friday 9am All platforms: 'Happy Friday! What are you building this weekend?'"

OpenClaw: Scheduling 5 posts across the week...

✓ Mon 9:00 AM — LinkedIn (1 platform)
✓ Tue 2:00 PM — X + LinkedIn (2 platforms)
✓ Wed 10:00 AM — Instagram (1 platform, with image)
✓ Thu 3:00 PM — X (1 platform)
✓ Fri 9:00 AM — All text-capable accounts (7 platforms)

All 5 posts scheduled. Total: 12 platform posts.

LinkedIn Analytics: Track Your Performance

LinkedIn post metrics (impressions, reach, reactions, comments, reshares), follower counts and profile summaries come from Publora's REST API, not from MCP tools; the MCP server's own post_stats and profile_stats tools cover Mastodon and Bluesky. All of these stats need the Pro plan.

You: "How did my LinkedIn product update post perform?"

OpenClaw: LinkedIn stats aren't an MCP tool, so I'll call Publora's REST API
(POST /linkedin-post-statistics, queryTypes: "ALL") for that post...

"Product update announcement" (urn:li:share:123456789)
• Impressions: 2,100
• Members reached: 1,480
• Reactions: 28
• Comments: 5
• Reshares: 3
// REST API — Get LinkedIn post stats
const stats = await fetch('https://api.publora.com/api/v1/linkedin-post-statistics', {
  method: 'POST',
  headers: { 'x-publora-key': 'sk_YOUR_API_KEY', 'Content-Type': 'application/json' },
  body: JSON.stringify({
    postedId: 'urn:li:share:123456789',
    platformId: 'linkedin-ABC123',
    queryTypes: 'ALL',
  }),
}).then(r => r.json());

console.log(stats);

Media Uploads: Images, Videos, and Documents

Publora uses a 3-step presigned URL process for media uploads:

const BASE = 'https://api.publora.com/api/v1';
const headers = { 'x-publora-key': 'sk_YOUR_API_KEY', 'Content-Type': 'application/json' };

// Step 1: Create a draft post (no scheduledTime)
const { postGroupId } = await fetch(`${BASE}/create-post`, {
  method: 'POST',
  headers,
  body: JSON.stringify({
    content: 'Check out our new campaign!',
    platforms: ['linkedin-ABC123', 'instagram-17841412345678', 'twitter-123456789'],
  }),
}).then(r => r.json());

// Step 2: Request an upload URL attached to the draft
const { uploadUrl, mediaId } = await fetch(`${BASE}/get-upload-url`, {
  method: 'POST',
  headers,
  body: JSON.stringify({ fileName: 'campaign-banner.jpg', contentType: 'image/jpeg', postGroupId }),
}).then(r => r.json());

// Step 3: Upload the file to the presigned URL
await fetch(uploadUrl, {
  method: 'PUT',
  body: fileBuffer,
  headers: { 'Content-Type': 'image/jpeg' },
});

// Optional: validate the upload right away
await fetch(`${BASE}/complete-media/${mediaId}`, { method: 'POST', headers });

// Step 4: Schedule the post
await fetch(`${BASE}/update-post/${postGroupId}`, {
  method: 'PUT',
  headers,
  body: JSON.stringify({
    status: 'scheduled',
    scheduledTime: new Date(Date.now() + 3600e3).toISOString(), // one hour from now
  }),
});

Via MCP, media handling is even simpler — just reference files or URLs and OpenClaw handles the upload process automatically.

Building an Autonomous Social Media Agent

Here's a complete example of an autonomous social media agent using Python with the MCP SDK to connect to Publora:

Autonomous AI agent system architecture

# autonomous_social_agent.py
# Connect to Publora MCP server programmatically

import asyncio
from contextlib import asynccontextmanager
from mcp import ClientSession
from mcp.client.streamable_http import streamablehttp_client
from datetime import datetime, timedelta, timezone

PUBLORA_KEY = "sk_YOUR_API_KEY"
MCP_URL = "https://mcp.publora.com"

@asynccontextmanager
async def get_session():
    """Connect to Publora MCP server."""
    headers = {"Authorization": f"Bearer {PUBLORA_KEY}"}
    async with streamablehttp_client(MCP_URL, headers=headers) as (read, write, _):
        async with ClientSession(read, write) as session:
            await session.initialize()
            yield session

# Connection IDs as returned by list_connections (platformId values)
PLATFORM_IDS = ["linkedin-ABC123", "twitter-123456789", "bluesky-did:plc:abc123"]

async def post_to_all_platforms(content: str, schedule_time: str = None):
    """Post content to the listed connected accounts (now, or at schedule_time)."""
    async with get_session() as session:
        params = {
            "content": content,
            "platforms": PLATFORM_IDS,
            # A time is required to publish; omitting it would create a draft
            "scheduledTime": schedule_time or datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"),
        }

        result = await session.call_tool("create_post", params)
        return result.content[0].text

async def get_weekly_analytics():
    """Get Bluesky follower and post counts."""
    async with get_session() as session:
        profile = await session.call_tool("profile_stats", {
            "platform": "bluesky",
            "platformId": "bluesky-did:plc:abc123"
        })
        return profile.content[0].text

async def schedule_content_calendar(posts: list):
    """Schedule a batch of posts with optimal timing."""
    results = []
    for post in posts:
        result = await post_to_all_platforms(
            content=post["content"],
            schedule_time=post["time"],
        )
        results.append(result)
    return results

# Example usage
async def main():
    # Post immediately to all platforms
    await post_to_all_platforms(
        "🚀 Exciting update: Our AI agent now supports 10 social platforms!"
    )

    # Schedule a week of content
    base = datetime.now(timezone.utc) + timedelta(days=1)  # tomorrow, in UTC
    calendar = [
        {
            "content": "Monday insight: AI is reshaping content creation.",
            "time": base.replace(hour=9, minute=0, second=0, microsecond=0).strftime("%Y-%m-%dT%H:%M:%SZ")
        },
        {
            "content": "Wednesday deep-dive: How we built our MCP integration.",
            "time": (base + timedelta(days=2)).replace(hour=14, minute=0, second=0, microsecond=0).strftime("%Y-%m-%dT%H:%M:%SZ")
        },
        {
            "content": "Friday wrap: This week in social media automation.",
            "time": (base + timedelta(days=4)).replace(hour=10, minute=0, second=0, microsecond=0).strftime("%Y-%m-%dT%H:%M:%SZ")
        },
    ]
    await schedule_content_calendar(calendar)

    # Check performance
    analytics = await get_weekly_analytics()
    print("Weekly performance:", analytics)

asyncio.run(main())

Using mcporter to Call Publora Tools Directly

OpenClaw's mcporter skill lets you call any Publora MCP tool directly from the command line — useful for scripting and automation:

# List all Publora tools
mcporter list --http-url https://mcp.publora.com --name publora --header "Authorization=Bearer sk_YOUR_API_KEY"

# List connected accounts (the "publora." commands below use the entry persisted in Step 1, Option A or B)
mcporter call publora.list_connections

# Create a post (scheduledTime must be a future UTC time; replace the placeholder)
mcporter call publora.create_post \
  content="Hello from mcporter!" \
  platforms='["linkedin-ABC123"]' \
  scheduledTime="2026-12-01T09:00:00Z"

# Get Bluesky follower counts
mcporter call publora.profile_stats platform=bluesky platformId=bluesky-did:plc:abc123

# Schedule a post (future UTC time; replace the placeholder)
mcporter call publora.create_post \
  content="Scheduled via CLI" \
  platforms='["linkedin-ABC123","twitter-123456789"]' \
  scheduledTime="2026-12-01T14:00:00Z"

Platform Quick Reference

Platform Character Limit Images Video Special
LinkedIn 3,000 Up to 10 30 min / 500 MB Documents (PDF up to 100 MB), multi-image posts
X (Twitter) 280 / 25,000* Up to 4 140s / 512 MB Auto-threading
Instagram 2,200 Up to 10 Reels 15 min / 300 MB, feed 60 min, carousel 60s Reels, Stories, carousels
Threads 500 Up to 20 5 min / 1 GB Auto-threading
TikTok 2,200 Up to 35 10 min / 4 GB Photo carousels
YouTube 100 title / 5,000 desc None (video only) 12 h / 256 GB Shorts (up to 3 min), custom thumbnails
Facebook 63,206 Up to 10 45 min / 2 GB Page posts, Reels (90s / 1 GB)
Bluesky 300 Up to 4 3 min / 100 MB Facets (links/mentions)
Mastodon 500* Up to 4 ~99 MB* Instance-configurable limits
Telegram 4,096 (1,024 captions) Up to 10 50 MB (Bot API) Markdown formatting

* X Premium / Mastodon varies by instance

Error Handling & Best Practices

When working with multiple platforms, handle failures gracefully:

// Robust cross-platform posting with error handling
const BASE = 'https://api.publora.com/api/v1';
const headers = { 'x-publora-key': 'sk_YOUR_API_KEY', 'Content-Type': 'application/json' };

async function postWithRetry(
  content,
  platforms,
  maxRetries = 2,
  idempotencyKey = crypto.randomUUID(),     // one key per logical post
  scheduledTime = new Date().toISOString(), // one timestamp per logical post
) {
  const response = await fetch(`${BASE}/create-post`, {
    method: 'POST',
    headers: { ...headers, 'Idempotency-Key': idempotencyKey },
    body: JSON.stringify({ content, platforms, scheduledTime }),
  });

  const result = await response.json();

  if (!response.ok) {
    // 429: rate limited; 409: the first attempt with this key is still in flight
    if ((response.status === 429 || response.status === 409) && maxRetries > 0) {
      const retryAfter = parseInt(response.headers.get('Retry-After') || '60');
      console.log(`Retrying in ${retryAfter}s...`);
      await new Promise(r => setTimeout(r, retryAfter * 1000));
      // Same key and same body (same timestamp): the retry replays, never duplicates
      return postWithRetry(content, platforms, maxRetries - 1, idempotencyKey, scheduledTime);
    }
    throw new Error(`Post failed: ${result.error || response.statusText}`);
  }

  // Later: check per-platform results
  const status = await fetch(`${BASE}/get-post/${result.postGroupId}`, { headers }).then(r => r.json());
  for (const platformPost of status.posts) {
    if (platformPost.status === 'failed') {
      console.warn(`Failed on ${platformPost.platform}`);
    } else {
      console.log(`✓ ${platformPost.platform}: ${platformPost.status}`);
    }
  }

  return result;
}

Also Works With Claude Desktop, Cursor, and More

The same Publora MCP server works with any MCP-compatible client — not just OpenClaw:

  • Claude Desktop — Settings → Developer → Edit Config
  • Claude Code — .mcp.json in project root or ~/.claude.json
  • Cursor — .cursor/mcp.json in project root
  • Windsurf — MCP settings panel
  • Any MCP client — Streamable HTTP transport to https://mcp.publora.com

The MCP config format is the same across all clients — just the config file location changes:

{
  "mcpServers": {
    "publora": {
      "type": "http",
      "url": "https://mcp.publora.com",
      "headers": {
        "Authorization": "Bearer sk_YOUR_API_KEY"
      }
    }
  }
}

What's Next

You now have everything you need to build an AI-powered social media management system. Here are some ideas to explore:

  • Content repurposing — Ask OpenClaw to take a blog post and create platform-specific versions for each network
  • Analytics-driven posting — Query your LinkedIn stats to find the best performing content types, then generate more of that
  • Automated engagement — Use LinkedIn reactions tools to engage with your network's content
  • Client workspaces — On the Agency plan, keep each client's accounts in an isolated workspace with role-based team access
  • Content calendar automation — Build a script that generates and schedules an entire month of content

Get started at publora.com — the free Starter plan includes full API and MCP access, and Pro is $5.99 per account per month, or $3.99 billed yearly. Read the full documentation at docs.publora.com/guides/mcp-server.