Bring your agent. Keep control of publishing.

Connect your AI agent for social media publishing

An ai agent for social media can turn a human’s brief into publishing requests, then check what happened. Postdom gives your existing agent tools to publish finished videos you supply to TikTok, Instagram Reels, YouTube Shorts, LinkedIn, Facebook Reels, X, Snapchat Spotlight, Threads and Bluesky, with approval and account limits controlled by a human.

You bring the agent and the finished video. Postdom does not generate video, manage an inbox, or promise audience growth.

What can an AI agent for social media do here?

Prepare a request

Read the workspace brief, select connected accounts and propose a caption or bounded publishing plan. Your agent supplies the judgment; Postdom supplies the tools.

Publish within permission

Submit your finished video for human review, or act within an already authorized plan or account policy. The agent cannot approve its own work or expand its authority.

Check the result

Read the post’s status and each destination’s outcome. Fetch available performance evidence without converting a missing value into zero.

This fits builders who already have an MCP-compatible agent and want to add short-form video publishing. If you need a content generator or an all-network social suite, this is not that product.

How do I connect my agent?

  1. Have a human prepare the workspace

    Create a workspace, complete social-account authorization, and create a workspace agent key in Postdom Accounts. Keep the key in private client settings or a protected environment. Never put it in chat, an operating brief or a repository.

  2. Configure the MCP connection

    Use the configuration shown in Accounts. The local package is @postdom/mcp@0.3.0 and requires Node.js 22 or newer. A client that can launch a local stdio MCP server runs the command below. Its settings format varies by client: Claude Code and Codex each register the server by running a command, while Cursor has no such command and reads a file you edit.

    Connection example for JSON-shaped MCP settings; replace the key privately
    {
      "mcpServers": {
        "postdom": {
          "command": "npx",
          "args": [
            "-y",
            "@postdom/mcp@0.3.0"
          ],
          "env": {
            "POSTDOM_API_KEY": "REPLACE_IN_PRIVATE_CLIENT_SETTINGS"
          }
        }
      }
    }

    The package defaults to https://api.postdom.com/v1. The example omits an API URL override. Check your client’s connection status and confirm the expected 13 tools are available before asking it to act.

    Claude Code’s MCP setup reference explains its local-server settings. This is setup guidance, not a claim that we tested your editor, account authorization or a live publish.

  3. Add the operating instructions separately

    AGENTS.md, CLAUDE.md and Cursor’s .cursor/rules/postdom.mdc describe how the agent should work. They are not the MCP connection settings. Add the brief below only after the connection works. ChatGPT project instructions alone cannot launch this local server; Postdom and ChatGPT covers what the brief does there and what it does not.

First run: submit a finished demo for review

Use a YouTube account for this example. A human explicitly selects L1 Post review before the agent submits anything. Do not assume that L1 is the account default. Confirm the account’s current policy and the exact caption, media and audience together.

Operating brief to adapt for your agent
Human-controlled first-run brief
Use only the Postdom connection I configured. Do not print credentials.
Read get_workspace_status, list_accounts and get_brief first. Stop if the workspace is paused, connections are locked, the account is disconnected, or policy is unclear.
I will explicitly set the selected account to L1 Post review before this request. Confirm the returned policy; do not assume a new account starts in L1.
Use only my selected providerAccountId and the finished video I supply. Show me the caption, account and all MCP defaults before submitting. Do not generate or upload a replacement video.
YouTube sends visibility: private, madeForKids: false and containsSyntheticMedia: true; its title comes from the caption's first line. TikTok sends privacy_level: SELF_ONLY, video_made_with_ai: true, content_preview_confirmed: true, express_consent_given: true, and allow_comment, allow_duet and allow_stitch: false. Instagram sends contentType: reel and isAiGenerated: true, with no equivalent private default. LinkedIn is sent no settings at all: the Posts API requires a visibility value, so LinkedIn sets one on the account's behalf, and Postdom neither chooses nor reads it. LinkedIn exposes no AI-disclosure field, so no disclosure is sent for it. Facebook is sent contentType: reel and nothing else, and exposes no AI-disclosure field on this path. X, Snapchat and Threads are sent no settings at all and expose no AI-disclosure field either; Snapchat additionally requires a Public Profile on the account before it can publish, Threads takes its audience from whether the profile is public or private rather than from anything sent with the post, and Bluesky posts are public because the post record has no visibility field at all.
These are submitted assertions, not evidence that human preview or consent happened. Require my actual preview of the supplied video and express consent before a TikTok request. Ask me to confirm that the audience and AI-disclosure settings truthfully fit this video for every selected destination. Stop if confirmation is absent or a setting is incompatible; the tool exposes no overrides for these settings. Do not infer consent from permission to call a tool.
After I authorize submission, call publish_video once with those exact inputs and a stable idempotency_key. Submission is not my approval to publish.
If the result requires approval, return its post ID and stop for human review. Never approve it yourself or change policy.
After human approval, use get_publish to check the same post ID. Use bounded backoff, and hand me the ID if my agreed waiting budget expires. Report each destination’s result; never call partial success complete.
Read get_performance only when appropriate. Preserve missing snapshots, null values and availability reasons. Do not resubmit or widen the audience without fresh human direction.

Read before you write

Read-only MCP calls; arguments are empty objects
get_workspace_status({})
list_accounts({})
get_brief({})

Stop if connections are locked, the workspace is paused or the chosen account is not connected. If authorization is needed, connect_account can start a handoff, but a human completes the social login. Do not claim success until the account appears in list_accounts.

Illustrative list_accounts item, not a real account
{
  "id": "internal-example-id",
  "providerAccountId": "example-youtube-account",
  "platform": "youtube",
  "handle": "example-channel",
  "status": "connected"
}

Use providerAccountId in account_ids, not the separate internal id. Keep the returned brief and follow its brand guidance. Ask the human before changing the selected account or supplied video.

Submit the agreed request once

Illustrative publish_video arguments; replace the example account and URL
publish_video({
  "account_ids": [
    "example-youtube-account"
  ],
  "video_url": "https://media.example.test/approved-demo.mp4",
  "caption": "A closer look at the demo\nThe finished walkthrough, reviewed by our team.",
  "intent": "Request human review of this supplied demo for the selected YouTube account",
  "idempotency_key": "demo-review-request-001"
})

The example URL is a placeholder, not a working video. For a stored handle, replace video_url with media_handle; supply exactly one. Omitted publish_at means this example does not request a future slot. For scheduling, agree the time with the human and supply its UTC timestamp; approval must still happen in time.

Illustrative L1 response excerpt, not proof of a live publish
{
  "id": "11111111-1111-4111-8111-111111111111",
  "status": "requires_approval",
  "message": "No provider request was made. Approve this exact immutable request."
}

Keep the returned post ID and hand it to the human. requires_approval means the request needs review; it is not a published video. The human reviews the exact immutable post through Postdom’s human approval workflow. Granting an agent permission to call a tool is not the same as approving the post.

Read the same post after human approval

Follow-up calls using the returned post ID
get_publish({ "post_id": "11111111-1111-4111-8111-111111111111" })
// Once publication has an outcome:
get_performance({ "post_id": "11111111-1111-4111-8111-111111111111" })

Agree a waiting budget and use bounded backoff for status reads. Return the ID and current state if that budget ends. A stable idempotency_key identifies the original request; do not replace it to work around a pending response or reuse it for changed content. After an uncertain response, reconcile the original request before creating another.

Example verification: the released package’s local stdio connection, tool discovery and calls were exercised against a local fixture API. No real workspace, OAuth login, provider upload or authenticated publication was performed. Responses here are illustrative excerpts, not real analytics or publication evidence.

What should the agent do with the result?

Read get_publish for post status. Check individual destination results too: a mixed outcome needs a different response from complete success.

Post statusNext action
draftA human must choose whether and when to publish the draft.
requires_approvalReturn the post ID. A human must review the exact post before it can proceed.
changes_requestedRead the feedback and return to the human; do not treat an edit as approval.
rejectedStop. Do not submit the rejected work under a new ID.
missed_approvalThe approval deadline passed. Ask the human to choose a new time or publish now explicitly.
missed_scheduleThe scheduled slot was missed. Ask the human how to recover; do not silently backfill.
scheduledCheck get_publish later with bounded backoff. Scheduled does not mean published.
publishingCheck the same post again within the agreed waiting budget; do not create a duplicate.
publishedInspect each destination result, then read get_performance. Publication does not guarantee metrics are ready.
partialSome destinations succeeded. Report every result and ask the human about recovery; do not replay successful destinations.
failedPreserve the error and post ID. Ask the human to resolve the cause before another attempt.
blockedStopped by policy before submission. Preserve the reason; a fresh request and authorization are required, not an automatic retry.
unknownThe provider may have received this run. Preserve its ID and evidence; do not retry while its outcome is being reconciled.

Performance is a separate read. An empty snapshot list is not zero views. Preserve null, the metric’s availability state and any reason. An estimable metric may still be null; a delayed state does not promise that a value will arrive. Use the destination metric availability reference before comparing accounts.

If you use plan review instead of post review

A plan is authorization for bounded work, not evidence that its posts published. Under L2, propose it with submit_plan, including the agreed accounts, time window, post allowance, objective and returned brief_version. Read get_plan; only approved lets the agent proceed within that plan’s remaining bounds. Attach its plan_id to the subsequent publish request.

  • requires_approval: Wait for human plan approval.
  • approved: Use only its authorized accounts, time window and post allowance; check policy again.
  • changes_requested: Return the requested changes to the human.
  • rejected: Stop this plan.
  • expired: Stop; its authorization window has ended.
  • cancelled: Stop; its authorization was withdrawn.

Read the scheduling and plan workflow.

Who decides how much the agent can do?

The human does. Workspace credentials do not let an agent approve work, create keys, change account policy, or resolve a human-only exception.

L0 · Manual

The agent creates a draft. A human chooses whether and when it publishes.

L1 · Post review

Each agent post waits for exact human approval before provider handoff.

L2 · Plan review

Posts flow only inside one approved plan covering the accounts, UTC window, and post maximum.

L3 · Bounded autonomy

Posts flow only inside the account's saved daily cap, visibility allowlist, and quiet hours.

The human can pause agent activity, revoke its key or change the account’s authority. Keep the first run on a deliberately chosen review setting; a prompt asking for caution is not a substitute for saved policy.

Questions before connecting

Does Postdom include an AI agent or generate videos?

Bring your own MCP-compatible agent and finished video. Postdom supplies publishing and outcome tools for TikTok, Instagram Reels, YouTube Shorts, LinkedIn, Facebook Reels, X, Snapchat Spotlight, Threads and Bluesky; it does not generate the video or replace your agent.

Can an agent publish without approving each post?

Only within the authority a human configures. L1 requires review of each post; L2 uses a human-approved bounded plan; L3 permits publishing within saved account policy. L0 keeps publication manual. An agent cannot grant itself approval or change these settings.

Will the MCP example publish publicly?

The released MCP tool sets YouTube to private with madeForKids: false and containsSyntheticMedia: true. TikTok uses privacy_level: SELF_ONLY and video_made_with_ai: true; allow_comment, allow_duet and allow_stitch are false. It also sends content_preview_confirmed: true and express_consent_given: true. Those flags assert preview and consent; they do not prove either happened. Require actual human preview and express consent before a TikTok request. Instagram uses contentType: reel and isAiGenerated: true, with no equivalent private default. LinkedIn receives no settings: it sets its own required visibility value, which Postdom neither chooses nor reads, and it exposes no AI-disclosure field, so none is sent. A human must confirm the audience and AI-disclosure settings fit the supplied video. Stop without confirmation or if a setting is incompatible: the tool exposes no overrides. Permission to call a tool is not consent or post approval, and an accepted request does not prove publication.

Can I connect by pasting the prompt into ChatGPT?

No. Instructions do not create a tool connection. ChatGPT project instructions can hold an operating brief, but live calls require a supported remote MCP connection. The local npx example is for clients that can launch a stdio MCP server, not ChatGPT project instructions.

Give your agent a reviewed first task

Prepare the finished video, choose the account and set its review policy. Then configure the connection and adapt the first-run brief above.

Implementation sources: released MCP package, released MCP code: arguments and destination defaults, run outcomes. Use the pinned version above; package README examples can lag the release. The current upload compatibility limitation above takes precedence over older upload examples.