upload-post-mcp
# upload-post-mcp
[](LICENSE)
[](package.json)
[](https://modelcontextprotocol.io)
[](https://upload-post-mcp.sgr-flutter.workers.dev)
[](https://github.com/MrSagarShah/upload-post-mcp/stargazers)
An MCP (Model Context Protocol) server that lets Claude — or any MCP client — post to social media via [upload-post.com](https://www.upload-post.com/): text, photos, and videos across **13 platforms**: TikTok, Instagram, LinkedIn, YouTube, Facebook, X, Threads, Pinterest, Bluesky, Reddit, Discord, Telegram, and Google Business Profile.
Unlike scheduler-specific connectors (e.g. Buffer's), this publishes **directly** to your connected accounts — no Buffer subscription, and it covers platforms most connectors don't (TikTok video, YouTube, Reddit, Google Business), plus scheduling, queues, analytics, and Instagram comment/DM replies.
## 🚀 Try it in 2 minutes (no install)
A hosted instance is live — connect it straight from your Claude settings:
1. **claude.ai (web) / Claude Desktop / mobile**: Settings → **Connectors** → **Add custom connector**
- Name: `Upload-Post`
- URL: `https://upload-post-mcp.sgr-flutter.workers.dev/mcp`
- Leave the OAuth fields empty → **Add**
2. Claude opens a consent page — paste your [upload-post API key](https://app.upload-post.com/api-keys) once (free account: 10 posts/month, no card)
3. In a chat, try: *"verify my upload-post account"*, then *"post 'hello from Claude' to my X"*
**Claude Code**: `claude mcp add --transport http upload-post https://upload-post-mcp.sgr-flutter.workers.dev/mcp`
Ships in two flavors from this repo:
| | Local (stdio) — repo root | Hosted (remote) — [`worker/`](worker/) |
|---|---|---|
| Runs | on your machine | on Cloudflare Workers |
| Works in | Claude Code, Claude Desktop, Cursor... | claude.ai (web), Claude Desktop & mobile via Settings → Connectors |
| Auth | `UPLOAD_POST_API_KEY` env var | OAuth 2.1 — users paste their API key once on a consent page; stored encrypted |
| Media | local file paths **or** URLs | public URLs only |
| Live instance | — | `https://upload-post-mcp.sgr-flutter.workers.dev/mcp` |
## Quick start
1. **Get an API key**: create an account at [app.upload-post.com](https://app.upload-post.com), create a *profile*, connect your social accounts to it, and generate an API key (Settings → API Keys). Free tier: 10 uploads/month.
2. **Add to Claude Code**:
```bash
claude mcp add upload-post --scope user \
--env UPLOAD_POST_API_KEY=YOUR_KEY_HERE \
-- npx -y upload-post-mcp
```
**Claude Desktop** (`claude_desktop_config.json`):
```json
{
"mcpServers": {
"upload-post": {
"command": "npx",
"args": ["-y", "upload-post-mcp"],
"env": { "UPLOAD_POST_API_KEY": "YOUR_KEY_HERE" }
}
}
}
```
3. **Test**: ask Claude to *"verify my upload-post account"*. It should return your account email and plan. Then try *"post 'hello world' to my X account"*.
### From source
```bash
git clone https://github.com/MrSagarShah/upload-post-mcp.git
cd upload-post-mcp && npm install && npm run build
claude mcp add upload-post --scope user \
--env UPLOAD_POST_API_KEY=YOUR_KEY_HERE \
-- node "$(pwd)/dist/index.js"
```
## Tools (17)
| Tool | Purpose |
|---|---|
| `post_text` | Text posts (X, LinkedIn, Facebook, Threads, Reddit, Bluesky, Discord, Telegram, GBP) |
| `post_photos` | Photos/carousels — local file paths or URLs |
| `post_video` | Videos (Reels, Shorts, TikToks...) — local file path or URL |
| `get_upload_status` | Poll async uploads (`request_id`) or scheduled jobs (`job_id`) |
| `get_history` | Paginated upload history |
| `list_scheduled_posts` / `edit_scheduled_post` / `cancel_scheduled_post` | Manage scheduled posts |
| `get_profile_analytics` | Followers/reach/likes/etc. per platform |
| `list_media` | Recent posts on a connected platform account |
| `get_comments` / `reply_to_comment` | Instagram comments + private DM replies |
| `verify_account` | Validate the API key, show plan |
| `list_page_targets` | Facebook pages / LinkedIn org pages / Pinterest boards (for required IDs) |
| `list_profiles` / `create_profile` / `generate_connect_link` | Manage upload-post profiles and link social accounts |
All publish tools support `scheduled_date` + `timezone`, `add_to_queue`, `async_upload`, `first_comment`, and an `extra_params` passthrough for any platform-specific field in the [upload-post API docs](https://docs.upload-post.com/) (X polls, YouTube tags/privacy, Instagram REELS/STORIES, TikTok privacy, and more).
Scheduling runs on upload-post's servers — schedule posts and close your laptop; they publish on time.
Publish calls send an `Idempotency-Key` automatically, so a retried request won't double-post.
## Example prompts
- *"Post 'We're hiring!' to my LinkedIn and X"*
- *"Schedule this for Friday 9am New York time on LinkedIn"*
- *"Post these three photos as an Instagram carousel with caption ..."*
- *"Upload ~/Videos/demo.mp4 to YouTube as unlisted and TikTok"*
- *"How did my last week's posts perform on X?"*
- *"Reply to the latest comments on my Instagram reel"*
## Notes
- The `user` argument on posting tools is your upload-post **profile** name (see `list_profiles`), not your account email.
- Facebook needs `facebook_page_id`, Pinterest needs `pinterest_board_id`, Reddit needs `subreddit` — use `list_page_targets` to find IDs.
- Media parameters accept either a local file path or a public `http(s)://` URL (hosted connector: URLs only).
## Troubleshooting
| Symptom | Cause / fix |
|---|---|
| `401: Invalid API key format` | The key in your env/consent page is wrong or a placeholder — regenerate at [app.upload-post.com/api-keys](https://app.upload-post.com/api-keys). |
| `429 — monthly quota exhausted` | Free tier is 10 uploads/month; the error includes your usage counters. Upgrade or wait for reset. |
| "must be a public http(s) URL" (hosted) | The hosted connector can't read files on your machine. Use a public URL, or switch to the local connector for file uploads. |
| Facebook/Pinterest/Reddit post rejected | Missing `facebook_page_id` / `pinterest_board_id` / `subreddit` — ask Claude to run `list_page_targets` first. |
| Connector missing after adding in claude.ai | Enable it per-chat via the tools (sliders) menu, and check Settings → Connectors shows it as connected. |
| Nothing posts to a platform | That platform isn't linked to the profile — ask Claude for a `generate_connect_link` and link it in the browser. |
## Roadmap
- [x] Local stdio connector (17 tools)
- [x] Hosted remote connector — OAuth 2.1 + Streamable HTTP on Cloudflare Workers
- [ ] npm package (`npx -y upload-post-mcp`)
- [ ] Anthropic connector directory listing
- [ ] LinkedIn document posts, auto-DM monitors, queue-settings tools
- [ ] Managed tier: connect socials directly, no upload-post account needed
## Contributing & support
Issues and PRs welcome — [open an issue](https://github.com/MrSagarShah/upload-post-mcp/issues) for bugs or tool requests. For anything else: saumil@tempbutton.com.
If this saved you time, a ⭐ helps others find it.
> **Disclaimer**: community project, not affiliated with or endorsed by Upload-Post. Your API key is yours; the hosted instance stores it encrypted and only forwards your own requests ([privacy](https://upload-post-mcp.sgr-flutter.workers.dev/privacy)).
## License
[MIT](LICENSE)
TDQS
Scored across 17 tools
Each tool targets a distinct action on a specific resource (e.g., post_photos vs post_video, cancel_scheduled_post vs edit_scheduled_post). There is no functional overlap, making it easy for an agent to select the correct tool.
All tool names follow a consistent verb_noun pattern with underscores (e.g., list_profiles, get_upload_status). No mixing of conventions, which enhances predictability.
17 tools cover a broad but focused domain (social media posting, scheduling, analytics, account management). Each tool serves a necessary function without redundancy.
The set covers core workflows: account linking, posting (photo/video/text), scheduling, commenting, analytics, and history. Minor gaps like missing a tool to delete a published post or update a profile, but overall comprehensive.