Skip to main content
Glama
MrSagarShah

upload-post-mcp

by MrSagarShah
README.md
# upload-post-mcp

[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
[![Node >= 18](https://img.shields.io/badge/node-%3E%3D18-brightgreen)](package.json)
[![MCP](https://img.shields.io/badge/protocol-MCP-blueviolet)](https://modelcontextprotocol.io)
[![Hosted on Cloudflare Workers](https://img.shields.io/badge/hosted-Cloudflare%20Workers-f38020)](https://upload-post-mcp.sgr-flutter.workers.dev)
[![GitHub stars](https://img.shields.io/github/stars/MrSagarShah/upload-post-mcp?style=social)](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

A4/5.0

Scored across 17 tools

Disambiguation5/5

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.

Naming Consistency5/5

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.

Tool Count5/5

17 tools cover a broad but focused domain (social media posting, scheduling, analytics, account management). Each tool serves a necessary function without redundancy.

Completeness4/5

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.

Maintenance

ActivityStale
ResponsivenessNo issues