Skip to main content

Use Upload-Post with the OpenAI Agents SDK

The OpenAI Agents SDK can load tools from any remote MCP server. Point it at the hosted Upload-Post MCP server and your agent gets nearly 60 tools to publish, schedule and analyze posts on TikTok, Instagram, YouTube, LinkedIn, Facebook, X, Threads, Pinterest, Bluesky and more.

  • Endpoint: https://mcp.upload-post.com/mcp (Streamable HTTP)
  • Auth: Authorization: ApiKey <UPLOAD_POST_API_KEY>

The SDK offers two ways to use it:

OptionWhere tool calls runUse it when
MCPServerStreamableHttpYour process connects to the MCP serverAny model provider, full control over the connection
HostedMCPToolOpenAI's Responses API calls the serverYou use OpenAI Responses models and want fewer round trips

Installation​

pip install openai-agents

API key​

Generate a key in the Upload-Post dashboard under API Keys, connect your social accounts to a profile, then export it:

export UPLOAD_POST_API_KEY="your-upload-post-api-key"
export OPENAI_API_KEY="your-openai-api-key"

Example: Streamable HTTP server​

import asyncio
import os

from agents import Agent, Runner
from agents.mcp import MCPServerStreamableHttp


async def main() -> None:
async with MCPServerStreamableHttp(
name="Upload-Post",
params={
"url": "https://mcp.upload-post.com/mcp",
"headers": {"Authorization": f"ApiKey {os.environ['UPLOAD_POST_API_KEY']}"},
"timeout": 30,
},
cache_tools_list=True,
max_retry_attempts=3,
) as upload_post:
agent = Agent(
name="Social media manager",
instructions=(
"You publish social media posts through Upload-Post. Call list_users "
"first to find the profile and its connected accounts. After an upload, "
"poll get_status with the returned request_id until it finishes."
),
mcp_servers=[upload_post],
)
result = await Runner.run(
agent,
"List my Upload-Post profiles, then post 'Hello from the OpenAI Agents SDK!' "
"to X and LinkedIn from the first profile and tell me the final status.",
)
print(result.final_output)


asyncio.run(main())

To expose only a subset of tools, pass a filter:

from agents.mcp import create_static_tool_filter

MCPServerStreamableHttp(
name="Upload-Post",
params={...},
tool_filter=create_static_tool_filter(
allowed_tool_names=["list_users", "upload_text", "upload_video", "get_status"]
),
)

Example: hosted MCP tool​

With HostedMCPTool the OpenAI Responses API connects to Upload-Post for you. The API key travels in the headers field of the tool configuration.

import asyncio
import os

from agents import Agent, HostedMCPTool, Runner


async def main() -> None:
agent = Agent(
name="Social media manager",
instructions="Publish posts through Upload-Post and check their status with get_status.",
tools=[
HostedMCPTool(
tool_config={
"type": "mcp",
"server_label": "upload_post",
"server_url": "https://mcp.upload-post.com/mcp",
"headers": {"Authorization": f"ApiKey {os.environ['UPLOAD_POST_API_KEY']}"},
"require_approval": "never",
}
)
],
)
result = await Runner.run(
agent,
"Publish the video https://example.com/launch.mp4 to TikTok and Instagram "
"from my first Upload-Post profile with the caption 'We just launched!'.",
)
print(result.final_output)


asyncio.run(main())

Set "require_approval": "always" if you want a human to confirm each tool call before anything is published.

TypeScript​

The JavaScript SDK (npm install @openai/agents) has the same two options. MCPServerStreamableHttp takes the header through requestInit:

import { Agent, run, MCPServerStreamableHttp } from '@openai/agents';

const uploadPost = new MCPServerStreamableHttp({
name: 'Upload-Post',
url: 'https://mcp.upload-post.com/mcp',
requestInit: {
headers: { Authorization: `ApiKey ${process.env.UPLOAD_POST_API_KEY}` },
},
});

const agent = new Agent({
name: 'Social media manager',
instructions: 'Publish posts through Upload-Post and check their status with get_status.',
mcpServers: [uploadPost],
});

try {
await uploadPost.connect();
const result = await run(
agent,
"List my Upload-Post profiles and post 'Hello from the Agents SDK!' to X from the first one.",
);
console.log(result.finalOutput);
} finally {
await uploadPost.close();
}

For the hosted variant use hostedMcpTool({ serverLabel: 'upload_post', serverUrl: 'https://mcp.upload-post.com/mcp', headers: { Authorization: 'ApiKey ...' } }).

Uploads are asynchronous​

upload_video, upload_photos and upload_text return a request_id right away while the post is delivered to each platform in the background. The agent should call get_status with that request_id until it reports success or failure. Scheduled or queued posts return a job_id instead: check them with get_job_status or list_scheduled. See Async uploads.