Upload-Post
OfficialThe Upload-Post server enables AI agents to publish, schedule, analyze, and manage social media content across 15+ platforms via a single API key.
Publishing & Uploading
Upload videos, photos/carousels, text posts, and documents (PDF, PPT, DOCX for LinkedIn) to platforms including TikTok, Instagram, YouTube, LinkedIn, Facebook, Pinterest, Threads, Reddit, Bluesky, X, Google Business, Discord, Telegram, Mastodon, WordPress, and more.
Open Upload Studio — a browser-based UI for staging and publishing locally attached video files (useful in ChatGPT/Claude).
Scheduling & Queue
Schedule posts for future publication, list/edit/cancel scheduled posts.
Configure queue settings (slots, timezone, days of week, max posts per slot) and preview upcoming queue slots.
Status & History
Poll async upload status by
request_idand scheduled job status byjob_id.Browse paginated upload history and retrieve recent media from connected accounts.
Analytics
Get aggregated profile analytics (followers, views, engagement), total impressions for date ranges, per-post analytics, and a reference of available platform metrics.
Media Staging
Create short-lived upload URLs for direct browser PUT, then complete or delete staged uploads.
FFmpeg Video Processing
Submit FFmpeg jobs for trimming, transcoding, watermarking, and thumbnail extraction; poll job status, download results, and check monthly quota usage.
User & Profile Management
Validate API keys, list/create/delete Upload-Post profiles, and generate/validate JWTs for white-label social connection flows.
Platform-Specific Utilities
List connected Facebook Pages, LinkedIn Pages, Pinterest Boards, and Google Business locations; get detailed Reddit post metadata (subreddit/flair).
Comments & DMs
Get Instagram post comments, reply publicly or privately via DM, send direct messages, list DM conversations, and manage AutoDM monitors (start, stop, pause, resume, delete, view logs).
Allows publishing, scheduling, analyzing, and managing posts on Bluesky.
Allows publishing, scheduling, analyzing, and managing posts on Discord, including sending DMs and managing conversations.
Allows publishing, scheduling, analyzing, and managing posts on Facebook, including managing Facebook pages.
Provides tools to submit FFmpeg video processing jobs, monitor their status, and download results.
Allows publishing, scheduling, analyzing, and managing posts on Instagram, including video and photo uploads.
Allows publishing, scheduling, analyzing, and managing posts on Pinterest, including managing boards.
Allows publishing, scheduling, analyzing, and managing posts on Reddit, including detailed post management.
Allows publishing, scheduling, analyzing, and managing posts on Telegram.
Allows publishing, scheduling, analyzing, and managing posts on Threads.
Allows publishing, scheduling, analyzing, and managing posts on TikTok, including video uploads.
Allows publishing, scheduling, analyzing, and managing videos on YouTube.
@upload-post/mcp
Official Model Context Protocol (MCP) server for Upload-Post.
Lets any MCP-compatible AI agent (Claude Desktop, Claude Code, Cursor, …) publish, schedule, analyze and manage social media across TikTok, Instagram, YouTube, LinkedIn, Facebook, Pinterest, Threads, Reddit, Bluesky, X, Google Business, Discord, Telegram and more with a single API key.
Built on top of the official
upload-postSDK and the public Upload-Post REST API.
Two ways to use it
A) Local stdio (single-user) — simplest
The server runs on your machine, spawned by the MCP client. Add to ~/.claude/mcp.json (or Cursor settings, etc.):
{
"mcpServers": {
"upload-post": {
"command": "npx",
"args": ["-y", "@upload-post/mcp"],
"env": { "UPLOAD_POST_API_KEY": "YOUR_API_KEY" }
}
}
}Get your API key at https://app.upload-post.com → API Keys. Restart the client — you should see 50 upload-post tools.
B) Hosted HTTP (multi-tenant) — share one server with many users
Run the server on any Docker-capable host (Fly, Railway, Cloud Run, your own box…) and let each user connect with their own Upload-Post API key. The server stores nothing per user.
{
"mcpServers": {
"upload-post": {
"url": "https://mcp.your-domain.com/mcp",
"headers": {
"Authorization": "ApiKey YOUR_OWN_UPLOAD_POST_API_KEY"
}
}
}
}Authorization: Bearer <key> is also accepted, for clients that only allow Bearer.
Related MCP server: publer-mcp-server
What can the agent do?
The server exposes Upload-Post API tools plus one ChatGPT App UI launcher.
Group | Tools |
Upload |
|
Media staging |
|
Status |
|
Schedule |
|
Analytics |
|
Users |
|
Pages/boards |
|
Comments |
|
DMs |
|
FFmpeg |
|
Queue |
|
Async uploads return a request_id. The agent should poll get_status until success: true.
get_media and get_cached_post_analytics are cursor-paginated: feed the response's next_cursor back as cursor until has_more is false. LinkedIn, Discord and Telegram do not support media cursors and accept limit only. Prefer get_cached_post_analytics over get_post_analytics when scanning many posts — it replays previously fetched results and so avoids the live analytics rate limit of 100 requests / 5 minutes. Only contains posts previously fetched through a live per-post endpoint; there is no background refresh, so captured_at is the last time that post was read live.
FFmpeg jobs accept one public URL through input_url or multiple URLs through files. Poll get_ffmpeg_job until completion, then call download_ffmpeg_result; it returns the result URL without streaming the processed binary through MCP.
ChatGPT video upload UI
open_upload_studio renders a ChatGPT Apps component for file-based video publishing. The widget creates a short-lived Upload-Post/R2 staging upload, PUTs the local video directly to R2, completes the upload, then calls upload_video with the returned temporary media URL.
The staging object is deleted after 24 hours whether it is used or not. Scheduled/queued posts remain safe because upload_video copies the temporary URL into the existing durable scheduler storage before execution.
Claude and other MCP clients can use the same flow without the ChatGPT UI: call create_media_upload, PUT the file to upload_url, call complete_media_upload, then pass media_url to upload_video.
Set UPLOAD_POST_R2_CONNECT_DOMAINS on the MCP host to the comma-separated origins used by the backend's R2 signed URLs when they differ from the defaults (for example https://<account>.r2.cloudflarestorage.com,https://<bucket>.<account>.r2.cloudflarestorage.com) so the ChatGPT component CSP allows the browser PUT.
The R2 bucket CORS policy must allow browser uploads. A restrictive policy can include your actual widget origin; for fastest validation, use:
[
{
"AllowedOrigins": ["*"],
"AllowedMethods": ["PUT", "GET", "HEAD"],
"AllowedHeaders": ["*"],
"ExposeHeaders": ["ETag"],
"MaxAgeSeconds": 3600
}
]Local / development
git clone https://github.com/Upload-Post/upload-post-mcp.git
cd upload-post-mcp
npm install
npm run build
# stdio (default — used by Claude Desktop, Cursor)
UPLOAD_POST_API_KEY=... node dist/index.js
# HTTP streamable (for hosted deployments)
UPLOAD_POST_API_KEY=... node dist/index.js --http --port 8080Inspect the live tool surface with the official inspector:
npx @modelcontextprotocol/inspector node dist/index.jsConfiguration
Env var | Mode | Default | Description |
| stdio | — (required) | Single user's Upload-Post API key. Ignored in |
| both |
| Override for self-hosted / staging. |
| http |
| Port for |
| http | Current Upload-Post challenge token | Optional override for ChatGPT Apps domain verification at |
CLI flags:
--http— start the streamable HTTP transport instead of stdio--port <n>— port for HTTP mode
HTTP endpoints:
POST /mcp— JSON-RPC over MCP streamable HTTP. RequiresAuthorization: ApiKey <key>(orBearer <key>) on every request. The key is the user's own Upload-Post API key; the server uses it only for that session and stores nothing.GET /healthz— liveness probe, always open. Returns{"ok":true}.
Auth model in --http mode is the same pattern Resend, Tavily, Brave Search and other API-key-native services use for their hosted MCPs: the upstream key is the auth.
Deploy with Docker
The repo ships with a multi-stage Dockerfile and a .dockerignore. On any Docker-capable PaaS (Fly.io, Railway, Render, Cloud Run, fly machines, your own box…):
Point the PaaS at this repo and select Dockerfile as the build pack.
Port: 8080 (matches
EXPOSE 8080).Environment variables: none are required. Optionally set
UPLOAD_POST_BASE_URLif you point at staging.Health check path:
/healthz(HTTP, port 8080).Domain: attach a domain, e.g.
mcp.your-domain.com, and provision TLS (most PaaS do this automatically via Let's Encrypt).
Deploy. The server is now ready for any number of users. Each user adds the endpoint to their MCP client config with their own Upload-Post API key:
{
"mcpServers": {
"upload-post": {
"url": "https://mcp.your-domain.com/mcp",
"headers": {
"Authorization": "ApiKey USER_OWN_UPLOAD_POST_API_KEY"
}
}
}
}Without an
Authorizationheader the server returns401. The header is the only credential — invalid Upload-Post keys will surface as upstream errors on the first tool call.
Local test of the production image:
docker build -t upload-post-mcp .
docker run --rm -p 8080:8080 upload-post-mcp
curl http://localhost:8080/healthz # → {"ok":true}
curl -i -X POST http://localhost:8080/mcp \
-H "content-type: application/json" \
-d '{}' # → 401 (no Authorization)Tips for prompting the agent
Prefer public URLs over local paths when uploading — local paths only work if the MCP server runs on the user's machine.
In ChatGPT Apps, prefer
open_upload_studiofor user-selected video files. It avoids local-path handoff issues by uploading to short-lived Upload-Post/R2 staging, then passing a temporary media URL toupload_video.To send video bytes directly (a client that holds the file rather than a URL), pass
videoBase64toupload_videoinstead ofvideoPathOrUrl. The server writes it to a temp file, uploads, then deletes it. Inline bytes are capped atUPLOAD_POST_MAX_INLINE_MB(default 100 MB) — for larger videos use a public URL.Always create the profile first (
create_user) and connect socials in the Upload-Post dashboard before publishing.For scheduled posts, pass ISO 8601 dates with timezone, e.g.
"2026-12-25T10:00:00Z"+"timezone": "Europe/Madrid".
Privacy & data handling
This server is a stateless proxy to the Upload-Post API. Per request, the only data it processes is the user's API key (or OAuth access token resolved to one) and the arguments of the tool call being executed. No user data is persisted by the MCP container itself.
What we receive per request: the
Authorizationheader, the MCP tool name + arguments, and any media URLs/paths the agent passes.What we forward: the tool arguments to the Upload-Post API on behalf of the authenticated user.
What we store: nothing per-user. OAuth tokens are stored upstream in the Upload-Post backend, hashed (SHA-256), so a breach of token storage cannot impersonate users.
What we log: HTTP method, path, status code, and an opaque request ID. No tool arguments, no API keys, no tokens.
Full Upload-Post privacy policy (data collection, retention, third-party sharing, contact, GDPR/CCPA): https://upload-post.com/privacy
To revoke a connector's access at any time, open Connected Apps in app.upload-post.com.
Security
All traffic is TLS-terminated at the edge (HTTPS only).
/mcprequires a validAuthorizationheader on every request; OAuth access tokens are short-lived (1 h access + 90 d refresh with rotation per RFC 6749 §10.4).The server validates the
Originheader against an allow-list (claude.ai,claude.com,chatgpt.com,chat.openai.com,app.upload-post.com,localhost) to mitigate DNS-rebinding attacks from browser-based clients. Extend withOAUTH_EXTRA_ALLOWED_ORIGINS(comma-separated) when self-hosting behind a custom dashboard.If ChatGPT shows
redirect_uri not on allow-listduring OAuth, add the exactredirect_urifrom the failing authorize request to the Upload-Post backend OAuth redirect allow-list. For ChatGPT clients this is typically onhttps://chatgpt.com/.../oauth/callbackorhttps://chat.openai.com/.../oauth/callback.OAuth redirect callbacks are pre-allowed for: Claude (claude.ai/claude.com), ChatGPT, Cursor, VS Code (stable + Insiders), Smithery, Glama, Toolhouse, Perplexity (standard + Enterprise), Mistral Studio debugger and Postman — plus any
http://localhost/loopback redirect (RFC 8252), which covers Claude Code, Windsurf, Cline, Continue, Goose, Gemini CLI and othermcp-remote-style clients. Platforms without a documented fixed callback (e.g. Grok, Le Chat production) are added on request.All tools declare MCP
readOnlyHint/destructiveHintannotations so clients can surface confirmation prompts for destructive operations.
Report a security issue: info@upload-post.com (encrypted PGP available on request).
License
MIT © Upload-Post
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/Upload-Post/upload-post-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server