socialmag v0.1 — 4/5 platforms live (Threads, FB, IG, TikTok)

This commit is contained in:
2026-09-10 21:10:55 +08:00
commit a4f33f456e
28 changed files with 2053 additions and 0 deletions
+193
View File
@@ -0,0 +1,193 @@
# 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
```json
{
"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
```json
{}
→ {"threads": true, "fb": true, "ig": true, "yt": true, "tiktok": true}
```
### 3. `get_status` — last post results
```json
{}
→ {"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