Skip to main content

Use Upload-Post with LlamaIndex

LlamaIndex turns MCP server tools into regular LlamaIndex tools with the llama-index-tools-mcp package. 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>

Installation​

pip install llama-index-tools-mcp llama-index-llms-openai

API key​

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

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

Example​

import asyncio
import os

from llama_index.core.agent.workflow import FunctionAgent
from llama_index.llms.openai import OpenAI
from llama_index.tools.mcp import BasicMCPClient, McpToolSpec


async def main() -> None:
client = BasicMCPClient(
"https://mcp.upload-post.com/mcp",
headers={"Authorization": f"ApiKey {os.environ['UPLOAD_POST_API_KEY']}"},
)
tool_spec = McpToolSpec(
client=client,
# Optional: expose only the tools this agent needs.
allowed_tools=["list_users", "upload_text", "upload_video", "get_status"],
)
tools = await tool_spec.to_tool_list_async()

agent = FunctionAgent(
tools=tools,
llm=OpenAI(model="gpt-4.1"),
system_prompt=(
"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."
),
)

response = await agent.run(
"List my Upload-Post profiles, then post 'Hello from LlamaIndex!' to X and "
"LinkedIn from the first profile and tell me the final status."
)
print(response)


asyncio.run(main())

Drop allowed_tools to load every tool the server exposes.

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.