Files

6.4 KiB

socialmag — Social Media MCP Server

Proposal Draft · 2026-09-10

What

An MCP server that lets any household agent post to social media platforms via a single tool call. Uses bravemag's CDP connection (port 9222) to abang's logged-in Brave browser. No API keys, no OAuth dance, no monthly fees.

Architecture

┌─ Any Agent ─────────────────────┐
│ create_post(                    │
│   platforms: ["threads","fb"],  │
│   text: "Hello world 🚀",      │
│   media: "/path/to/img.jpg",   │  ← optional
│   schedule: null                │  ← future: cron/delay
│ )                               │
└─────────────┬───────────────────┘
              ↓
┌─ socialmag (MCP server) ────────┐
│  Python · stdio MCP interface   │
│  CDP client → ws://127.0.0.1:9222
│                                 │
│  Queue: sequential per-platform │
│  (one browser, one tab at a time)
│                                 │
│  ┌─ post_threads(text, media?)  │
│  ├─ post_facebook(text, media?) │
│  ├─ post_instagram(media, caption)
│  ├─ post_youtube(text)          │  ← community post
│  ├─ post_youtube_video(file, title, desc)
│  └─ post_tiktok(file, caption)  │
│                                 │
│  Returns: per-platform status   │
│  {threads: "ok", fb: "ok", ...} │
└─────────────────────────────────┘

MCP Tools (public interface)

1. create_post — the main tool

{
  "platforms": ["threads", "fb", "ig", "yt", "tiktok"],
  "text": "Post content here",
  "media": "/absolute/path/to/file.jpg",
  "visibility": "public"
}
  • platforms: array, pick any combo
  • text: required for threads/fb/yt. Used as caption for ig/tiktok
  • media: optional for threads/fb/yt. REQUIRED for ig/tiktok
  • visibility: "public" | "friends" (fb only)

2. check_login — verify which platforms are logged in

{}
→ {"threads": true, "fb": true, "ig": true, "yt": true, "tiktok": true}

3. get_status — last post results

{}
→ {"last_post": "2026-09-10T19:30:00", "results": {...}}

Per-Platform Posting Logic (from FAFO recon)

Threads ⭐

1. navigate("https://www.threads.net/")
2. click([aria-label="Empty text field. Type to compose a new post."])
3. wait for [role=dialog]
4. type into [role=dialog] [role=textbox]
5. if media: inject via CDP DOM.setFileInputFiles on "Attach media" flow
6. click "Post" button in dialog
7. wait for dialog close = success

Facebook ⭐⭐

1. navigate("https://www.facebook.com/")
2. JS: find span with "on your mind" → walk parent to [role=button] → click()
   ⚠️ Direct element click triggers Messenger!
3. wait for [role=dialog] containing "Create post"
4. type into dialog [role=textbox][contenteditable=true]
5. if media: click "Photo/video" → CDP setFileInputFiles
6. if visibility != "friends": click privacy button → change
7. click [aria-label="Post"]
8. wait for dialog close = success

Instagram ⭐⭐⭐⭐

1. navigate("https://www.instagram.com/")
2. click(svg[aria-label="New post"])
3. wait for "Create new post" dialog
4. CDP: DOM.setFileInputFiles on input[type=file] → inject media
   (bypasses native file picker)
5. wait for crop screen → click "Next"
6. wait for filter screen → click "Next"
7. wait for caption screen → type caption in textarea
8. click "Share"
9. wait for dialog close = success

YouTube (community post) ⭐⭐

1. navigate("https://www.youtube.com/")
2. click(button[aria-label="Create"])
3. click "Create post" in dropdown menu
4. wait for redirect to channel/posts page
5. type into #contenteditable-root
6. click button[aria-label="Post"]
7. wait for post to appear = success

TikTok ⭐⭐⭐⭐

1. navigate("https://www.tiktok.com/tiktokstudio/upload?from=upload")
2. wait for upload page
3. for video: CDP setFileInputFiles on input[type=file][accept="video/*"]
4. for photos: click "Photos" tab first, then upload
5. wait for processing
6. type caption/description
7. set hashtags, settings
8. click "Post" / "Publish"
9. wait for success confirmation

Tech Stack

  • Python 3 (stdlib-only server, same pattern as tiledmag/pixel-room-mcp)
  • CDP client: websockets library for WebSocket to Chrome DevTools
  • MCP interface: stdio (standard MCP pattern)
  • No framework: plain Python, no LangChain/FastAPI/etc
  • Systemd managed: socialmag.service, auto-restart

File Structure

/mnt/playground/Playground_V2/socialmag/
├── server.py          # MCP server + tool definitions
├── cdp.py             # CDP WebSocket client (navigate, click, type, setFiles)
├── platforms/
│   ├── threads.py     # Threads posting logic
│   ├── facebook.py    # Facebook posting logic
│   ├── instagram.py   # Instagram posting logic
│   ├── youtube.py     # YouTube posting logic
│   └── tiktok.py      # TikTok posting logic
├── selectors.py       # All platform selectors in one place
├── queue.py           # Sequential execution queue
└── README.md

Dependencies

  • websockets (for CDP WebSocket)
  • That's it. Everything else is stdlib.

Risks & Mitigations

Risk Mitigation
Platform UI changes break selectors selectors.py is one file — update and go
Bot detection (especially TikTok) Human-like delays between actions (random 0.5-2s)
Browser not logged in check_login tool verifies before posting
Brave restart kills CDP Health check + clear error message
Rate limiting Queue with configurable delay between platforms
Media file not found Validate path exists before starting
Multi-step IG/TikTok flow fails mid-way Per-step error handling, screenshot on failure

Future (not now)

  • Schedule posts (cron integration)
  • Analytics reading (pull post performance)
  • Reply/DM automation
  • Multi-account support
  • Template system ("post this format every Monday")

Build Order

  1. CDP client (cdp.py) — navigate, click, type, setFiles
  2. Threads posting (simplest, validates the pattern)
  3. Facebook posting
  4. YouTube community post
  5. Instagram posting (media flow)
  6. TikTok posting (media flow)
  7. MCP server wrapper (server.py)
  8. Queue + error handling
  9. systemd service